146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown/*
246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * Copyright (C) 2010 The Android Open Source Project
346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown *
446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * you may not use this file except in compliance with the License.
646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * You may obtain a copy of the License at
746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown *
846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown *
1046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * Unless required by applicable law or agreed to in writing, software
1146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
1246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * See the License for the specific language governing permissions and
1446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * limitations under the License.
1546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown */
1646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
174532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brownpackage com.android.server.input;
1846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
195660fad79808c6d1823a7135b283003b0947773aYohei Yukawaimport android.annotation.NonNull;
20b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawaimport android.annotation.Nullable;
2123cbe85610f780134cc77dd4a54732a22ed6e86eYohei Yukawaimport android.os.LocaleList;
22354736e196ff79962b3ddb52619a674044d773e2Dianne Hackbornimport android.os.ShellCallback;
239918234dcf9e115560144d0218682dd5050843bcAdrian Roosimport android.util.Log;
24ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brownimport android.view.Display;
25d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wrightimport com.android.internal.inputmethod.InputMethodSubtypeHandle;
26282cfefea0fbbd299839e353e6d30affdcd4a55cChris Wrenimport com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
27af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitschimport com.android.internal.notification.SystemNotificationChannels;
2839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wrightimport com.android.internal.os.SomeArgs;
29cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brownimport com.android.internal.R;
30fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport com.android.internal.util.DumpUtils;
31b004b5137e12bffae9a3d3ae97440c8c24bdc07aMichael Wrightimport com.android.internal.util.Preconditions;
3246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport com.android.internal.util.XmlUtils;
334ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brownimport com.android.server.DisplayThread;
344ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brownimport com.android.server.LocalServices;
3589ef0720ee8e0ac6ae1758faa917e4d6c9606fb4Jeff Brownimport com.android.server.Watchdog;
3646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
3746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport org.xmlpull.v1.XmlPullParser;
3846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
39a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brownimport android.Manifest;
40cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brownimport android.app.Notification;
41cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brownimport android.app.NotificationManager;
42cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brownimport android.app.PendingIntent;
435bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brownimport android.bluetooth.BluetoothAdapter;
445bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brownimport android.bluetooth.BluetoothDevice;
456ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brownimport android.content.BroadcastReceiver;
469f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.ComponentName;
4746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport android.content.Context;
489f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.Intent;
496ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brownimport android.content.IntentFilter;
509f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.pm.ActivityInfo;
518ebac231966e27364e5d463b63540a0527d40c4bMichael Wrightimport android.content.pm.ApplicationInfo;
52349703effce5acc53ed96f7ed8556131f0c65e18Jeff Brownimport android.content.pm.PackageManager;
539f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.pm.ResolveInfo;
549f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.pm.PackageManager.NameNotFoundException;
559f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.res.Resources;
566ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brownimport android.content.res.Resources.NotFoundException;
579f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.res.TypedArray;
589f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.res.XmlResourceParser;
591a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brownimport android.database.ContentObserver;
604ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brownimport android.hardware.display.DisplayViewport;
61af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.hardware.input.IInputDevicesChangedListener;
62c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganovimport android.hardware.input.IInputManager;
63fb290df3c9a6f37ec050163029e25844de2f8590RoboErikimport android.hardware.input.InputDeviceIdentifier;
64ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.hardware.input.InputManager;
654ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brownimport android.hardware.input.InputManagerInternal;
6639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wrightimport android.hardware.input.ITabletModeChangedListener;
679f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.hardware.input.KeyboardLayout;
68d6396d67201fb2b64d13070324bb115c9c23b08aJason Gereckeimport android.hardware.input.TouchCalibration;
694532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brownimport android.os.Binder;
709f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.os.Bundle;
7146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport android.os.Environment;
724532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brownimport android.os.Handler;
73af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.IBinder;
74a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brownimport android.os.Looper;
75af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.Message;
7605dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brownimport android.os.MessageQueue;
77ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.Process;
78af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.RemoteException;
79d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wrightimport android.os.ResultReceiver;
80d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wrightimport android.os.ShellCommand;
8150cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackbornimport android.os.UserHandle;
821a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brownimport android.provider.Settings;
831a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brownimport android.provider.Settings.SettingNotFoundException;
840748342d2ed264c01384fbaa4446a702a8824813Michael Wrightimport android.text.TextUtils;
8546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport android.util.Slog;
86af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.util.SparseArray;
8746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport android.util.Xml;
88c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganovimport android.view.IInputFilter;
89c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganovimport android.view.IInputFilterHost;
903787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheevimport android.view.IWindow;
9146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport android.view.InputChannel;
928d60866e2100db70ecf0502c14768a384514d7e9Jeff Brownimport android.view.InputDevice;
936ec402b5ae33c8927694d8522b4cc6a5c8ba974eJeff Brownimport android.view.InputEvent;
941f2451007c660091b7b090c1ea332f9044515d2dJeff Brownimport android.view.KeyEvent;
952352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownimport android.view.PointerIcon;
96d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gereckeimport android.view.Surface;
97a454767b09ecb7d25d00beae0e5a1fdd48605c63Jeff Brownimport android.view.ViewConfiguration;
980029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownimport android.view.WindowManagerPolicy;
99b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawaimport android.view.inputmethod.InputMethodInfo;
100b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawaimport android.view.inputmethod.InputMethodSubtype;
10146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
10246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport java.io.File;
1034532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brownimport java.io.FileDescriptor;
10446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport java.io.FileNotFoundException;
10546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport java.io.FileReader;
1069918234dcf9e115560144d0218682dd5050843bcAdrian Roosimport java.io.FileWriter;
10746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport java.io.IOException;
1086ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brownimport java.io.InputStreamReader;
10946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport java.io.PrintWriter;
11046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport java.util.ArrayList;
1110748342d2ed264c01384fbaa4446a702a8824813Michael Wrightimport java.util.Collections;
1129f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport java.util.HashMap;
113cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brownimport java.util.HashSet;
11439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wrightimport java.util.List;
1150748342d2ed264c01384fbaa4446a702a8824813Michael Wrightimport java.util.Locale;
116a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown
1179918234dcf9e115560144d0218682dd5050843bcAdrian Roosimport libcore.io.IoUtils;
1186ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brownimport libcore.io.Streams;
119a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brownimport libcore.util.Objects;
12046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
12146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown/*
12246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * Wraps the C++ InputManager and provides its callbacks.
12346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown */
124d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brownpublic class InputManagerService extends IInputManager.Stub
1254ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown        implements Watchdog.Monitor {
12646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    static final String TAG = "InputManager";
1271b9ba578f1d2acf86c75110e89ae3d2e0434483aJeff Brown    static final boolean DEBUG = false;
1284532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
1294532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
1304532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
131af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final int MSG_DELIVER_INPUT_DEVICES_CHANGED = 1;
132cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 2;
133cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 3;
134cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 4;
135cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private static final int MSG_RELOAD_DEVICE_ALIASES = 5;
13639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private static final int MSG_DELIVER_TABLET_MODE_CHANGED = 6;
137b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa    private static final int MSG_INPUT_METHOD_SUBTYPE_CHANGED = 7;
138af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1394532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Pointer to native input manager service object.
1407e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private final long mPtr;
141b699726018a0049665d8ad6b90dbc5af0e18f135Jeff Brown
14246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    private final Context mContext;
143af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final InputManagerHandler mHandler;
144a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown
1459918234dcf9e115560144d0218682dd5050843bcAdrian Roos    private final File mDoubleTouchGestureEnableFile;
1469918234dcf9e115560144d0218682dd5050843bcAdrian Roos
147a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown    private WindowManagerCallbacks mWindowManagerCallbacks;
1482f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    private WiredAccessoryCallbacks mWiredAccessoryCallbacks;
1496ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    private boolean mSystemReady;
150cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private NotificationManager mNotificationManager;
151af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
15239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private final Object mTabletModeLock = new Object();
15339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    // List of currently registered tablet mode changed listeners by process id
15439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private final SparseArray<TabletModeChangedListenerRecord> mTabletModeChangedListeners =
15539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            new SparseArray<>(); // guarded by mTabletModeLock
15639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private final List<TabletModeChangedListenerRecord> mTempTabletModeChangedListenersToNotify =
15739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            new ArrayList<>();
15839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
159a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown    // Persistent data store.  Must be locked each time during use.
160a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown    private final PersistentDataStore mDataStore = new PersistentDataStore();
161af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
162af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    // List of currently registered input devices changed listeners by process id.
163af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private Object mInputDevicesLock = new Object();
164af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private boolean mInputDevicesChangedPending; // guarded by mInputDevicesLock
165af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private InputDevice[] mInputDevices = new InputDevice[0];
166af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final SparseArray<InputDevicesChangedListenerRecord> mInputDevicesChangedListeners =
167af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            new SparseArray<InputDevicesChangedListenerRecord>(); // guarded by mInputDevicesLock
168af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final ArrayList<InputDevicesChangedListenerRecord>
169af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mTempInputDevicesChangedListenersToNotify =
170af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    new ArrayList<InputDevicesChangedListenerRecord>(); // handler thread only
171cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private final ArrayList<InputDevice>
172cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            mTempFullKeyboards = new ArrayList<InputDevice>(); // handler thread only
173cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private boolean mKeyboardLayoutNotificationShown;
174d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    private InputMethodSubtypeHandle mCurrentImeHandle;
175af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
176a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    // State for vibrator tokens.
177a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    private Object mVibratorLock = new Object();
178a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    private HashMap<IBinder, VibratorToken> mVibratorTokens =
179a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            new HashMap<IBinder, VibratorToken>();
180a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    private int mNextVibratorTokenValue;
181a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
182af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    // State for the currently installed input filter.
183af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    final Object mInputFilterLock = new Object();
184c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov    IInputFilter mInputFilter; // guarded by mInputFilterLock
185af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    InputFilterHost mInputFilterHost; // guarded by mInputFilterLock
1864532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
1873787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev    private IWindow mFocusedWindow;
1883787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev    private boolean mFocusedWindowHasCapture;
1893787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev
1907e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native long nativeInit(InputManagerService service,
1914532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            Context context, MessageQueue messageQueue);
1927e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeStart(long ptr);
193b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon    private static native void nativeSetVirtualDisplayViewports(long ptr,
194b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon            DisplayViewport[] viewports);
195b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon    private static native void nativeSetDisplayViewport(long ptr, int viewportType,
196d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            int displayId, int rotation,
197d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            int logicalLeft, int logicalTop, int logicalRight, int logicalBottom,
19883d616a9c7b9505153d258511eb5c16b552e268dJeff Brown            int physicalLeft, int physicalTop, int physicalRight, int physicalBottom,
199b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon            int deviceWidth, int deviceHeight, String uniqueId);
200d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
2017e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native int nativeGetScanCodeState(long ptr,
2024532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            int deviceId, int sourceMask, int scanCode);
2037e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native int nativeGetKeyCodeState(long ptr,
2044532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            int deviceId, int sourceMask, int keyCode);
2057e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native int nativeGetSwitchState(long ptr,
2064532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            int deviceId, int sourceMask, int sw);
2077e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native boolean nativeHasKeys(long ptr,
2084532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists);
2097e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeRegisterInputChannel(long ptr, InputChannel inputChannel,
210928e054931d357326613c78e62f4d850b7c442ffJeff Brown            InputWindowHandle inputWindowHandle, boolean monitor);
2117e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel);
2127e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeSetInputFilterEnabled(long ptr, boolean enable);
213ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown    private static native int nativeInjectInputEvent(long ptr, InputEvent event, int displayId,
2140029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
2150029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            int policyFlags);
216112d05678b7de53da8948f62dd2e968274f62244Andrii Kulian    private static native void nativeToggleCapsLock(long ptr, int deviceId);
2177e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
2187e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen);
2197e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeSetSystemUiVisibility(long ptr, int visibility);
2207e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeSetFocusedApplication(long ptr,
2214532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            InputApplicationHandle application);
2227e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native boolean nativeTransferTouchFocus(long ptr,
2234532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            InputChannel fromChannel, InputChannel toChannel);
2247e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeSetPointerSpeed(long ptr, int speed);
2257e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeSetShowTouches(long ptr, boolean enabled);
226037c33eae74bee2774897d969d48947f9abe254fJeff Brown    private static native void nativeSetInteractive(long ptr, boolean interactive);
227857aa7be880c53d78f72a9f227cbdf72ee68d587Jason Gerecke    private static native void nativeReloadCalibration(long ptr);
2287e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeVibrate(long ptr, int deviceId, long[] pattern,
229a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            int repeat, int token);
2307e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeCancelVibrate(long ptr, int deviceId, int token);
2317e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeReloadKeyboardLayouts(long ptr);
2327e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeReloadDeviceAliases(long ptr);
2337e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native String nativeDump(long ptr);
2347e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeMonitor(long ptr);
235f9d9ce7705475874c82af04eb9b208a7fb556792Michael Wright    private static native void nativeSetPointerIconType(long ptr, int iconId);
23619a560197950425f7e1856d5bd1216fbc680bf70Jun Mukai    private static native void nativeReloadPointerIcons(long ptr);
237d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    private static native void nativeSetCustomPointerIcon(long ptr, PointerIcon icon);
2383787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev    private static native void nativeSetPointerCapture(long ptr, boolean detached);
239ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
2407fbdc84e87dd3a0e196b9803bb04495d11e9cb8aJeff Brown    // Input event injection constants defined in InputDispatcher.h.
241ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
242ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1;
243ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private static final int INPUT_EVENT_INJECTION_FAILED = 2;
244ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3;
245ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
246ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    // Maximum number of milliseconds to wait for input event injection.
247ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
248ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
2496d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    // Key states (may be returned by queries about the current state of a
2506d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    // particular key code, scan code or switch).
2512f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
2526d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /** The key state is unknown or the requested key itself is not supported. */
2536d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public static final int KEY_STATE_UNKNOWN = -1;
2546d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
2556d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /** The key is up. /*/
2566d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public static final int KEY_STATE_UP = 0;
2576d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
2586d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /** The key is down. */
2596d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public static final int KEY_STATE_DOWN = 1;
2606d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
2616d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /** The key is down but is a virtual key press that is being emulated by the system. */
2626d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public static final int KEY_STATE_VIRTUAL = 2;
2636d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
264c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown    /** Scan code: Mouse / trackball button. */
265c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown    public static final int BTN_MOUSE = 0x110;
266c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown
2672f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    // Switch code values must match bionic/libc/kernel/common/linux/input.h
268c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown    /** Switch code: Lid switch.  When set, lid is shut. */
269c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown    public static final int SW_LID = 0x00;
270c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown
27139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    /** Switch code: Tablet mode switch.
27239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * When set, the device is in tablet mode (i.e. no keyboard is connected).
27339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     */
27439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    public static final int SW_TABLET_MODE = 0x01;
27539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
276c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown    /** Switch code: Keypad slide.  When set, keyboard is exposed. */
277c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown    public static final int SW_KEYPAD_SLIDE = 0x0a;
278c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown
2792f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    /** Switch code: Headphone.  When set, headphone is inserted. */
2802f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_HEADPHONE_INSERT = 0x02;
2812f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
2822f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    /** Switch code: Microphone.  When set, microphone is inserted. */
2832f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_MICROPHONE_INSERT = 0x04;
2842f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
28543cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund    /** Switch code: Line out.  When set, Line out (hi-Z) is inserted. */
28643cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund    public static final int SW_LINEOUT_INSERT = 0x06;
28743cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund
2882f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    /** Switch code: Headphone/Microphone Jack.  When set, something is inserted. */
2892f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_JACK_PHYSICAL_INSERT = 0x07;
2902f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
2913818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright    /** Switch code: Camera lens cover. When set the lens is covered. */
2923818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright    public static final int SW_CAMERA_LENS_COVER = 0x09;
2933818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright
294b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon    // Viewport constants defined in InputReader.h.
295b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon    public static final int VIEWPORT_DEFAULT = 1;
296b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon    public static final int VIEWPORT_EXTERNAL = 2;
297b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon    public static final int VIEWPORT_VIRTUAL = 3;
298b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon
2992f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_LID_BIT = 1 << SW_LID;
30039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    public static final int SW_TABLET_MODE_BIT = 1 << SW_TABLET_MODE;
3012f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
3022f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_HEADPHONE_INSERT_BIT = 1 << SW_HEADPHONE_INSERT;
3032f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_MICROPHONE_INSERT_BIT = 1 << SW_MICROPHONE_INSERT;
30443cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund    public static final int SW_LINEOUT_INSERT_BIT = 1 << SW_LINEOUT_INSERT;
3052f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_JACK_PHYSICAL_INSERT_BIT = 1 << SW_JACK_PHYSICAL_INSERT;
3062f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_JACK_BITS =
30743cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund            SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_JACK_PHYSICAL_INSERT_BIT | SW_LINEOUT_INSERT_BIT;
3083818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright    public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER;
3092f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
3102f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */
3112f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    final boolean mUseDevInputEventForAudioJack;
3122f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
3134ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown    public InputManagerService(Context context) {
31446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        this.mContext = context;
3154ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
31605dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown
3172f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        mUseDevInputEventForAudioJack =
3182f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
3192f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
3202f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner                + mUseDevInputEventForAudioJack);
3214532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
3224ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown
3239918234dcf9e115560144d0218682dd5050843bcAdrian Roos        String doubleTouchGestureEnablePath = context.getResources().getString(
3249918234dcf9e115560144d0218682dd5050843bcAdrian Roos                R.string.config_doubleTouchGestureEnableFile);
3259918234dcf9e115560144d0218682dd5050843bcAdrian Roos        mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
3269918234dcf9e115560144d0218682dd5050843bcAdrian Roos            new File(doubleTouchGestureEnablePath);
3279918234dcf9e115560144d0218682dd5050843bcAdrian Roos
3284ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown        LocalServices.addService(InputManagerInternal.class, new LocalService());
32946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
3301a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown
331a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown    public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
332a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown        mWindowManagerCallbacks = callbacks;
333a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown    }
334a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown
3352f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public void setWiredAccessoryCallbacks(WiredAccessoryCallbacks callbacks) {
3362f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        mWiredAccessoryCallbacks = callbacks;
3372f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    }
3382f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
33946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    public void start() {
34046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        Slog.i(TAG, "Starting input manager");
3414532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeStart(mPtr);
3424532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
3434532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        // Add ourself to the Watchdog monitors.
3444532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        Watchdog.getInstance().addMonitor(this);
3451a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown
3461a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown        registerPointerSpeedSettingObserver();
347daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        registerShowTouchesSettingObserver();
34819a560197950425f7e1856d5bd1216fbc680bf70Jun Mukai        registerAccessibilityLargePointerSettingObserver();
349daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown
350d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        mContext.registerReceiver(new BroadcastReceiver() {
351d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            @Override
352d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            public void onReceive(Context context, Intent intent) {
353d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                updatePointerSpeedFromSettings();
354d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                updateShowTouchesFromSettings();
355e4e75daa655c862a7d5ee62da4104b13e3f45bbdJun Mukai                updateAccessibilityLargePointerFromSettings();
356d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            }
357d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
358d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown
3591a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown        updatePointerSpeedFromSettings();
360daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        updateShowTouchesFromSettings();
361e4e75daa655c862a7d5ee62da4104b13e3f45bbdJun Mukai        updateAccessibilityLargePointerFromSettings();
36246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
3636ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
3649631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie    // TODO(BT) Pass in paramter for bluetooth system
365a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public void systemRunning() {
3666ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        if (DEBUG) {
3676ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            Slog.d(TAG, "System ready.");
3686ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        }
369cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        mNotificationManager = (NotificationManager)mContext.getSystemService(
370cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                Context.NOTIFICATION_SERVICE);
3716ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        mSystemReady = true;
3726ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
3736ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
3746ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
3756ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
37669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown        filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
3776ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        filter.addDataScheme("package");
3786ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        mContext.registerReceiver(new BroadcastReceiver() {
3796ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            @Override
3806ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            public void onReceive(Context context, Intent intent) {
381cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                updateKeyboardLayouts();
3826ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            }
3836ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        }, filter, null, mHandler);
3845bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown
3855bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown        filter = new IntentFilter(BluetoothDevice.ACTION_ALIAS_CHANGED);
3865bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown        mContext.registerReceiver(new BroadcastReceiver() {
3875bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown            @Override
3885bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown            public void onReceive(Context context, Intent intent) {
3895bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown                reloadDeviceAliases();
3905bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown            }
3915bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown        }, filter, null, mHandler);
3925bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown
393cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        mHandler.sendEmptyMessage(MSG_RELOAD_DEVICE_ALIASES);
394cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        mHandler.sendEmptyMessage(MSG_UPDATE_KEYBOARD_LAYOUTS);
3954a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent
3964a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent        if (mWiredAccessoryCallbacks != null) {
3974a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent            mWiredAccessoryCallbacks.systemReady();
3984a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent        }
3996ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    }
4006ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
4016ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    private void reloadKeyboardLayouts() {
402cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (DEBUG) {
403cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            Slog.d(TAG, "Reloading keyboard layouts.");
404cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
4056ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        nativeReloadKeyboardLayouts(mPtr);
4066ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    }
4076ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
4085bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown    private void reloadDeviceAliases() {
409cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (DEBUG) {
410cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            Slog.d(TAG, "Reloading device names.");
411cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
4125bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown        nativeReloadDeviceAliases(mPtr);
4135bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown    }
4145bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown
4154ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown    private void setDisplayViewportsInternal(DisplayViewport defaultViewport,
416b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon            DisplayViewport externalTouchViewport,
417b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon            List<DisplayViewport> virtualTouchViewports) {
418d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        if (defaultViewport.valid) {
419b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon            setDisplayViewport(VIEWPORT_DEFAULT, defaultViewport);
42046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        }
421d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
422d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        if (externalTouchViewport.valid) {
423b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon            setDisplayViewport(VIEWPORT_EXTERNAL, externalTouchViewport);
424d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        } else if (defaultViewport.valid) {
425b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon            setDisplayViewport(VIEWPORT_EXTERNAL, defaultViewport);
426b699726018a0049665d8ad6b90dbc5af0e18f135Jeff Brown        }
427b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon
428b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon        nativeSetVirtualDisplayViewports(mPtr,
429b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon                virtualTouchViewports.toArray(new DisplayViewport[0]));
43046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
4314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
432b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon    private void setDisplayViewport(int viewportType, DisplayViewport viewport) {
433b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon        nativeSetDisplayViewport(mPtr, viewportType,
434d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                viewport.displayId, viewport.orientation,
435d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                viewport.logicalFrame.left, viewport.logicalFrame.top,
436d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                viewport.logicalFrame.right, viewport.logicalFrame.bottom,
437d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                viewport.physicalFrame.left, viewport.physicalFrame.top,
43883d616a9c7b9505153d258511eb5c16b552e268dJeff Brown                viewport.physicalFrame.right, viewport.physicalFrame.bottom,
439b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon                viewport.deviceWidth, viewport.deviceHeight, viewport.uniqueId);
44046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
441ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
4426d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /**
4436d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * Gets the current state of a key or button by key code.
4446d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param deviceId The input device id, or -1 to consult all devices.
4456d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
4466d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * consider all input sources.  An input device is consulted if at least one of its
4476d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * non-class input source bits matches the specified source mask.
4486d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param keyCode The key code to check.
4496d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @return The key state.
4506d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     */
4516d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) {
4524532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return nativeGetKeyCodeState(mPtr, deviceId, sourceMask, keyCode);
45346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
4542f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
4556d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /**
4566d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * Gets the current state of a key or button by scan code.
4576d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param deviceId The input device id, or -1 to consult all devices.
4586d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
4596d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * consider all input sources.  An input device is consulted if at least one of its
4606d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * non-class input source bits matches the specified source mask.
4616d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param scanCode The scan code to check.
4626d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @return The key state.
4636d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     */
4646d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public int getScanCodeState(int deviceId, int sourceMask, int scanCode) {
4654532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return nativeGetScanCodeState(mPtr, deviceId, sourceMask, scanCode);
46646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
467fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
4686d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /**
4696d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * Gets the current state of a switch by switch code.
4706d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param deviceId The input device id, or -1 to consult all devices.
4716d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
4726d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * consider all input sources.  An input device is consulted if at least one of its
4736d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * non-class input source bits matches the specified source mask.
4746d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param switchCode The switch code to check.
4756d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @return The switch state.
4766d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     */
4776d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public int getSwitchState(int deviceId, int sourceMask, int switchCode) {
4784532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return nativeGetSwitchState(mPtr, deviceId, sourceMask, switchCode);
47946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
48046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
4816d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /**
4826d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * Determines whether the specified key codes are supported by a particular device.
4836d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param deviceId The input device id, or -1 to consult all devices.
4846d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
4856d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * consider all input sources.  An input device is consulted if at least one of its
4866d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * non-class input source bits matches the specified source mask.
4876d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param keyCodes The array of key codes to check.
4886d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param keyExists An array at least as large as keyCodes whose entries will be set
4896d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * to true or false based on the presence or absence of support for the corresponding
4906d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * key codes.
4916d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @return True if the lookup was successful, false otherwise.
4926d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     */
4939f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
4946d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) {
49546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        if (keyCodes == null) {
49646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            throw new IllegalArgumentException("keyCodes must not be null.");
49746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        }
4986d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown        if (keyExists == null || keyExists.length < keyCodes.length) {
4996d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown            throw new IllegalArgumentException("keyExists must not be null and must be at "
5006d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown                    + "least as large as keyCodes.");
50146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        }
502fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
5034532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return nativeHasKeys(mPtr, deviceId, sourceMask, keyCodes, keyExists);
50446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
505fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
506a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    /**
507a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     * Creates an input channel that will receive all input from the input dispatcher.
508a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     * @param inputChannelName The input channel name.
509a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     * @return The input channel.
510a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     */
511a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    public InputChannel monitorInput(String inputChannelName) {
512a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown        if (inputChannelName == null) {
513a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown            throw new IllegalArgumentException("inputChannelName must not be null.");
514a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown        }
515fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
516a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown        InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
5174532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeRegisterInputChannel(mPtr, inputChannels[0], null, true);
518a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown        inputChannels[0].dispose(); // don't need to retain the Java object reference
519a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown        return inputChannels[1];
520a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    }
521a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown
522a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    /**
523a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     * Registers an input channel so that it can be used as an input event target.
524a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     * @param inputChannel The input channel to register.
525928e054931d357326613c78e62f4d850b7c442ffJeff Brown     * @param inputWindowHandle The handle of the input window associated with the
526928e054931d357326613c78e62f4d850b7c442ffJeff Brown     * input channel, or null if none.
527a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     */
528928e054931d357326613c78e62f4d850b7c442ffJeff Brown    public void registerInputChannel(InputChannel inputChannel,
529928e054931d357326613c78e62f4d850b7c442ffJeff Brown            InputWindowHandle inputWindowHandle) {
53046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        if (inputChannel == null) {
53146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            throw new IllegalArgumentException("inputChannel must not be null.");
53246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        }
533fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
5344532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
53546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
536fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
537a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    /**
538a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     * Unregisters an input channel.
539a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     * @param inputChannel The input channel to unregister.
540a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     */
54146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    public void unregisterInputChannel(InputChannel inputChannel) {
54246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        if (inputChannel == null) {
54346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            throw new IllegalArgumentException("inputChannel must not be null.");
54446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        }
545fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
5464532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeUnregisterInputChannel(mPtr, inputChannel);
54746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
5480029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
5490029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    /**
5500029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * Sets an input filter that will receive all input events before they are dispatched.
5510029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * The input filter may then reinterpret input events or inject new ones.
5520029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     *
5530029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * To ensure consistency, the input dispatcher automatically drops all events
5540029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * in progress whenever an input filter is installed or uninstalled.  After an input
5550029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * filter is uninstalled, it can no longer send input events unless it is reinstalled.
5560029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * Any events it attempts to send after it has been uninstalled will be dropped.
5570029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     *
5580029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * @param filter The input filter, or null to remove the current filter.
5590029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     */
560c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov    public void setInputFilter(IInputFilter filter) {
5610029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        synchronized (mInputFilterLock) {
562c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov            final IInputFilter oldFilter = mInputFilter;
5630029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            if (oldFilter == filter) {
5640029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                return; // nothing to do
5650029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            }
5660029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
5670029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            if (oldFilter != null) {
5680029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                mInputFilter = null;
5690029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                mInputFilterHost.disconnectLocked();
5700029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                mInputFilterHost = null;
571c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                try {
572c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                    oldFilter.uninstall();
573c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                } catch (RemoteException re) {
574c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                    /* ignore */
575c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                }
5760029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            }
5770029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
5780029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            if (filter != null) {
5790029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                mInputFilter = filter;
5800029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                mInputFilterHost = new InputFilterHost();
581c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                try {
582c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                    filter.install(mInputFilterHost);
583c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                } catch (RemoteException re) {
584c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                    /* ignore */
585c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                }
5860029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            }
5870029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
5884532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            nativeSetInputFilterEnabled(mPtr, filter != null);
5890029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        }
5900029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
5910029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
5929f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
593ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public boolean injectInputEvent(InputEvent event, int mode) {
594ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown        return injectInputEventInternal(event, Display.DEFAULT_DISPLAY, mode);
595ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown    }
596ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown
597ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown    private boolean injectInputEventInternal(InputEvent event, int displayId, int mode) {
5987fbdc84e87dd3a0e196b9803bb04495d11e9cb8aJeff Brown        if (event == null) {
5997fbdc84e87dd3a0e196b9803bb04495d11e9cb8aJeff Brown            throw new IllegalArgumentException("event must not be null");
6007fbdc84e87dd3a0e196b9803bb04495d11e9cb8aJeff Brown        }
601ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (mode != InputManager.INJECT_INPUT_EVENT_MODE_ASYNC
602ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
603ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
604ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("mode is invalid");
6057fbdc84e87dd3a0e196b9803bb04495d11e9cb8aJeff Brown        }
6066ec402b5ae33c8927694d8522b4cc6a5c8ba974eJeff Brown
607ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        final int pid = Binder.getCallingPid();
608ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        final int uid = Binder.getCallingUid();
609ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        final long ident = Binder.clearCallingIdentity();
610ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        final int result;
611ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
612ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown            result = nativeInjectInputEvent(mPtr, event, displayId, pid, uid, mode,
613ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                    INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
614ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } finally {
615ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            Binder.restoreCallingIdentity(ident);
616ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
617ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        switch (result) {
618ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
619ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                Slog.w(TAG, "Input event injection from pid " + pid + " permission denied.");
620ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                throw new SecurityException(
621ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                        "Injecting to another application requires INJECT_EVENTS permission");
622ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            case INPUT_EVENT_INJECTION_SUCCEEDED:
623ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                return true;
624ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            case INPUT_EVENT_INJECTION_TIMED_OUT:
625ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                Slog.w(TAG, "Input event injection from pid " + pid + " timed out.");
626ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                return false;
627ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            case INPUT_EVENT_INJECTION_FAILED:
628ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            default:
629ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                Slog.w(TAG, "Input event injection from pid " + pid + " failed.");
630ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                return false;
631ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
63246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
6330029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
6348d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown    /**
6358d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown     * Gets information about the input device with the specified id.
6362f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner     * @param deviceId The device id.
6378d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown     * @return The input device or null if not found.
6388d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown     */
6399f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
6408d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown    public InputDevice getInputDevice(int deviceId) {
641af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
642af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int count = mInputDevices.length;
643af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < count; i++) {
644af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                final InputDevice inputDevice = mInputDevices[i];
645af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                if (inputDevice.getId() == deviceId) {
646af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    return inputDevice;
647af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                }
648af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
649af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
650af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        return null;
6518d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown    }
652af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
6538d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown    /**
6548d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown     * Gets the ids of all input devices in the system.
6558d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown     * @return The input device ids.
6568d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown     */
6579f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
6588d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown    public int[] getInputDeviceIds() {
659af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
660af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int count = mInputDevices.length;
661af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int[] ids = new int[count];
662af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < count; i++) {
663af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                ids[i] = mInputDevices[i].getId();
664af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
665af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            return ids;
666af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
667af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
668af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
669daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown    /**
670daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown     * Gets all input devices in the system.
671daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown     * @return The array of input devices.
672daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown     */
673daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown    public InputDevice[] getInputDevices() {
674daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown        synchronized (mInputDevicesLock) {
675daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown            return mInputDevices;
676daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown        }
677daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown    }
678daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown
679af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    @Override // Binder call
680af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public void registerInputDevicesChangedListener(IInputDevicesChangedListener listener) {
681af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (listener == null) {
682af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            throw new IllegalArgumentException("listener must not be null");
683af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
684af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
685af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
686af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int callingPid = Binder.getCallingPid();
687af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (mInputDevicesChangedListeners.get(callingPid) != null) {
688af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                throw new SecurityException("The calling process has already "
689af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        + "registered an InputDevicesChangedListener.");
690af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
691af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
692af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            InputDevicesChangedListenerRecord record =
693af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    new InputDevicesChangedListenerRecord(callingPid, listener);
694af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            try {
695af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                IBinder binder = listener.asBinder();
696af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                binder.linkToDeath(record, 0);
697af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            } catch (RemoteException ex) {
698af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                // give up
699af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                throw new RuntimeException(ex);
700af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
701af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
702af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mInputDevicesChangedListeners.put(callingPid, record);
703af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
704af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
705af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
706af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void onInputDevicesChangedListenerDied(int pid) {
707af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
708af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mInputDevicesChangedListeners.remove(pid);
709af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
710af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
711af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
712af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    // Must be called on handler.
713cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private void deliverInputDevicesChanged(InputDevice[] oldInputDevices) {
714cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        // Scan for changes.
715cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        int numFullKeyboardsAdded = 0;
716af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        mTempInputDevicesChangedListenersToNotify.clear();
717cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        mTempFullKeyboards.clear();
718af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        final int numListeners;
719af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        final int[] deviceIdAndGeneration;
720af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
721af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (!mInputDevicesChangedPending) {
722af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                return;
723af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
724af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mInputDevicesChangedPending = false;
725af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
726af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            numListeners = mInputDevicesChangedListeners.size();
727af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < numListeners; i++) {
728af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mTempInputDevicesChangedListenersToNotify.add(
729af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        mInputDevicesChangedListeners.valueAt(i));
730af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
731af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
732af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int numDevices = mInputDevices.length;
733af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            deviceIdAndGeneration = new int[numDevices * 2];
734af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < numDevices; i++) {
735af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                final InputDevice inputDevice = mInputDevices[i];
736af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                deviceIdAndGeneration[i * 2] = inputDevice.getId();
737af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                deviceIdAndGeneration[i * 2 + 1] = inputDevice.getGeneration();
738cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
7397e4ff4b986d626493afb676dd4824d2b3663260aJeff Brown                if (!inputDevice.isVirtual() && inputDevice.isFullKeyboard()) {
740cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    if (!containsInputDeviceWithDescriptor(oldInputDevices,
741cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                            inputDevice.getDescriptor())) {
742cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        mTempFullKeyboards.add(numFullKeyboardsAdded++, inputDevice);
743cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    } else {
744cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        mTempFullKeyboards.add(inputDevice);
745cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    }
746cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
747af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
748af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
749af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
750cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        // Notify listeners.
751af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        for (int i = 0; i < numListeners; i++) {
752af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mTempInputDevicesChangedListenersToNotify.get(i).notifyInputDevicesChanged(
753af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    deviceIdAndGeneration);
754af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
755cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        mTempInputDevicesChangedListenersToNotify.clear();
756cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
757cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        // Check for missing keyboard layouts.
7580748342d2ed264c01384fbaa4446a702a8824813Michael Wright        List<InputDevice> keyboardsMissingLayout = new ArrayList<>();
7590748342d2ed264c01384fbaa4446a702a8824813Michael Wright        final int numFullKeyboards = mTempFullKeyboards.size();
7600748342d2ed264c01384fbaa4446a702a8824813Michael Wright        synchronized (mDataStore) {
7610748342d2ed264c01384fbaa4446a702a8824813Michael Wright            for (int i = 0; i < numFullKeyboards; i++) {
7620748342d2ed264c01384fbaa4446a702a8824813Michael Wright                final InputDevice inputDevice = mTempFullKeyboards.get(i);
7630748342d2ed264c01384fbaa4446a702a8824813Michael Wright                String layout =
7640748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier());
7650748342d2ed264c01384fbaa4446a702a8824813Michael Wright                if (layout == null) {
7660748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    layout = getDefaultKeyboardLayout(inputDevice);
7670748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    if (layout != null) {
7680748342d2ed264c01384fbaa4446a702a8824813Michael Wright                        setCurrentKeyboardLayoutForInputDevice(
7690748342d2ed264c01384fbaa4446a702a8824813Michael Wright                                inputDevice.getIdentifier(), layout);
770cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    }
771cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
7720748342d2ed264c01384fbaa4446a702a8824813Michael Wright                if (layout == null) {
7730748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    keyboardsMissingLayout.add(inputDevice);
7740748342d2ed264c01384fbaa4446a702a8824813Michael Wright                }
775cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
7760748342d2ed264c01384fbaa4446a702a8824813Michael Wright        }
7770748342d2ed264c01384fbaa4446a702a8824813Michael Wright
7780748342d2ed264c01384fbaa4446a702a8824813Michael Wright        if (mNotificationManager != null) {
7790748342d2ed264c01384fbaa4446a702a8824813Michael Wright            if (!keyboardsMissingLayout.isEmpty()) {
7800748342d2ed264c01384fbaa4446a702a8824813Michael Wright                if (keyboardsMissingLayout.size() > 1) {
7810748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    // We have more than one keyboard missing a layout, so drop the
7820748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    // user at the generic input methods page so they can pick which
7830748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    // one to set.
7840748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    showMissingKeyboardLayoutNotification(null);
7850748342d2ed264c01384fbaa4446a702a8824813Michael Wright                } else {
7860748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    showMissingKeyboardLayoutNotification(keyboardsMissingLayout.get(0));
787cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
788cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            } else if (mKeyboardLayoutNotificationShown) {
789cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                hideMissingKeyboardLayoutNotification();
790cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
791cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
792cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        mTempFullKeyboards.clear();
793cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
794cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
7950748342d2ed264c01384fbaa4446a702a8824813Michael Wright    private String getDefaultKeyboardLayout(final InputDevice d) {
7960748342d2ed264c01384fbaa4446a702a8824813Michael Wright        final Locale systemLocale = mContext.getResources().getConfiguration().locale;
7970748342d2ed264c01384fbaa4446a702a8824813Michael Wright        // If our locale doesn't have a language for some reason, then we don't really have a
7980748342d2ed264c01384fbaa4446a702a8824813Michael Wright        // reasonable default.
7990748342d2ed264c01384fbaa4446a702a8824813Michael Wright        if (TextUtils.isEmpty(systemLocale.getLanguage())) {
8000748342d2ed264c01384fbaa4446a702a8824813Michael Wright            return null;
8010748342d2ed264c01384fbaa4446a702a8824813Michael Wright        }
8020748342d2ed264c01384fbaa4446a702a8824813Michael Wright        final List<KeyboardLayout> layouts = new ArrayList<>();
8030748342d2ed264c01384fbaa4446a702a8824813Michael Wright        visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
8040748342d2ed264c01384fbaa4446a702a8824813Michael Wright            @Override
8050748342d2ed264c01384fbaa4446a702a8824813Michael Wright            public void visitKeyboardLayout(Resources resources,
8060748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    int keyboardLayoutResId, KeyboardLayout layout) {
8070748342d2ed264c01384fbaa4446a702a8824813Michael Wright                // Only select a default when we know the layout is appropriate. For now, this
8080748342d2ed264c01384fbaa4446a702a8824813Michael Wright                // means its a custom layout for a specific keyboard.
8090748342d2ed264c01384fbaa4446a702a8824813Michael Wright                if (layout.getVendorId() != d.getVendorId()
8100748342d2ed264c01384fbaa4446a702a8824813Michael Wright                        || layout.getProductId() != d.getProductId()) {
8110748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    return;
8120748342d2ed264c01384fbaa4446a702a8824813Michael Wright                }
8135660fad79808c6d1823a7135b283003b0947773aYohei Yukawa                final LocaleList locales = layout.getLocales();
8145660fad79808c6d1823a7135b283003b0947773aYohei Yukawa                final int numLocales = locales.size();
8155660fad79808c6d1823a7135b283003b0947773aYohei Yukawa                for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) {
8165660fad79808c6d1823a7135b283003b0947773aYohei Yukawa                    if (isCompatibleLocale(systemLocale, locales.get(localeIndex))) {
8170748342d2ed264c01384fbaa4446a702a8824813Michael Wright                        layouts.add(layout);
8180748342d2ed264c01384fbaa4446a702a8824813Michael Wright                        break;
8190748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    }
8200748342d2ed264c01384fbaa4446a702a8824813Michael Wright                }
8210748342d2ed264c01384fbaa4446a702a8824813Michael Wright            }
8220748342d2ed264c01384fbaa4446a702a8824813Michael Wright        });
8230748342d2ed264c01384fbaa4446a702a8824813Michael Wright
8240748342d2ed264c01384fbaa4446a702a8824813Michael Wright        if (layouts.isEmpty()) {
8250748342d2ed264c01384fbaa4446a702a8824813Michael Wright            return null;
8260748342d2ed264c01384fbaa4446a702a8824813Michael Wright        }
8270748342d2ed264c01384fbaa4446a702a8824813Michael Wright
8280748342d2ed264c01384fbaa4446a702a8824813Michael Wright        // First sort so that ones with higher priority are listed at the top
8290748342d2ed264c01384fbaa4446a702a8824813Michael Wright        Collections.sort(layouts);
8300748342d2ed264c01384fbaa4446a702a8824813Michael Wright        // Next we want to try to find an exact match of language, country and variant.
8310748342d2ed264c01384fbaa4446a702a8824813Michael Wright        final int N = layouts.size();
8320748342d2ed264c01384fbaa4446a702a8824813Michael Wright        for (int i = 0; i < N; i++) {
8330748342d2ed264c01384fbaa4446a702a8824813Michael Wright            KeyboardLayout layout = layouts.get(i);
8345660fad79808c6d1823a7135b283003b0947773aYohei Yukawa            final LocaleList locales = layout.getLocales();
8355660fad79808c6d1823a7135b283003b0947773aYohei Yukawa            final int numLocales = locales.size();
8365660fad79808c6d1823a7135b283003b0947773aYohei Yukawa            for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) {
8375660fad79808c6d1823a7135b283003b0947773aYohei Yukawa                final Locale locale = locales.get(localeIndex);
8385660fad79808c6d1823a7135b283003b0947773aYohei Yukawa                if (locale.getCountry().equals(systemLocale.getCountry())
8395660fad79808c6d1823a7135b283003b0947773aYohei Yukawa                        && locale.getVariant().equals(systemLocale.getVariant())) {
8400748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    return layout.getDescriptor();
8410748342d2ed264c01384fbaa4446a702a8824813Michael Wright                }
8420748342d2ed264c01384fbaa4446a702a8824813Michael Wright            }
8430748342d2ed264c01384fbaa4446a702a8824813Michael Wright        }
8440748342d2ed264c01384fbaa4446a702a8824813Michael Wright        // Then try an exact match of language and country
8450748342d2ed264c01384fbaa4446a702a8824813Michael Wright        for (int i = 0; i < N; i++) {
8460748342d2ed264c01384fbaa4446a702a8824813Michael Wright            KeyboardLayout layout = layouts.get(i);
8475660fad79808c6d1823a7135b283003b0947773aYohei Yukawa            final LocaleList locales = layout.getLocales();
8485660fad79808c6d1823a7135b283003b0947773aYohei Yukawa            final int numLocales = locales.size();
8495660fad79808c6d1823a7135b283003b0947773aYohei Yukawa            for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) {
8505660fad79808c6d1823a7135b283003b0947773aYohei Yukawa                final Locale locale = locales.get(localeIndex);
8515660fad79808c6d1823a7135b283003b0947773aYohei Yukawa                if (locale.getCountry().equals(systemLocale.getCountry())) {
8520748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    return layout.getDescriptor();
8530748342d2ed264c01384fbaa4446a702a8824813Michael Wright                }
8540748342d2ed264c01384fbaa4446a702a8824813Michael Wright            }
8550748342d2ed264c01384fbaa4446a702a8824813Michael Wright        }
8560748342d2ed264c01384fbaa4446a702a8824813Michael Wright
8570748342d2ed264c01384fbaa4446a702a8824813Michael Wright        // Give up and just use the highest priority layout with matching language
8580748342d2ed264c01384fbaa4446a702a8824813Michael Wright        return layouts.get(0).getDescriptor();
8590748342d2ed264c01384fbaa4446a702a8824813Michael Wright    }
8600748342d2ed264c01384fbaa4446a702a8824813Michael Wright
8610748342d2ed264c01384fbaa4446a702a8824813Michael Wright    private static boolean isCompatibleLocale(Locale systemLocale, Locale keyboardLocale) {
8620748342d2ed264c01384fbaa4446a702a8824813Michael Wright        // Different languages are never compatible
8630748342d2ed264c01384fbaa4446a702a8824813Michael Wright        if (!systemLocale.getLanguage().equals(keyboardLocale.getLanguage())) {
8640748342d2ed264c01384fbaa4446a702a8824813Michael Wright            return false;
8650748342d2ed264c01384fbaa4446a702a8824813Michael Wright        }
8660748342d2ed264c01384fbaa4446a702a8824813Michael Wright        // If both the system and the keyboard layout have a country specifier, they must be equal.
8670748342d2ed264c01384fbaa4446a702a8824813Michael Wright        if (!TextUtils.isEmpty(systemLocale.getCountry())
8680748342d2ed264c01384fbaa4446a702a8824813Michael Wright                && !TextUtils.isEmpty(keyboardLocale.getCountry())
8690748342d2ed264c01384fbaa4446a702a8824813Michael Wright                && !systemLocale.getCountry().equals(keyboardLocale.getCountry())) {
8700748342d2ed264c01384fbaa4446a702a8824813Michael Wright            return false;
8710748342d2ed264c01384fbaa4446a702a8824813Michael Wright        }
8720748342d2ed264c01384fbaa4446a702a8824813Michael Wright        return true;
8730748342d2ed264c01384fbaa4446a702a8824813Michael Wright    }
8740748342d2ed264c01384fbaa4446a702a8824813Michael Wright
875857aa7be880c53d78f72a9f227cbdf72ee68d587Jason Gerecke    @Override // Binder call & native callback
876d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke    public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor,
877d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke            int surfaceRotation) {
878d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        if (inputDeviceDescriptor == null) {
879d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
880d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
881d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke
882d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        synchronized (mDataStore) {
883d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke            return mDataStore.getTouchCalibration(inputDeviceDescriptor, surfaceRotation);
884d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
885d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke    }
886d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke
887d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke    @Override // Binder call
888d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke    public void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation,
889d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            TouchCalibration calibration) {
890d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        if (!checkCallingPermission(android.Manifest.permission.SET_INPUT_CALIBRATION,
891d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke                "setTouchCalibrationForInputDevice()")) {
892d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            throw new SecurityException("Requires SET_INPUT_CALIBRATION permission");
893d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
894d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        if (inputDeviceDescriptor == null) {
895d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
896d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
897d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        if (calibration == null) {
898d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            throw new IllegalArgumentException("calibration must not be null");
899d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
900d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke        if (surfaceRotation < Surface.ROTATION_0 || surfaceRotation > Surface.ROTATION_270) {
901d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke            throw new IllegalArgumentException("surfaceRotation value out of bounds");
902d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke        }
903d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke
904d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        synchronized (mDataStore) {
905d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            try {
906d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke                if (mDataStore.setTouchCalibration(inputDeviceDescriptor, surfaceRotation,
907d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke                        calibration)) {
908857aa7be880c53d78f72a9f227cbdf72ee68d587Jason Gerecke                    nativeReloadCalibration(mPtr);
909857aa7be880c53d78f72a9f227cbdf72ee68d587Jason Gerecke                }
910d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            } finally {
911d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke                mDataStore.saveIfNeeded();
912d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            }
913d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
914d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke    }
915d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke
91639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    @Override // Binder call
9179209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    public int isInTabletMode() {
9189209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright        if (!checkCallingPermission(android.Manifest.permission.TABLET_MODE,
9199209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright                "isInTabletMode()")) {
9209209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright            throw new SecurityException("Requires TABLET_MODE permission");
9219209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright        }
9229209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright        return getSwitchState(-1, InputDevice.SOURCE_ANY, SW_TABLET_MODE);
9239209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    }
9249209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright
9259209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    @Override // Binder call
92639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    public void registerTabletModeChangedListener(ITabletModeChangedListener listener) {
9279209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright        if (!checkCallingPermission(android.Manifest.permission.TABLET_MODE,
92839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                "registerTabletModeChangedListener()")) {
92939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            throw new SecurityException("Requires TABLET_MODE_LISTENER permission");
93039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
93139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        if (listener == null) {
93239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            throw new IllegalArgumentException("listener must not be null");
93339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
93439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
93539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        synchronized (mTabletModeLock) {
93639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            final int callingPid = Binder.getCallingPid();
93739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            if (mTabletModeChangedListeners.get(callingPid) != null) {
93839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                throw new IllegalStateException("The calling process has already registered "
93939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                        + "a TabletModeChangedListener.");
94039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
94139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            TabletModeChangedListenerRecord record =
94239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    new TabletModeChangedListenerRecord(callingPid, listener);
94339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            try {
94439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                IBinder binder = listener.asBinder();
94539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                binder.linkToDeath(record, 0);
94639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            } catch (RemoteException ex) {
94739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                throw new RuntimeException(ex);
94839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
94939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            mTabletModeChangedListeners.put(callingPid, record);
95039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
95139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
95239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
95339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private void onTabletModeChangedListenerDied(int pid) {
95439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        synchronized (mTabletModeLock) {
95539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            mTabletModeChangedListeners.remove(pid);
95639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
95739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
95839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
95939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    // Must be called on handler
96039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private void deliverTabletModeChanged(long whenNanos, boolean inTabletMode) {
96139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        mTempTabletModeChangedListenersToNotify.clear();
96239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        final int numListeners;
96339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        synchronized (mTabletModeLock) {
96439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            numListeners = mTabletModeChangedListeners.size();
96539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            for (int i = 0; i < numListeners; i++) {
96639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                mTempTabletModeChangedListenersToNotify.add(
96739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                        mTabletModeChangedListeners.valueAt(i));
96839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
96939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
97039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        for (int i = 0; i < numListeners; i++) {
97139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            mTempTabletModeChangedListenersToNotify.get(i).notifyTabletModeChanged(
97239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    whenNanos, inTabletMode);
97339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
97439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
97539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
976cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    // Must be called on handler.
977c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright    private void showMissingKeyboardLayoutNotification(InputDevice device) {
978cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (!mKeyboardLayoutNotificationShown) {
9792bff4902929037cc7135a0769c43721a1322cb98Yohei Yukawa            final Intent intent = new Intent(Settings.ACTION_HARD_KEYBOARD_SETTINGS);
980c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright            if (device != null) {
981c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                intent.putExtra(Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, device.getIdentifier());
982cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
983c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
984c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
985c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                    | Intent.FLAG_ACTIVITY_CLEAR_TOP);
986c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright            final PendingIntent keyboardLayoutIntent = PendingIntent.getActivityAsUser(mContext, 0,
987c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                    intent, 0, null, UserHandle.CURRENT);
988cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
989cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            Resources r = mContext.getResources();
990af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch            Notification notification =
991af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                    new Notification.Builder(mContext, SystemNotificationChannels.PHYSICAL_KEYBOARD)
992af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                            .setContentTitle(r.getString(
993af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                                    R.string.select_keyboard_layout_notification_title))
994af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                            .setContentText(r.getString(
995af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                                    R.string.select_keyboard_layout_notification_message))
996af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                            .setContentIntent(keyboardLayoutIntent)
997af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                            .setSmallIcon(R.drawable.ic_settings_language)
998af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                            .setColor(mContext.getColor(
999af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                                    com.android.internal.R.color.system_notification_accent_color))
1000af759c52ce01fe6b5144957e38da956af01a217bGeoffrey Pitsch                            .build();
100150cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn            mNotificationManager.notifyAsUser(null,
1002282cfefea0fbbd299839e353e6d30affdcd4a55cChris Wren                    SystemMessage.NOTE_SELECT_KEYBOARD_LAYOUT,
100350cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    notification, UserHandle.ALL);
1004cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            mKeyboardLayoutNotificationShown = true;
1005cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1006cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
1007cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1008cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    // Must be called on handler.
1009cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private void hideMissingKeyboardLayoutNotification() {
1010cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (mKeyboardLayoutNotificationShown) {
1011cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            mKeyboardLayoutNotificationShown = false;
101250cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn            mNotificationManager.cancelAsUser(null,
1013282cfefea0fbbd299839e353e6d30affdcd4a55cChris Wren                    SystemMessage.NOTE_SELECT_KEYBOARD_LAYOUT,
101450cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    UserHandle.ALL);
1015cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1016cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
1017cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1018cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    // Must be called on handler.
1019cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private void updateKeyboardLayouts() {
1020cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        // Scan all input devices state for keyboard layouts that have been uninstalled.
1021cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        final HashSet<String> availableKeyboardLayouts = new HashSet<String>();
1022cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
1023cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            @Override
10240748342d2ed264c01384fbaa4446a702a8824813Michael Wright            public void visitKeyboardLayout(Resources resources,
10250748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    int keyboardLayoutResId, KeyboardLayout layout) {
10260748342d2ed264c01384fbaa4446a702a8824813Michael Wright                availableKeyboardLayouts.add(layout.getDescriptor());
1027cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
1028cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        });
1029cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        synchronized (mDataStore) {
1030cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            try {
1031cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                mDataStore.removeUninstalledKeyboardLayouts(availableKeyboardLayouts);
1032cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            } finally {
1033cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                mDataStore.saveIfNeeded();
1034cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
1035cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1036cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1037cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        // Reload keyboard layouts.
1038cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        reloadKeyboardLayouts();
1039cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
1040cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1041cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private static boolean containsInputDeviceWithDescriptor(InputDevice[] inputDevices,
1042cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            String descriptor) {
1043cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        final int numDevices = inputDevices.length;
1044cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        for (int i = 0; i < numDevices; i++) {
1045cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            final InputDevice inputDevice = inputDevices[i];
1046cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            if (inputDevice.getDescriptor().equals(descriptor)) {
1047cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                return true;
1048cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
1049cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1050cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        return false;
10518d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown    }
10529f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
10539f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
10549f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public KeyboardLayout[] getKeyboardLayouts() {
10556ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        final ArrayList<KeyboardLayout> list = new ArrayList<KeyboardLayout>();
10566ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
10576ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            @Override
10580748342d2ed264c01384fbaa4446a702a8824813Michael Wright            public void visitKeyboardLayout(Resources resources,
10590748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    int keyboardLayoutResId, KeyboardLayout layout) {
10600748342d2ed264c01384fbaa4446a702a8824813Michael Wright                list.add(layout);
10610748342d2ed264c01384fbaa4446a702a8824813Michael Wright            }
10620748342d2ed264c01384fbaa4446a702a8824813Michael Wright        });
10630748342d2ed264c01384fbaa4446a702a8824813Michael Wright        return list.toArray(new KeyboardLayout[list.size()]);
10640748342d2ed264c01384fbaa4446a702a8824813Michael Wright    }
10650748342d2ed264c01384fbaa4446a702a8824813Michael Wright
1066b0e804a303272655ec7c2cece66d69f39b488955Michael Wright    @Override // Binder call
10670748342d2ed264c01384fbaa4446a702a8824813Michael Wright    public KeyboardLayout[] getKeyboardLayoutsForInputDevice(
10680748342d2ed264c01384fbaa4446a702a8824813Michael Wright            final InputDeviceIdentifier identifier) {
1069b0e804a303272655ec7c2cece66d69f39b488955Michael Wright        final String[] enabledLayoutDescriptors =
1070b0e804a303272655ec7c2cece66d69f39b488955Michael Wright            getEnabledKeyboardLayoutsForInputDevice(identifier);
1071b0e804a303272655ec7c2cece66d69f39b488955Michael Wright        final ArrayList<KeyboardLayout> enabledLayouts =
1072b0e804a303272655ec7c2cece66d69f39b488955Michael Wright            new ArrayList<KeyboardLayout>(enabledLayoutDescriptors.length);
1073b0e804a303272655ec7c2cece66d69f39b488955Michael Wright        final ArrayList<KeyboardLayout> potentialLayouts = new ArrayList<KeyboardLayout>();
10740748342d2ed264c01384fbaa4446a702a8824813Michael Wright        visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
10750748342d2ed264c01384fbaa4446a702a8824813Michael Wright            boolean mHasSeenDeviceSpecificLayout;
10760748342d2ed264c01384fbaa4446a702a8824813Michael Wright
10770748342d2ed264c01384fbaa4446a702a8824813Michael Wright            @Override
10780748342d2ed264c01384fbaa4446a702a8824813Michael Wright            public void visitKeyboardLayout(Resources resources,
10790748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    int keyboardLayoutResId, KeyboardLayout layout) {
1080b0e804a303272655ec7c2cece66d69f39b488955Michael Wright                // First check if it's enabled. If the keyboard layout is enabled then we always
1081b0e804a303272655ec7c2cece66d69f39b488955Michael Wright                // want to return it as a possible layout for the device.
1082b0e804a303272655ec7c2cece66d69f39b488955Michael Wright                for (String s : enabledLayoutDescriptors) {
1083b0e804a303272655ec7c2cece66d69f39b488955Michael Wright                    if (s != null && s.equals(layout.getDescriptor())) {
1084b0e804a303272655ec7c2cece66d69f39b488955Michael Wright                        enabledLayouts.add(layout);
1085b0e804a303272655ec7c2cece66d69f39b488955Michael Wright                        return;
1086b0e804a303272655ec7c2cece66d69f39b488955Michael Wright                    }
1087b0e804a303272655ec7c2cece66d69f39b488955Michael Wright                }
1088b0e804a303272655ec7c2cece66d69f39b488955Michael Wright                // Next find any potential layouts that aren't yet enabled for the device. For
1089b0e804a303272655ec7c2cece66d69f39b488955Michael Wright                // devices that have special layouts we assume there's a reason that the generic
1090b0e804a303272655ec7c2cece66d69f39b488955Michael Wright                // layouts don't work for them so we don't want to return them since it's likely
1091b0e804a303272655ec7c2cece66d69f39b488955Michael Wright                // to result in a poor user experience.
10920748342d2ed264c01384fbaa4446a702a8824813Michael Wright                if (layout.getVendorId() == identifier.getVendorId()
10930748342d2ed264c01384fbaa4446a702a8824813Michael Wright                        && layout.getProductId() == identifier.getProductId()) {
10940748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    if (!mHasSeenDeviceSpecificLayout) {
10950748342d2ed264c01384fbaa4446a702a8824813Michael Wright                        mHasSeenDeviceSpecificLayout = true;
1096b0e804a303272655ec7c2cece66d69f39b488955Michael Wright                        potentialLayouts.clear();
10970748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    }
1098b0e804a303272655ec7c2cece66d69f39b488955Michael Wright                    potentialLayouts.add(layout);
10990748342d2ed264c01384fbaa4446a702a8824813Michael Wright                } else if (layout.getVendorId() == -1 && layout.getProductId() == -1
11000748342d2ed264c01384fbaa4446a702a8824813Michael Wright                        && !mHasSeenDeviceSpecificLayout) {
1101b0e804a303272655ec7c2cece66d69f39b488955Michael Wright                    potentialLayouts.add(layout);
11020748342d2ed264c01384fbaa4446a702a8824813Michael Wright                }
11036ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            }
11046ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        });
1105b0e804a303272655ec7c2cece66d69f39b488955Michael Wright        final int enabledLayoutSize = enabledLayouts.size();
1106b0e804a303272655ec7c2cece66d69f39b488955Michael Wright        final int potentialLayoutSize = potentialLayouts.size();
1107b0e804a303272655ec7c2cece66d69f39b488955Michael Wright        KeyboardLayout[] layouts = new KeyboardLayout[enabledLayoutSize + potentialLayoutSize];
1108b0e804a303272655ec7c2cece66d69f39b488955Michael Wright        enabledLayouts.toArray(layouts);
1109b0e804a303272655ec7c2cece66d69f39b488955Michael Wright        for (int i = 0; i < potentialLayoutSize; i++) {
1110b0e804a303272655ec7c2cece66d69f39b488955Michael Wright            layouts[enabledLayoutSize + i] = potentialLayouts.get(i);
1111b0e804a303272655ec7c2cece66d69f39b488955Michael Wright        }
1112b0e804a303272655ec7c2cece66d69f39b488955Michael Wright        return layouts;
11139f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    }
11149f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
11159f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
11169f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
11179f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        if (keyboardLayoutDescriptor == null) {
11189f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
11199f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
11209f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
11216ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        final KeyboardLayout[] result = new KeyboardLayout[1];
11226ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
11236ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            @Override
11240748342d2ed264c01384fbaa4446a702a8824813Michael Wright            public void visitKeyboardLayout(Resources resources,
11250748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    int keyboardLayoutResId, KeyboardLayout layout) {
11260748342d2ed264c01384fbaa4446a702a8824813Michael Wright                result[0] = layout;
11276ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            }
11286ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        });
11296ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        if (result[0] == null) {
11300748342d2ed264c01384fbaa4446a702a8824813Michael Wright            Slog.w(TAG, "Could not get keyboard layout with descriptor '"
11316ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                    + keyboardLayoutDescriptor + "'.");
11329f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
11336ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        return result[0];
11346ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    }
11359f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
11366ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    private void visitAllKeyboardLayouts(KeyboardLayoutVisitor visitor) {
11379f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        final PackageManager pm = mContext.getPackageManager();
11386ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        Intent intent = new Intent(InputManager.ACTION_QUERY_KEYBOARD_LAYOUTS);
11396ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent,
11408a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey                PackageManager.GET_META_DATA | PackageManager.MATCH_DIRECT_BOOT_AWARE
11418a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE)) {
11428ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            final ActivityInfo activityInfo = resolveInfo.activityInfo;
11438ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            final int priority = resolveInfo.priority;
11448ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            visitKeyboardLayoutsInPackage(pm, activityInfo, null, priority, visitor);
11456ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        }
11466ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    }
11476ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
11486ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    private void visitKeyboardLayout(String keyboardLayoutDescriptor,
11496ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            KeyboardLayoutVisitor visitor) {
11506ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        KeyboardLayoutDescriptor d = KeyboardLayoutDescriptor.parse(keyboardLayoutDescriptor);
11516ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        if (d != null) {
11526ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            final PackageManager pm = mContext.getPackageManager();
11536ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            try {
11546ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                ActivityInfo receiver = pm.getReceiverInfo(
11556ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                        new ComponentName(d.packageName, d.receiverName),
11565217cacbd9f382068bb9e176cd5a0b15388a335cJeff Sharkey                        PackageManager.GET_META_DATA
11578a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey                                | PackageManager.MATCH_DIRECT_BOOT_AWARE
11588a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
11598ebac231966e27364e5d463b63540a0527d40c4bMichael Wright                visitKeyboardLayoutsInPackage(pm, receiver, d.keyboardLayoutName, 0, visitor);
11606ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            } catch (NameNotFoundException ex) {
11616ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            }
11629f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
11639f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    }
11649f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
11656ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    private void visitKeyboardLayoutsInPackage(PackageManager pm, ActivityInfo receiver,
11668ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            String keyboardName, int requestedPriority, KeyboardLayoutVisitor visitor) {
11679f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        Bundle metaData = receiver.metaData;
11689f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        if (metaData == null) {
11696ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            return;
11709f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
11719f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
11729f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        int configResId = metaData.getInt(InputManager.META_DATA_KEYBOARD_LAYOUTS);
11739f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        if (configResId == 0) {
11740748342d2ed264c01384fbaa4446a702a8824813Michael Wright            Slog.w(TAG, "Missing meta-data '" + InputManager.META_DATA_KEYBOARD_LAYOUTS
11759f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    + "' on receiver " + receiver.packageName + "/" + receiver.name);
11766ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            return;
11779f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
11789f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
1179d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown        CharSequence receiverLabel = receiver.loadLabel(pm);
1180d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown        String collection = receiverLabel != null ? receiverLabel.toString() : "";
11818ebac231966e27364e5d463b63540a0527d40c4bMichael Wright        int priority;
11828ebac231966e27364e5d463b63540a0527d40c4bMichael Wright        if ((receiver.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
11838ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            priority = requestedPriority;
11848ebac231966e27364e5d463b63540a0527d40c4bMichael Wright        } else {
11858ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            priority = 0;
11868ebac231966e27364e5d463b63540a0527d40c4bMichael Wright        }
1187d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown
11889f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        try {
11899f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            Resources resources = pm.getResourcesForApplication(receiver.applicationInfo);
11909f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            XmlResourceParser parser = resources.getXml(configResId);
11919f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            try {
11929f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                XmlUtils.beginDocument(parser, "keyboard-layouts");
11939f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
11949f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                for (;;) {
11959f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    XmlUtils.nextElement(parser);
11969f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    String element = parser.getName();
11979f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    if (element == null) {
11989f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                        break;
11999f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    }
12009f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    if (element.equals("keyboard-layout")) {
12019f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                        TypedArray a = resources.obtainAttributes(
12029f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                parser, com.android.internal.R.styleable.KeyboardLayout);
12039f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                        try {
12049f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                            String name = a.getString(
12059f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                    com.android.internal.R.styleable.KeyboardLayout_name);
12069f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                            String label = a.getString(
12079f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                    com.android.internal.R.styleable.KeyboardLayout_label);
12082f0957607411b99810226ad38d59cf18718b86d0Jeff Brown                            int keyboardLayoutResId = a.getResourceId(
12092f0957607411b99810226ad38d59cf18718b86d0Jeff Brown                                    com.android.internal.R.styleable.KeyboardLayout_keyboardLayout,
12102f0957607411b99810226ad38d59cf18718b86d0Jeff Brown                                    0);
12110748342d2ed264c01384fbaa4446a702a8824813Michael Wright                            String languageTags = a.getString(
12120748342d2ed264c01384fbaa4446a702a8824813Michael Wright                                    com.android.internal.R.styleable.KeyboardLayout_locale);
12135660fad79808c6d1823a7135b283003b0947773aYohei Yukawa                            LocaleList locales = getLocalesFromLanguageTags(languageTags);
12140748342d2ed264c01384fbaa4446a702a8824813Michael Wright                            int vid = a.getInt(
12150748342d2ed264c01384fbaa4446a702a8824813Michael Wright                                    com.android.internal.R.styleable.KeyboardLayout_vendorId, -1);
12160748342d2ed264c01384fbaa4446a702a8824813Michael Wright                            int pid = a.getInt(
12170748342d2ed264c01384fbaa4446a702a8824813Michael Wright                                    com.android.internal.R.styleable.KeyboardLayout_productId, -1);
12180748342d2ed264c01384fbaa4446a702a8824813Michael Wright
12192f0957607411b99810226ad38d59cf18718b86d0Jeff Brown                            if (name == null || label == null || keyboardLayoutResId == 0) {
12200748342d2ed264c01384fbaa4446a702a8824813Michael Wright                                Slog.w(TAG, "Missing required 'name', 'label' or 'keyboardLayout' "
12219f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                        + "attributes in keyboard layout "
12229f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                        + "resource from receiver "
12239f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                        + receiver.packageName + "/" + receiver.name);
12249f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                            } else {
12259f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                String descriptor = KeyboardLayoutDescriptor.format(
12269f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                        receiver.packageName, receiver.name, name);
12276ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                                if (keyboardName == null || name.equals(keyboardName)) {
12280748342d2ed264c01384fbaa4446a702a8824813Michael Wright                                    KeyboardLayout layout = new KeyboardLayout(
12290748342d2ed264c01384fbaa4446a702a8824813Michael Wright                                            descriptor, label, collection, priority,
12300748342d2ed264c01384fbaa4446a702a8824813Michael Wright                                            locales, vid, pid);
12310748342d2ed264c01384fbaa4446a702a8824813Michael Wright                                    visitor.visitKeyboardLayout(
12320748342d2ed264c01384fbaa4446a702a8824813Michael Wright                                            resources, keyboardLayoutResId, layout);
12339f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                }
12349f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                            }
12359f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                        } finally {
12369f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                            a.recycle();
12379f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                        }
12389f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    } else {
12390748342d2ed264c01384fbaa4446a702a8824813Michael Wright                        Slog.w(TAG, "Skipping unrecognized element '" + element
12409f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                + "' in keyboard layout resource from receiver "
12419f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                + receiver.packageName + "/" + receiver.name);
12429f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    }
12439f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                }
12449f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            } finally {
12459f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                parser.close();
12469f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            }
12479f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (Exception ex) {
12480748342d2ed264c01384fbaa4446a702a8824813Michael Wright            Slog.w(TAG, "Could not parse keyboard layout resource from receiver "
12499f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    + receiver.packageName + "/" + receiver.name, ex);
12509f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
12519f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    }
12529f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
12535660fad79808c6d1823a7135b283003b0947773aYohei Yukawa    @NonNull
12545660fad79808c6d1823a7135b283003b0947773aYohei Yukawa    private static LocaleList getLocalesFromLanguageTags(String languageTags) {
12550748342d2ed264c01384fbaa4446a702a8824813Michael Wright        if (TextUtils.isEmpty(languageTags)) {
12565660fad79808c6d1823a7135b283003b0947773aYohei Yukawa            return LocaleList.getEmptyLocaleList();
12570748342d2ed264c01384fbaa4446a702a8824813Michael Wright        }
12585660fad79808c6d1823a7135b283003b0947773aYohei Yukawa        return LocaleList.forLanguageTags(languageTags.replace('|', ','));
12590748342d2ed264c01384fbaa4446a702a8824813Michael Wright    }
12600748342d2ed264c01384fbaa4446a702a8824813Michael Wright
1261fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    /**
1262fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * Builds a layout descriptor for the vendor/product. This returns the
1263fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * descriptor for ids that aren't useful (such as the default 0, 0).
1264fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     */
1265fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    private String getLayoutDescriptor(InputDeviceIdentifier identifier) {
1266fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier == null || identifier.getDescriptor() == null) {
1267fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            throw new IllegalArgumentException("identifier and descriptor must not be null");
1268fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        }
1269fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
1270fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier.getVendorId() == 0 && identifier.getProductId() == 0) {
1271fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            return identifier.getDescriptor();
12729f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
1273fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        StringBuilder bob = new StringBuilder();
1274fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        bob.append("vendor:").append(identifier.getVendorId());
1275fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        bob.append(",product:").append(identifier.getProductId());
1276fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        return bob.toString();
1277fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    }
1278fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
1279fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    @Override // Binder call
1280fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
12819f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
1282fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        String key = getLayoutDescriptor(identifier);
1283a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown        synchronized (mDataStore) {
1284fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            String layout = null;
1285fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            // try loading it using the layout descriptor if we have it
1286fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            layout = mDataStore.getCurrentKeyboardLayout(key);
1287fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            if (layout == null && !key.equals(identifier.getDescriptor())) {
1288fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                // if it doesn't exist fall back to the device descriptor
1289fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                layout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1290fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            }
1291fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            if (DEBUG) {
1292fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                Slog.d(TAG, "Loaded keyboard layout id for " + key + " and got "
1293fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                        + layout);
1294fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            }
1295fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            return layout;
1296a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown        }
12979f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    }
12989f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
12999f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
1300fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
13019f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            String keyboardLayoutDescriptor) {
13029f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1303cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                "setCurrentKeyboardLayoutForInputDevice()")) {
13049f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
13059f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
1306cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (keyboardLayoutDescriptor == null) {
1307cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1308cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1309cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1310fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        String key = getLayoutDescriptor(identifier);
1311cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        synchronized (mDataStore) {
1312cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            try {
1313fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                if (mDataStore.setCurrentKeyboardLayout(key, keyboardLayoutDescriptor)) {
1314fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                    if (DEBUG) {
1315fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                        Slog.d(TAG, "Saved keyboard layout using " + key);
1316fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                    }
1317cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1318cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
1319cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            } finally {
1320cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                mDataStore.saveIfNeeded();
1321cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
1322cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1323cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
13249f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
1325cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    @Override // Binder call
13260748342d2ed264c01384fbaa4446a702a8824813Michael Wright    public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
1327fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        String key = getLayoutDescriptor(identifier);
1328cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        synchronized (mDataStore) {
1329fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            String[] layouts = mDataStore.getKeyboardLayouts(key);
1330fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            if ((layouts == null || layouts.length == 0)
1331fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                    && !key.equals(identifier.getDescriptor())) {
1332fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                layouts = mDataStore.getKeyboardLayouts(identifier.getDescriptor());
1333fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            }
1334fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            return layouts;
1335cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1336cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
1337cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1338cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    @Override // Binder call
1339d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    @Nullable
1340d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    public KeyboardLayout getKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
1341d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            InputMethodInfo imeInfo, InputMethodSubtype imeSubtype) {
1342d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        InputMethodSubtypeHandle handle = new InputMethodSubtypeHandle(imeInfo, imeSubtype);
1343d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        String key = getLayoutDescriptor(identifier);
1344d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        final String keyboardLayoutDescriptor;
1345d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        synchronized (mDataStore) {
1346d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            keyboardLayoutDescriptor = mDataStore.getKeyboardLayout(key, handle);
1347d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
1348d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
1349d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        if (keyboardLayoutDescriptor == null) {
1350d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            return null;
1351d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
1352d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
1353d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        final KeyboardLayout[] result = new KeyboardLayout[1];
1354d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
1355d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            @Override
1356d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            public void visitKeyboardLayout(Resources resources,
1357d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    int keyboardLayoutResId, KeyboardLayout layout) {
1358d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                result[0] = layout;
1359d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            }
1360d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        });
1361d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        if (result[0] == null) {
1362d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            Slog.w(TAG, "Could not get keyboard layout with descriptor '"
1363d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    + keyboardLayoutDescriptor + "'.");
1364d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
1365d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        return result[0];
1366d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    }
1367d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
1368d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    @Override
1369d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
1370d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            InputMethodInfo imeInfo, InputMethodSubtype imeSubtype,
1371d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            String keyboardLayoutDescriptor) {
1372d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1373d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                "setKeyboardLayoutForInputDevice()")) {
1374d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1375d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
1376d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        if (keyboardLayoutDescriptor == null) {
1377d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1378d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
137946ac35d09b0a1ba7af7eb4c14293a7978edcd2abYohei Yukawa        if (imeInfo == null) {
138046ac35d09b0a1ba7af7eb4c14293a7978edcd2abYohei Yukawa            throw new IllegalArgumentException("imeInfo must not be null");
1381d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
1382d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        InputMethodSubtypeHandle handle = new InputMethodSubtypeHandle(imeInfo, imeSubtype);
1383d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        setKeyboardLayoutForInputDeviceInner(identifier, handle, keyboardLayoutDescriptor);
1384d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    }
1385d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
1386d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    private void setKeyboardLayoutForInputDeviceInner(InputDeviceIdentifier identifier,
1387d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            InputMethodSubtypeHandle imeHandle, String keyboardLayoutDescriptor) {
1388d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        String key = getLayoutDescriptor(identifier);
1389d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        synchronized (mDataStore) {
1390d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            try {
1391d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                if (mDataStore.setKeyboardLayout(key, imeHandle, keyboardLayoutDescriptor)) {
1392d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    if (DEBUG) {
1393d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                        Slog.d(TAG, "Set keyboard layout " + keyboardLayoutDescriptor +
1394d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                                " for subtype " + imeHandle + " and device " + identifier +
1395d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                                " using key " + key);
1396d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    }
1397d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    if (imeHandle.equals(mCurrentImeHandle)) {
1398d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                        if (DEBUG) {
1399d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                            Slog.d(TAG, "Layout for current subtype changed, switching layout");
1400d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                        }
1401d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                        SomeArgs args = SomeArgs.obtain();
1402d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                        args.arg1 = identifier;
1403d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                        args.arg2 = imeHandle;
1404d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                        mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, args).sendToTarget();
1405d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    }
1406d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1407d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                }
1408d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            } finally {
1409d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                mDataStore.saveIfNeeded();
1410d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            }
1411d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
1412d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    }
1413d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
1414d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    @Override // Binder call
1415fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
1416cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            String keyboardLayoutDescriptor) {
1417cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1418cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                "addKeyboardLayoutForInputDevice()")) {
1419cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1420cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1421cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (keyboardLayoutDescriptor == null) {
1422cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1423cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1424cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1425fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        String key = getLayoutDescriptor(identifier);
1426a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown        synchronized (mDataStore) {
1427a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown            try {
1428fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
1429fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
1430fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                    oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1431fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                }
1432fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                if (mDataStore.addKeyboardLayout(key, keyboardLayoutDescriptor)
1433d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                        && !Objects.equal(oldLayout, mDataStore.getCurrentKeyboardLayout(key))) {
1434cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1435cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
1436a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown            } finally {
1437a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown                mDataStore.saveIfNeeded();
1438a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown            }
1439a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown        }
1440cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
14419f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
1442cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    @Override // Binder call
1443fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
1444cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            String keyboardLayoutDescriptor) {
1445cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1446cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                "removeKeyboardLayoutForInputDevice()")) {
1447cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1448cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1449cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (keyboardLayoutDescriptor == null) {
1450cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1451cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1452cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1453fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        String key = getLayoutDescriptor(identifier);
1454cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        synchronized (mDataStore) {
1455cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            try {
1456fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
1457fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
1458fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                    oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1459fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                }
1460fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                boolean removed = mDataStore.removeKeyboardLayout(key, keyboardLayoutDescriptor);
1461fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                if (!key.equals(identifier.getDescriptor())) {
1462fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                    // We need to remove from both places to ensure it is gone
1463fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                    removed |= mDataStore.removeKeyboardLayout(identifier.getDescriptor(),
1464fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                            keyboardLayoutDescriptor);
1465fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                }
1466fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                if (removed && !Objects.equal(oldLayout,
1467fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                                mDataStore.getCurrentKeyboardLayout(key))) {
1468cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1469cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
1470cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            } finally {
1471cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                mDataStore.saveIfNeeded();
1472cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
1473cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1474cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
1475cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1476b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa    // Must be called on handler.
1477b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa    private void handleSwitchInputMethodSubtype(int userId,
1478b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa            @Nullable InputMethodInfo inputMethodInfo, @Nullable InputMethodSubtype subtype) {
1479b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa        if (DEBUG) {
1480b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa            Slog.i(TAG, "InputMethodSubtype changed: userId=" + userId
1481b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa                    + " ime=" + inputMethodInfo + " subtype=" + subtype);
1482b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa        }
1483d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        if (inputMethodInfo == null) {
1484d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            Slog.d(TAG, "No InputMethod is running, ignoring change");
1485d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            return;
1486d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
1487d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        if (subtype != null && !"keyboard".equals(subtype.getMode())) {
1488d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            Slog.d(TAG, "InputMethodSubtype changed to non-keyboard subtype, ignoring change");
1489d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            return;
1490d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
1491d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        InputMethodSubtypeHandle handle = new InputMethodSubtypeHandle(inputMethodInfo, subtype);
1492d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        if (!handle.equals(mCurrentImeHandle)) {
1493d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            mCurrentImeHandle = handle;
1494d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            handleSwitchKeyboardLayout(null, handle);
1495d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
1496cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
1497cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1498cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    // Must be called on handler.
1499d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    private void handleSwitchKeyboardLayout(@Nullable InputDeviceIdentifier identifier,
1500d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            InputMethodSubtypeHandle handle) {
1501d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        synchronized (mInputDevicesLock) {
1502d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            for (InputDevice device : mInputDevices) {
1503d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                if (identifier != null && !device.getIdentifier().equals(identifier) ||
1504d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                        !device.isFullKeyboard()) {
1505d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    continue;
1506cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
1507d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                String key = getLayoutDescriptor(device.getIdentifier());
1508d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                boolean changed = false;
1509d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                synchronized (mDataStore) {
1510d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    try {
1511d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                        if (mDataStore.switchKeyboardLayout(key, handle)) {
1512d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                            changed = true;
1513d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                        }
1514d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    } finally {
1515d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                        mDataStore.saveIfNeeded();
1516cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    }
1517cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
1518d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                if (changed) {
1519d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    reloadKeyboardLayouts();
1520d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                }
15219f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            }
15229f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
15236ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    }
15249f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
15253787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev    public void setInputWindows(InputWindowHandle[] windowHandles,
15263787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev            InputWindowHandle focusedWindowHandle) {
15273787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev        final IWindow newFocusedWindow =
15283787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev            focusedWindowHandle != null ? focusedWindowHandle.clientWindow : null;
15293787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev        if (mFocusedWindow != newFocusedWindow) {
15303787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev            mFocusedWindow = newFocusedWindow;
15313787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev            if (mFocusedWindowHasCapture) {
15323787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev                setPointerCapture(false);
15333787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev            }
15343787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev        }
15354532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeSetInputWindows(mPtr, windowHandles);
1536349703effce5acc53ed96f7ed8556131f0c65e18Jeff Brown    }
1537fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
15389302c8796fc4dcda08d4bd1e11733848fd4fafafJeff Brown    public void setFocusedApplication(InputApplicationHandle application) {
15394532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeSetFocusedApplication(mPtr, application);
1540349703effce5acc53ed96f7ed8556131f0c65e18Jeff Brown    }
1541fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
15423787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev    @Override
15433787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev    public void requestPointerCapture(IBinder windowToken, boolean enabled) {
15443787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev        if (mFocusedWindow == null || mFocusedWindow.asBinder() != windowToken) {
15453787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev            Slog.e(TAG, "requestPointerCapture called for a window that has no focus: "
15463787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev                    + windowToken);
15473787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev            return;
15483787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev        }
15493787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev        if (mFocusedWindowHasCapture == enabled) {
15503787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev            Slog.i(TAG, "requestPointerCapture: already " + (enabled ? "enabled" : "disabled"));
15513787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev            return;
15523787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev        }
15533787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev        setPointerCapture(enabled);
15543787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev        try {
15553787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev            mFocusedWindow.dispatchPointerCaptureChanged(enabled);
15563787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev        } catch (RemoteException ex) {
15573787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev            /* ignore */
15583787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev        }
15593787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev    }
15603787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev
15613787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev    private void setPointerCapture(boolean enabled) {
15623787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev        mFocusedWindowHasCapture = enabled;
15633787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev        nativeSetPointerCapture(mPtr, enabled);
15643787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev    }
15653787de16d24001eeb452e1c711d4290a396e67c9Vladislav Kaznacheev
1566349703effce5acc53ed96f7ed8556131f0c65e18Jeff Brown    public void setInputDispatchMode(boolean enabled, boolean frozen) {
15674532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeSetInputDispatchMode(mPtr, enabled, frozen);
1568349703effce5acc53ed96f7ed8556131f0c65e18Jeff Brown    }
156905dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown
157005dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown    public void setSystemUiVisibility(int visibility) {
15714532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeSetSystemUiVisibility(mPtr, visibility);
157205dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown    }
157305dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown
1574e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown    /**
1575e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * Atomically transfers touch focus from one window to another as identified by
1576e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * their input channels.  It is possible for multiple windows to have
1577e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * touch focus if they support split touch dispatch
1578e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * {@link android.view.WindowManager.LayoutParams#FLAG_SPLIT_TOUCH} but this
1579e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * method only transfers touch focus of the specified window without affecting
1580e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * other windows that may also have touch focus at the same time.
1581e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * @param fromChannel The channel of a window that currently has touch focus.
1582e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * @param toChannel The channel of the window that should receive touch focus in
1583e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * place of the first.
1584e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * @return True if the transfer was successful.  False if the window with the
1585e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * specified channel did not actually have touch focus at the time of the request.
1586e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     */
1587e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown    public boolean transferTouchFocus(InputChannel fromChannel, InputChannel toChannel) {
1588e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown        if (fromChannel == null) {
1589e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown            throw new IllegalArgumentException("fromChannel must not be null.");
1590e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown        }
1591e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown        if (toChannel == null) {
1592e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown            throw new IllegalArgumentException("toChannel must not be null.");
1593e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown        }
15944532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return nativeTransferTouchFocus(mPtr, fromChannel, toChannel);
1595e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown    }
159605dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown
15979f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
1598ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public void tryPointerSpeed(int speed) {
1599ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED,
1600ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                "tryPointerSpeed()")) {
1601ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new SecurityException("Requires SET_POINTER_SPEED permission");
1602ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
1603ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
16049f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        if (speed < InputManager.MIN_POINTER_SPEED || speed > InputManager.MAX_POINTER_SPEED) {
16059f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            throw new IllegalArgumentException("speed out of range");
16069f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
16079f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
1608ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        setPointerSpeedUnchecked(speed);
16091a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown    }
16101a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown
16111a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown    public void updatePointerSpeedFromSettings() {
1612ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        int speed = getPointerSpeedSetting();
1613ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        setPointerSpeedUnchecked(speed);
1614ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
1615ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
1616ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private void setPointerSpeedUnchecked(int speed) {
1617ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        speed = Math.min(Math.max(speed, InputManager.MIN_POINTER_SPEED),
1618ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                InputManager.MAX_POINTER_SPEED);
1619ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        nativeSetPointerSpeed(mPtr, speed);
16201a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown    }
16211a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown
16221a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown    private void registerPointerSpeedSettingObserver() {
16231a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown        mContext.getContentResolver().registerContentObserver(
16241a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown                Settings.System.getUriFor(Settings.System.POINTER_SPEED), true,
16254532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                new ContentObserver(mHandler) {
16261a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown                    @Override
16271a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown                    public void onChange(boolean selfChange) {
16281a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown                        updatePointerSpeedFromSettings();
16291a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown                    }
1630d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                }, UserHandle.USER_ALL);
16311a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown    }
16321a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown
1633ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private int getPointerSpeedSetting() {
1634ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        int speed = InputManager.DEFAULT_POINTER_SPEED;
16351a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown        try {
1636d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            speed = Settings.System.getIntForUser(mContext.getContentResolver(),
1637d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                    Settings.System.POINTER_SPEED, UserHandle.USER_CURRENT);
16381a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown        } catch (SettingNotFoundException snfe) {
16391a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown        }
16401a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown        return speed;
16411a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown    }
16421a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown
1643daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown    public void updateShowTouchesFromSettings() {
1644daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        int setting = getShowTouchesSetting(0);
16454532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeSetShowTouches(mPtr, setting != 0);
1646daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown    }
1647daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown
1648daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown    private void registerShowTouchesSettingObserver() {
1649daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        mContext.getContentResolver().registerContentObserver(
1650daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown                Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), true,
16514532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                new ContentObserver(mHandler) {
1652daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown                    @Override
1653daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown                    public void onChange(boolean selfChange) {
1654daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown                        updateShowTouchesFromSettings();
1655daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown                    }
1656d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                }, UserHandle.USER_ALL);
1657daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown    }
1658daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown
1659e4e75daa655c862a7d5ee62da4104b13e3f45bbdJun Mukai    public void updateAccessibilityLargePointerFromSettings() {
1660e4e75daa655c862a7d5ee62da4104b13e3f45bbdJun Mukai        final int accessibilityConfig = Settings.Secure.getIntForUser(
1661e4e75daa655c862a7d5ee62da4104b13e3f45bbdJun Mukai                mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON,
1662e4e75daa655c862a7d5ee62da4104b13e3f45bbdJun Mukai                0, UserHandle.USER_CURRENT);
16631f3dbffa0c521d89bce9b43220b279760911bcb7Jun Mukai        PointerIcon.setUseLargeIcons(accessibilityConfig == 1);
1664e4e75daa655c862a7d5ee62da4104b13e3f45bbdJun Mukai        nativeReloadPointerIcons(mPtr);
1665e4e75daa655c862a7d5ee62da4104b13e3f45bbdJun Mukai    }
1666e4e75daa655c862a7d5ee62da4104b13e3f45bbdJun Mukai
166719a560197950425f7e1856d5bd1216fbc680bf70Jun Mukai    private void registerAccessibilityLargePointerSettingObserver() {
166819a560197950425f7e1856d5bd1216fbc680bf70Jun Mukai        mContext.getContentResolver().registerContentObserver(
166919a560197950425f7e1856d5bd1216fbc680bf70Jun Mukai                Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON), true,
167019a560197950425f7e1856d5bd1216fbc680bf70Jun Mukai                new ContentObserver(mHandler) {
167119a560197950425f7e1856d5bd1216fbc680bf70Jun Mukai                    @Override
167219a560197950425f7e1856d5bd1216fbc680bf70Jun Mukai                    public void onChange(boolean selfChange) {
1673e4e75daa655c862a7d5ee62da4104b13e3f45bbdJun Mukai                        updateAccessibilityLargePointerFromSettings();
167419a560197950425f7e1856d5bd1216fbc680bf70Jun Mukai                    }
167519a560197950425f7e1856d5bd1216fbc680bf70Jun Mukai                }, UserHandle.USER_ALL);
167619a560197950425f7e1856d5bd1216fbc680bf70Jun Mukai    }
167719a560197950425f7e1856d5bd1216fbc680bf70Jun Mukai
1678daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown    private int getShowTouchesSetting(int defaultValue) {
1679daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        int result = defaultValue;
1680daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        try {
1681d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            result = Settings.System.getIntForUser(mContext.getContentResolver(),
1682d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                    Settings.System.SHOW_TOUCHES, UserHandle.USER_CURRENT);
1683daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        } catch (SettingNotFoundException snfe) {
1684daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        }
1685daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        return result;
1686daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown    }
1687daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown
1688a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    // Binder call
1689a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    @Override
1690a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    public void vibrate(int deviceId, long[] pattern, int repeat, IBinder token) {
1691a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        if (repeat >= pattern.length) {
1692a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            throw new ArrayIndexOutOfBoundsException();
1693a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1694a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1695a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        VibratorToken v;
1696a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        synchronized (mVibratorLock) {
1697a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            v = mVibratorTokens.get(token);
1698a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            if (v == null) {
1699a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                v = new VibratorToken(deviceId, token, mNextVibratorTokenValue++);
1700a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                try {
1701a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                    token.linkToDeath(v, 0);
1702a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                } catch (RemoteException ex) {
1703a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                    // give up
1704a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                    throw new RuntimeException(ex);
1705a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                }
1706a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                mVibratorTokens.put(token, v);
1707a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
1708a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1709a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1710a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        synchronized (v) {
1711a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            v.mVibrating = true;
1712a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            nativeVibrate(mPtr, deviceId, pattern, repeat, v.mTokenValue);
1713a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1714a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
1715a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1716a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    // Binder call
1717a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    @Override
1718a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    public void cancelVibrate(int deviceId, IBinder token) {
1719a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        VibratorToken v;
1720a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        synchronized (mVibratorLock) {
1721a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            v = mVibratorTokens.get(token);
1722a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            if (v == null || v.mDeviceId != deviceId) {
1723a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                return; // nothing to cancel
1724a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
1725a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1726a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1727a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        cancelVibrateIfNeeded(v);
1728a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
1729a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1730a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    void onVibratorTokenDied(VibratorToken v) {
1731a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        synchronized (mVibratorLock) {
1732a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mVibratorTokens.remove(v.mToken);
1733a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1734a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1735a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        cancelVibrateIfNeeded(v);
1736a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
1737a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1738a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    private void cancelVibrateIfNeeded(VibratorToken v) {
1739a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        synchronized (v) {
1740a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            if (v.mVibrating) {
1741a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                nativeCancelVibrate(mPtr, v.mDeviceId, v.mTokenValue);
1742a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                v.mVibrating = false;
1743a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
1744a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1745a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
1746a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
174719a560197950425f7e1856d5bd1216fbc680bf70Jun Mukai    // Binder call
174819a560197950425f7e1856d5bd1216fbc680bf70Jun Mukai    @Override
1749f9d9ce7705475874c82af04eb9b208a7fb556792Michael Wright    public void setPointerIconType(int iconId) {
1750f9d9ce7705475874c82af04eb9b208a7fb556792Michael Wright        nativeSetPointerIconType(mPtr, iconId);
175119a560197950425f7e1856d5bd1216fbc680bf70Jun Mukai    }
17521db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai
1753d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    // Binder call
1754d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    @Override
1755d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    public void setCustomPointerIcon(PointerIcon icon) {
1756b004b5137e12bffae9a3d3ae97440c8c24bdc07aMichael Wright        Preconditions.checkNotNull(icon);
1757d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai        nativeSetCustomPointerIcon(mPtr, icon);
1758d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    }
1759d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai
17604532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    @Override
1761d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
1762fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
17634532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
17644532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        pw.println("INPUT MANAGER (dumpsys input)\n");
17654532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        String dumpStr = nativeDump(mPtr);
1766e33348ba54cd68d6936cffd4507037c14d4b10c2Jeff Brown        if (dumpStr != null) {
1767e33348ba54cd68d6936cffd4507037c14d4b10c2Jeff Brown            pw.println(dumpStr);
1768e33348ba54cd68d6936cffd4507037c14d4b10c2Jeff Brown        }
1769d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        pw.println("  Keyboard Layouts:");
1770d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
1771d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            @Override
1772d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            public void visitKeyboardLayout(Resources resources,
1773d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    int keyboardLayoutResId, KeyboardLayout layout) {
1774d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                pw.println("    \"" + layout + "\": " + layout.getDescriptor());
1775d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            }
1776d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        });
1777d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        pw.println();
1778d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        synchronized(mDataStore) {
1779d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            mDataStore.dump(pw, "  ");
1780d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
1781d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    }
1782d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
1783d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    @Override
1784d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    public void onShellCommand(FileDescriptor in, FileDescriptor out,
1785354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn            FileDescriptor err, String[] args, ShellCallback callback,
1786354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn            ResultReceiver resultReceiver) {
1787354736e196ff79962b3ddb52619a674044d773e2Dianne Hackborn        (new Shell()).exec(this, in, out, err, args, callback, resultReceiver);
1788d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    }
1789d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
1790d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    public int onShellCommand(Shell shell, String cmd) {
1791d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        if (TextUtils.isEmpty(cmd)) {
1792d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            shell.onHelp();
1793d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            return 1;
1794d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
1795d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        if (cmd.equals("setlayout")) {
1796d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1797d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    "onShellCommand()")) {
1798d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1799d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            }
1800d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            InputMethodSubtypeHandle handle = new InputMethodSubtypeHandle(
1801d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    shell.getNextArgRequired(), Integer.parseInt(shell.getNextArgRequired()));
1802d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            String descriptor = shell.getNextArgRequired();
1803d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            int vid = Integer.decode(shell.getNextArgRequired());
1804d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            int pid = Integer.decode(shell.getNextArgRequired());
1805d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            InputDeviceIdentifier id = new InputDeviceIdentifier(descriptor, vid, pid);
1806d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            setKeyboardLayoutForInputDeviceInner(id, handle, shell.getNextArgRequired());
1807d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
1808d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        return 0;
180946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
1810b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown
1811d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
1812ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private boolean checkCallingPermission(String permission, String func) {
1813ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        // Quick check: if the calling permission is me, it's all okay.
1814ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (Binder.getCallingPid() == Process.myPid()) {
1815ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            return true;
1816ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
1817ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
1818ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
1819ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            return true;
1820ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
1821ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        String msg = "Permission Denial: " + func + " from pid="
1822ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                + Binder.getCallingPid()
1823ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                + ", uid=" + Binder.getCallingUid()
1824ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                + " requires " + permission;
1825ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        Slog.w(TAG, msg);
1826ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        return false;
1827ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
1828ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
18294532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection).
18302f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    @Override
183189ef0720ee8e0ac6ae1758faa917e4d6c9606fb4Jeff Brown    public void monitor() {
183289ef0720ee8e0ac6ae1758faa917e4d6c9606fb4Jeff Brown        synchronized (mInputFilterLock) { }
18334532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeMonitor(mPtr);
183489ef0720ee8e0ac6ae1758faa917e4d6c9606fb4Jeff Brown    }
183589ef0720ee8e0ac6ae1758faa917e4d6c9606fb4Jeff Brown
18364532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
18374532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private void notifyConfigurationChanged(long whenNanos) {
1838a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown        mWindowManagerCallbacks.notifyConfigurationChanged();
18394532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
18400029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
18414532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
1842af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void notifyInputDevicesChanged(InputDevice[] inputDevices) {
1843af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
1844af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (!mInputDevicesChangedPending) {
1845af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mInputDevicesChangedPending = true;
1846cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                mHandler.obtainMessage(MSG_DELIVER_INPUT_DEVICES_CHANGED,
1847cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        mInputDevices).sendToTarget();
1848af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
1849cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1850cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            mInputDevices = inputDevices;
1851af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
1852af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
1853af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1854af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    // Native callback.
1855bcc046af4ef171aa3aa3c6b64efb5cafc1e46cd3Jeff Brown    private void notifySwitch(long whenNanos, int switchValues, int switchMask) {
1856bcc046af4ef171aa3aa3c6b64efb5cafc1e46cd3Jeff Brown        if (DEBUG) {
1857bcc046af4ef171aa3aa3c6b64efb5cafc1e46cd3Jeff Brown            Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues)
1858bcc046af4ef171aa3aa3c6b64efb5cafc1e46cd3Jeff Brown                    + ", mask=" + Integer.toHexString(switchMask));
1859bcc046af4ef171aa3aa3c6b64efb5cafc1e46cd3Jeff Brown        }
1860bcc046af4ef171aa3aa3c6b64efb5cafc1e46cd3Jeff Brown
18612f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        if ((switchMask & SW_LID_BIT) != 0) {
18622f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner            final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
1863bcc046af4ef171aa3aa3c6b64efb5cafc1e46cd3Jeff Brown            mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
18645338428ddbe662283bf88171c7ca361d51d78da8Jeff Brown        }
18652f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
18663818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright        if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) {
18679e10d25732518f3d5740b5ede88f43cb28f51a14Michael Wright            final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) != 0);
18683818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright            mWindowManagerCallbacks.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
18693818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright        }
18703818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright
18712f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
18722f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner            mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
18732f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner                    switchMask);
18742f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        }
187539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
18769209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright        if ((switchMask & SW_TABLET_MODE_BIT) != 0) {
187739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            SomeArgs args = SomeArgs.obtain();
187839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            args.argi1 = (int) (whenNanos & 0xFFFFFFFF);
187939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            args.argi2 = (int) (whenNanos >> 32);
188039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            args.arg1 = Boolean.valueOf((switchValues & SW_TABLET_MODE_BIT) != 0);
188139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            mHandler.obtainMessage(MSG_DELIVER_TABLET_MODE_CHANGED,
188239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    args).sendToTarget();
188339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
18844532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
18850029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
18864532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
18874532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
1888a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown        mWindowManagerCallbacks.notifyInputChannelBroken(inputWindowHandle);
18894532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
18900029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
18914532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
18924532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private long notifyANR(InputApplicationHandle inputApplicationHandle,
1893bd181bb83282571eb793d2e4a48b4d19585de7f2Jeff Brown            InputWindowHandle inputWindowHandle, String reason) {
1894bd181bb83282571eb793d2e4a48b4d19585de7f2Jeff Brown        return mWindowManagerCallbacks.notifyANR(
1895bd181bb83282571eb793d2e4a48b4d19585de7f2Jeff Brown                inputApplicationHandle, inputWindowHandle, reason);
18964532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
18974532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
18984532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
18994532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    final boolean filterInputEvent(InputEvent event, int policyFlags) {
19004532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        synchronized (mInputFilterLock) {
19014532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            if (mInputFilter != null) {
1902c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                try {
1903c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                    mInputFilter.filterInputEvent(event, policyFlags);
1904c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                } catch (RemoteException e) {
1905c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                    /* ignore */
1906c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                }
19074532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                return false;
19080029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            }
19090029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        }
19104532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        event.recycle();
19114532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return true;
19120029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
19130029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
19144532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
1915037c33eae74bee2774897d969d48947f9abe254fJeff Brown    private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
1916037c33eae74bee2774897d969d48947f9abe254fJeff Brown        return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
19174532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
19180029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
19194532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
192070af00abf73160235d4efe114fcf4753007a8ff3Michael Wright    private int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
192170af00abf73160235d4efe114fcf4753007a8ff3Michael Wright        return mWindowManagerCallbacks.interceptMotionBeforeQueueingNonInteractive(
19222687550272ba061448f5d5b914700dc335299ee7Jeff Brown                whenNanos, policyFlags);
19234532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
19240029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
19254532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
19264532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private long interceptKeyBeforeDispatching(InputWindowHandle focus,
19274532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            KeyEvent event, int policyFlags) {
1928a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown        return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
19294532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
193056194ebec6212e229f4ccdaa4b187166d20013efJeff Brown
19314532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
19324532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
19334532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            KeyEvent event, int policyFlags) {
1934a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown        return mWindowManagerCallbacks.dispatchUnhandledKey(focus, event, policyFlags);
19354532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
193656194ebec6212e229f4ccdaa4b187166d20013efJeff Brown
19374532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
19384532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
19394532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return mContext.checkPermission(android.Manifest.permission.INJECT_EVENTS,
19404532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                injectorPid, injectorUid) == PackageManager.PERMISSION_GRANTED;
19414532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
1942fe50892af3b365806a767298dfd8e86447682581Jeff Brown
19434532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
19444532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getVirtualKeyQuietTimeMillis() {
19454532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return mContext.getResources().getInteger(
19464532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                com.android.internal.R.integer.config_virtualKeyQuietTimeMillis);
19474532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
1948fe50892af3b365806a767298dfd8e86447682581Jeff Brown
19494532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
19504532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private String[] getExcludedDeviceNames() {
19514532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        ArrayList<String> names = new ArrayList<String>();
19524532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
19534532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        // Read partner-provided list of excluded input devices
19544532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        XmlPullParser parser = null;
19554532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
19564532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH);
19574532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        FileReader confreader = null;
19584532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        try {
19594532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            confreader = new FileReader(confFile);
19604532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            parser = Xml.newPullParser();
19614532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            parser.setInput(confreader);
19624532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            XmlUtils.beginDocument(parser, "devices");
19634532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
19644532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            while (true) {
19654532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                XmlUtils.nextElement(parser);
19664532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                if (!"device".equals(parser.getName())) {
19674532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                    break;
19684532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                }
19694532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                String name = parser.getAttributeValue(null, "name");
19704532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                if (name != null) {
19714532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                    names.add(name);
197246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown                }
197346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            }
19744532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        } catch (FileNotFoundException e) {
19754532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            // It's ok if the file does not exist.
19764532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        } catch (Exception e) {
19774532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
19784532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        } finally {
19794532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            try { if (confreader != null) confreader.close(); } catch (IOException e) { }
198046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        }
1981a454767b09ecb7d25d00beae0e5a1fdd48605c63Jeff Brown
19824532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return names.toArray(new String[names.size()]);
19834532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
1984a454767b09ecb7d25d00beae0e5a1fdd48605c63Jeff Brown
19854532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
19864532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getKeyRepeatTimeout() {
19874532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return ViewConfiguration.getKeyRepeatTimeout();
19884532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
1989a454767b09ecb7d25d00beae0e5a1fdd48605c63Jeff Brown
19904532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
19914532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getKeyRepeatDelay() {
19924532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return ViewConfiguration.getKeyRepeatDelay();
19934532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
1994bb3fcba0caf697f1d238a2cbefdf1efe06eded99Jeff Brown
19954532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
19964532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getHoverTapTimeout() {
19974532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return ViewConfiguration.getHoverTapTimeout();
19984532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
1999214eaf48878bba00cbd5831871bcbd82632b6e34Jeff Brown
20004532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
20014532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getHoverTapSlop() {
20024532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return ViewConfiguration.getHoverTapSlop();
20034532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
2004214eaf48878bba00cbd5831871bcbd82632b6e34Jeff Brown
20054532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
20064532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getDoubleTapTimeout() {
20074532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return ViewConfiguration.getDoubleTapTimeout();
20084532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
2009214eaf48878bba00cbd5831871bcbd82632b6e34Jeff Brown
20104532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
20114532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getLongPressTimeout() {
20124532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return ViewConfiguration.getLongPressTimeout();
20134532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
20144532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
20154532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
20164532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getPointerLayer() {
2017a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown        return mWindowManagerCallbacks.getPointerLayer();
20184532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
20194532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
20204532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
20214532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private PointerIcon getPointerIcon() {
20224532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return PointerIcon.getDefaultIcon(mContext);
20234532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
20244532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
20256ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    // Native callback.
2026fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    private String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier) {
20276ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        if (!mSystemReady) {
20286ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            return null;
20296ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        }
20306ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
2031fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        String keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier);
20326ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        if (keyboardLayoutDescriptor == null) {
20336ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            return null;
20346ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        }
20356ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
20366ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        final String[] result = new String[2];
20376ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
20386ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            @Override
20390748342d2ed264c01384fbaa4446a702a8824813Michael Wright            public void visitKeyboardLayout(Resources resources,
20400748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    int keyboardLayoutResId, KeyboardLayout layout) {
20416ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                try {
20420748342d2ed264c01384fbaa4446a702a8824813Michael Wright                    result[0] = layout.getDescriptor();
20436ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                    result[1] = Streams.readFully(new InputStreamReader(
20442f0957607411b99810226ad38d59cf18718b86d0Jeff Brown                            resources.openRawResource(keyboardLayoutResId)));
20456ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                } catch (IOException ex) {
20466ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                } catch (NotFoundException ex) {
20476ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                }
20486ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            }
20496ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        });
20506ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        if (result[0] == null) {
20510748342d2ed264c01384fbaa4446a702a8824813Michael Wright            Slog.w(TAG, "Could not get keyboard layout with descriptor '"
20526ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                    + keyboardLayoutDescriptor + "'.");
20536ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            return null;
20546ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        }
20556ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        return result;
20566ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    }
20576ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
20585bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown    // Native callback.
20595bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown    private String getDeviceAlias(String uniqueId) {
20609631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie        if (BluetoothAdapter.checkBluetoothAddress(uniqueId)) {
20619631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie            // TODO(BT) mBluetoothService.getRemoteAlias(uniqueId)
20629631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie            return null;
20635bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown        }
20645bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown        return null;
20655bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown    }
20665bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown
20674532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    /**
20684532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown     * Callback interface implemented by the Window Manager.
20694532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown     */
2070a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown    public interface WindowManagerCallbacks {
20714532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public void notifyConfigurationChanged();
20724532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
20734532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
20744532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
20753818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright        public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered);
20763818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright
20774532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle);
20784532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
20794532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public long notifyANR(InputApplicationHandle inputApplicationHandle,
2080bd181bb83282571eb793d2e4a48b4d19585de7f2Jeff Brown                InputWindowHandle inputWindowHandle, String reason);
20814532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
2082037c33eae74bee2774897d969d48947f9abe254fJeff Brown        public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
20834532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
208470af00abf73160235d4efe114fcf4753007a8ff3Michael Wright        public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
20854532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
20864532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public long interceptKeyBeforeDispatching(InputWindowHandle focus,
20874532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                KeyEvent event, int policyFlags);
20884532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
20894532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
20904532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                KeyEvent event, int policyFlags);
20914532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
20924532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public int getPointerLayer();
20934532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
20944532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
20954532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    /**
20962f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner     * Callback interface implemented by WiredAccessoryObserver.
20972f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner     */
20982f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public interface WiredAccessoryCallbacks {
20992f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask);
21004a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent        public void systemReady();
21012f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    }
21022f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
21032f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    /**
2104af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Private handler for the input manager.
2105af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
2106af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final class InputManagerHandler extends Handler {
2107a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown        public InputManagerHandler(Looper looper) {
2108a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown            super(looper, null, true /*async*/);
2109a2910d0abbbe18ba1710dfd4a31af45769632255Jeff Brown        }
2110a2910d0abbbe18ba1710dfd4a31af45769632255Jeff Brown
2111af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        @Override
2112af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public void handleMessage(Message msg) {
2113af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            switch (msg.what) {
2114af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                case MSG_DELIVER_INPUT_DEVICES_CHANGED:
2115cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    deliverInputDevicesChanged((InputDevice[])msg.obj);
2116cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    break;
2117d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                case MSG_SWITCH_KEYBOARD_LAYOUT: {
2118d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    SomeArgs args = (SomeArgs)msg.obj;
2119d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    handleSwitchKeyboardLayout((InputDeviceIdentifier)args.arg1,
2120d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                            (InputMethodSubtypeHandle)args.arg2);
2121cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    break;
2122d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                }
2123cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                case MSG_RELOAD_KEYBOARD_LAYOUTS:
2124cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    reloadKeyboardLayouts();
2125cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    break;
2126cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                case MSG_UPDATE_KEYBOARD_LAYOUTS:
2127cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    updateKeyboardLayouts();
2128cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    break;
2129cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                case MSG_RELOAD_DEVICE_ALIASES:
2130cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    reloadDeviceAliases();
2131af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    break;
2132b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa                case MSG_DELIVER_TABLET_MODE_CHANGED: {
213339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    SomeArgs args = (SomeArgs) msg.obj;
213439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    long whenNanos = (args.argi1 & 0xFFFFFFFFl) | ((long) args.argi2 << 32);
213539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    boolean inTabletMode = (boolean) args.arg1;
213639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    deliverTabletModeChanged(whenNanos, inTabletMode);
213739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    break;
2138b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa                }
2139b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa                case MSG_INPUT_METHOD_SUBTYPE_CHANGED: {
2140b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa                    final int userId = msg.arg1;
2141b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa                    final SomeArgs args = (SomeArgs) msg.obj;
2142b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa                    final InputMethodInfo inputMethodInfo = (InputMethodInfo) args.arg1;
2143b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa                    final InputMethodSubtype subtype = (InputMethodSubtype) args.arg2;
2144b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa                    args.recycle();
2145b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa                    handleSwitchInputMethodSubtype(userId, inputMethodInfo, subtype);
2146b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa                    break;
2147b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa                }
2148af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
2149af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
2150af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
2151af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
2152af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
21534532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown     * Hosting interface for input filters to call back into the input manager.
21544532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown     */
2155c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov    private final class InputFilterHost extends IInputFilterHost.Stub {
21564532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        private boolean mDisconnected;
21574532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
21584532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public void disconnectLocked() {
21594532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            mDisconnected = true;
216083c09685f2e62bc3cf7e71bc61d903f4b9ccaeb4Jeff Brown        }
2161b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown
21622f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        @Override
21634532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public void sendInputEvent(InputEvent event, int policyFlags) {
21644532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            if (event == null) {
21654532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                throw new IllegalArgumentException("event must not be null");
21664532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            }
21674532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
21684532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            synchronized (mInputFilterLock) {
21694532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                if (!mDisconnected) {
2170ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown                    nativeInjectInputEvent(mPtr, event, Display.DEFAULT_DISPLAY, 0, 0,
2171ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                            InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0,
21724532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                            policyFlags | WindowManagerPolicy.FLAG_FILTERED);
21734532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                }
21744532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            }
2175b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown        }
217646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
21779f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
21789f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    private static final class KeyboardLayoutDescriptor {
21799f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        public String packageName;
21809f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        public String receiverName;
21819f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        public String keyboardLayoutName;
21829f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
21839f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        public static String format(String packageName,
21849f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                String receiverName, String keyboardName) {
21859f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return packageName + "/" + receiverName + "/" + keyboardName;
21869f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
21879f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
21889f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        public static KeyboardLayoutDescriptor parse(String descriptor) {
21899f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            int pos = descriptor.indexOf('/');
21909f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            if (pos < 0 || pos + 1 == descriptor.length()) {
21919f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                return null;
21929f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            }
21939f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            int pos2 = descriptor.indexOf('/', pos + 1);
21949f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            if (pos2 < pos + 2 || pos2 + 1 == descriptor.length()) {
21959f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                return null;
21969f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            }
21979f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
21989f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            KeyboardLayoutDescriptor result = new KeyboardLayoutDescriptor();
21999f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            result.packageName = descriptor.substring(0, pos);
22009f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            result.receiverName = descriptor.substring(pos + 1, pos2);
22019f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            result.keyboardLayoutName = descriptor.substring(pos2 + 1);
22029f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return result;
22039f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
22049f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    }
2205af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
22066ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    private interface KeyboardLayoutVisitor {
22070748342d2ed264c01384fbaa4446a702a8824813Michael Wright        void visitKeyboardLayout(Resources resources,
22080748342d2ed264c01384fbaa4446a702a8824813Michael Wright                int keyboardLayoutResId, KeyboardLayout layout);
22096ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    }
22106ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
2211af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final class InputDevicesChangedListenerRecord implements DeathRecipient {
2212af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        private final int mPid;
2213af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        private final IInputDevicesChangedListener mListener;
2214af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
2215af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public InputDevicesChangedListenerRecord(int pid, IInputDevicesChangedListener listener) {
2216af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mPid = pid;
2217af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mListener = listener;
2218af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
2219af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
2220af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        @Override
2221af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public void binderDied() {
2222af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (DEBUG) {
2223af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                Slog.d(TAG, "Input devices changed listener for pid " + mPid + " died.");
2224af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
2225af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            onInputDevicesChangedListenerDied(mPid);
2226af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
2227af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
2228af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public void notifyInputDevicesChanged(int[] info) {
2229af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            try {
2230af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mListener.onInputDevicesChanged(info);
2231af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            } catch (RemoteException ex) {
2232af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                Slog.w(TAG, "Failed to notify process "
2233af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        + mPid + " that input devices changed, assuming it died.", ex);
2234af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                binderDied();
2235af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
2236af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
2237af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
2238a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
223939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private final class TabletModeChangedListenerRecord implements DeathRecipient {
224039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        private final int mPid;
224139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        private final ITabletModeChangedListener mListener;
224239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
224339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        public TabletModeChangedListenerRecord(int pid, ITabletModeChangedListener listener) {
224439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            mPid = pid;
224539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            mListener = listener;
224639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
224739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
224839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        @Override
224939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        public void binderDied() {
225039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            if (DEBUG) {
225139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                Slog.d(TAG, "Tablet mode changed listener for pid " + mPid + " died.");
225239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
225339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            onTabletModeChangedListenerDied(mPid);
225439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
225539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
225639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        public void notifyTabletModeChanged(long whenNanos, boolean inTabletMode) {
225739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            try {
225839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                mListener.onTabletModeChanged(whenNanos, inTabletMode);
225939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            } catch (RemoteException ex) {
226039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                Slog.w(TAG, "Failed to notify process " + mPid +
226139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                        " that tablet mode changed, assuming it died.", ex);
226239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                binderDied();
226339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
226439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
226539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
226639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
2267a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    private final class VibratorToken implements DeathRecipient {
2268a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public final int mDeviceId;
2269a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public final IBinder mToken;
2270a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public final int mTokenValue;
2271a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
2272a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public boolean mVibrating;
2273a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
2274a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public VibratorToken(int deviceId, IBinder token, int tokenValue) {
2275a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mDeviceId = deviceId;
2276a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mToken = token;
2277a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mTokenValue = tokenValue;
2278a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
2279a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
2280a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
2281a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public void binderDied() {
2282a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            if (DEBUG) {
2283a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                Slog.d(TAG, "Vibrator token died.");
2284a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
2285a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            onVibratorTokenDied(this);
2286a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
2287a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
22884ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown
2289d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    private class Shell extends ShellCommand {
2290d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        @Override
2291d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        public int onCommand(String cmd) {
2292d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            return onShellCommand(this, cmd);
2293d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
2294d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
2295d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        @Override
2296d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        public void onHelp() {
2297d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            final PrintWriter pw = getOutPrintWriter();
2298d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            pw.println("Input manager commands:");
2299d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            pw.println("  help");
2300d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            pw.println("    Print this help text.");
2301d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            pw.println("");
2302d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            pw.println("  setlayout IME_ID IME_SUPTYPE_HASH_CODE"
2303d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    + " DEVICE_DESCRIPTOR VENDOR_ID PRODUCT_ID KEYBOARD_DESCRIPTOR");
2304d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            pw.println("    Sets a keyboard layout for a given IME subtype and input device pair");
2305d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
2306d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    }
2307d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
23084ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown    private final class LocalService extends InputManagerInternal {
23094ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown        @Override
2310b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon        public void setDisplayViewports(DisplayViewport defaultViewport,
2311b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon                DisplayViewport externalTouchViewport,
2312b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon                List<DisplayViewport> virtualTouchViewports) {
2313b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon            setDisplayViewportsInternal(defaultViewport, externalTouchViewport,
2314b0608636a29bcec8ecb4391cd50f29f68b3e7e81Santos Cordon                    virtualTouchViewports);
23154ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown        }
2316ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown
2317ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown        @Override
2318ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown        public boolean injectInputEvent(InputEvent event, int displayId, int mode) {
2319ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown            return injectInputEventInternal(event, displayId, mode);
2320ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown        }
2321037c33eae74bee2774897d969d48947f9abe254fJeff Brown
2322037c33eae74bee2774897d969d48947f9abe254fJeff Brown        @Override
2323037c33eae74bee2774897d969d48947f9abe254fJeff Brown        public void setInteractive(boolean interactive) {
2324037c33eae74bee2774897d969d48947f9abe254fJeff Brown            nativeSetInteractive(mPtr, interactive);
2325037c33eae74bee2774897d969d48947f9abe254fJeff Brown        }
2326b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa
2327b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa        @Override
2328b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa        public void onInputMethodSubtypeChanged(int userId,
2329b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa                @Nullable InputMethodInfo inputMethodInfo, @Nullable InputMethodSubtype subtype) {
2330b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa            final SomeArgs someArgs = SomeArgs.obtain();
2331b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa            someArgs.arg1 = inputMethodInfo;
2332b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa            someArgs.arg2 = subtype;
2333b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa            mHandler.obtainMessage(MSG_INPUT_METHOD_SUBTYPE_CHANGED, userId, 0, someArgs)
2334b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa                    .sendToTarget();
2335b097b8262ba22040d46d6e212a31b758b7023307Yohei Yukawa        }
2336112d05678b7de53da8948f62dd2e968274f62244Andrii Kulian
2337112d05678b7de53da8948f62dd2e968274f62244Andrii Kulian        @Override
2338112d05678b7de53da8948f62dd2e968274f62244Andrii Kulian        public void toggleCapsLock(int deviceId) {
2339112d05678b7de53da8948f62dd2e968274f62244Andrii Kulian            nativeToggleCapsLock(mPtr, deviceId);
2340112d05678b7de53da8948f62dd2e968274f62244Andrii Kulian        }
23419918234dcf9e115560144d0218682dd5050843bcAdrian Roos
23429918234dcf9e115560144d0218682dd5050843bcAdrian Roos        @Override
23439918234dcf9e115560144d0218682dd5050843bcAdrian Roos        public void setPulseGestureEnabled(boolean enabled) {
23449918234dcf9e115560144d0218682dd5050843bcAdrian Roos            if (mDoubleTouchGestureEnableFile != null) {
23459918234dcf9e115560144d0218682dd5050843bcAdrian Roos                FileWriter writer = null;
23469918234dcf9e115560144d0218682dd5050843bcAdrian Roos                try {
23479918234dcf9e115560144d0218682dd5050843bcAdrian Roos                    writer = new FileWriter(mDoubleTouchGestureEnableFile);
23489918234dcf9e115560144d0218682dd5050843bcAdrian Roos                    writer.write(enabled ? "1" : "0");
23499918234dcf9e115560144d0218682dd5050843bcAdrian Roos                } catch (IOException e) {
23509918234dcf9e115560144d0218682dd5050843bcAdrian Roos                    Log.wtf(TAG, "Unable to setPulseGestureEnabled", e);
23519918234dcf9e115560144d0218682dd5050843bcAdrian Roos                } finally {
23529918234dcf9e115560144d0218682dd5050843bcAdrian Roos                    IoUtils.closeQuietly(writer);
23539918234dcf9e115560144d0218682dd5050843bcAdrian Roos                }
23549918234dcf9e115560144d0218682dd5050843bcAdrian Roos            }
23559918234dcf9e115560144d0218682dd5050843bcAdrian Roos        }
23564ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown    }
235746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
2358