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
19ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brownimport android.view.Display;
20cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brownimport com.android.internal.R;
2146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport com.android.internal.util.XmlUtils;
224ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brownimport com.android.server.DisplayThread;
234ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brownimport com.android.server.LocalServices;
2489ef0720ee8e0ac6ae1758faa917e4d6c9606fb4Jeff Brownimport com.android.server.Watchdog;
2546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
2646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport org.xmlpull.v1.XmlPullParser;
2746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
28a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brownimport android.Manifest;
29cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brownimport android.app.Notification;
30cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brownimport android.app.NotificationManager;
31cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brownimport android.app.PendingIntent;
325bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brownimport android.bluetooth.BluetoothAdapter;
335bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brownimport android.bluetooth.BluetoothDevice;
346ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brownimport android.content.BroadcastReceiver;
359f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.ComponentName;
3646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport android.content.Context;
379f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.Intent;
386ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brownimport android.content.IntentFilter;
399f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.pm.ActivityInfo;
408ebac231966e27364e5d463b63540a0527d40c4bMichael Wrightimport android.content.pm.ApplicationInfo;
41349703effce5acc53ed96f7ed8556131f0c65e18Jeff Brownimport android.content.pm.PackageManager;
429f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.pm.ResolveInfo;
439f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.pm.PackageManager.NameNotFoundException;
449f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.res.Resources;
456ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brownimport android.content.res.Resources.NotFoundException;
469f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.res.TypedArray;
479f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.content.res.XmlResourceParser;
481a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brownimport android.database.ContentObserver;
494ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brownimport android.hardware.display.DisplayViewport;
50af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.hardware.input.IInputDevicesChangedListener;
51c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganovimport android.hardware.input.IInputManager;
52fb290df3c9a6f37ec050163029e25844de2f8590RoboErikimport android.hardware.input.InputDeviceIdentifier;
53ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.hardware.input.InputManager;
544ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brownimport android.hardware.input.InputManagerInternal;
559f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.hardware.input.KeyboardLayout;
56d6396d67201fb2b64d13070324bb115c9c23b08aJason Gereckeimport android.hardware.input.TouchCalibration;
574532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brownimport android.os.Binder;
589f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.os.Bundle;
5946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport android.os.Environment;
604532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brownimport android.os.Handler;
61af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.IBinder;
62a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brownimport android.os.Looper;
63af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.Message;
6405dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brownimport android.os.MessageQueue;
65ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.Process;
66af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.RemoteException;
6750cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackbornimport android.os.UserHandle;
681a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brownimport android.provider.Settings;
691a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brownimport android.provider.Settings.SettingNotFoundException;
709f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.util.Log;
7146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport android.util.Slog;
72af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.util.SparseArray;
7346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport android.util.Xml;
74c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganovimport android.view.IInputFilter;
75c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganovimport android.view.IInputFilterHost;
7646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport android.view.InputChannel;
778d60866e2100db70ecf0502c14768a384514d7e9Jeff Brownimport android.view.InputDevice;
786ec402b5ae33c8927694d8522b4cc6a5c8ba974eJeff Brownimport android.view.InputEvent;
791f2451007c660091b7b090c1ea332f9044515d2dJeff Brownimport android.view.KeyEvent;
802352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brownimport android.view.PointerIcon;
81d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gereckeimport android.view.Surface;
82a454767b09ecb7d25d00beae0e5a1fdd48605c63Jeff Brownimport android.view.ViewConfiguration;
830029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brownimport android.view.WindowManagerPolicy;
84cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brownimport android.widget.Toast;
8546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
8646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport java.io.File;
874532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brownimport java.io.FileDescriptor;
8846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport java.io.FileNotFoundException;
8946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport java.io.FileReader;
9046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport java.io.IOException;
916ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brownimport java.io.InputStreamReader;
9246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport java.io.PrintWriter;
9346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownimport java.util.ArrayList;
949f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport java.util.HashMap;
95cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brownimport java.util.HashSet;
96a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown
976ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brownimport libcore.io.Streams;
98a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brownimport libcore.util.Objects;
9946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
10046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown/*
10146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown * Wraps the C++ InputManager and provides its callbacks.
10246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown */
103d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brownpublic class InputManagerService extends IInputManager.Stub
1044ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown        implements Watchdog.Monitor {
10546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    static final String TAG = "InputManager";
1061b9ba578f1d2acf86c75110e89ae3d2e0434483aJeff Brown    static final boolean DEBUG = false;
1074532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
1084532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
1094532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
110af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final int MSG_DELIVER_INPUT_DEVICES_CHANGED = 1;
111cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 2;
112cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 3;
113cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 4;
114cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private static final int MSG_RELOAD_DEVICE_ALIASES = 5;
115af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1164532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Pointer to native input manager service object.
1177e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private final long mPtr;
118b699726018a0049665d8ad6b90dbc5af0e18f135Jeff Brown
11946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    private final Context mContext;
120af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final InputManagerHandler mHandler;
121a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown
122a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown    private WindowManagerCallbacks mWindowManagerCallbacks;
1232f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    private WiredAccessoryCallbacks mWiredAccessoryCallbacks;
1246ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    private boolean mSystemReady;
125cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private NotificationManager mNotificationManager;
126af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
127a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown    // Persistent data store.  Must be locked each time during use.
128a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown    private final PersistentDataStore mDataStore = new PersistentDataStore();
129af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
130af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    // List of currently registered input devices changed listeners by process id.
131af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private Object mInputDevicesLock = new Object();
132af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private boolean mInputDevicesChangedPending; // guarded by mInputDevicesLock
133af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private InputDevice[] mInputDevices = new InputDevice[0];
134af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final SparseArray<InputDevicesChangedListenerRecord> mInputDevicesChangedListeners =
135af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            new SparseArray<InputDevicesChangedListenerRecord>(); // guarded by mInputDevicesLock
136af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final ArrayList<InputDevicesChangedListenerRecord>
137af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mTempInputDevicesChangedListenersToNotify =
138af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    new ArrayList<InputDevicesChangedListenerRecord>(); // handler thread only
139cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private final ArrayList<InputDevice>
140cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            mTempFullKeyboards = new ArrayList<InputDevice>(); // handler thread only
141cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private boolean mKeyboardLayoutNotificationShown;
142cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private PendingIntent mKeyboardLayoutIntent;
143cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private Toast mSwitchedKeyboardLayoutToast;
144af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
145a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    // State for vibrator tokens.
146a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    private Object mVibratorLock = new Object();
147a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    private HashMap<IBinder, VibratorToken> mVibratorTokens =
148a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            new HashMap<IBinder, VibratorToken>();
149a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    private int mNextVibratorTokenValue;
150a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
151af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    // State for the currently installed input filter.
152af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    final Object mInputFilterLock = new Object();
153c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov    IInputFilter mInputFilter; // guarded by mInputFilterLock
154af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    InputFilterHost mInputFilterHost; // guarded by mInputFilterLock
1554532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
1567e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native long nativeInit(InputManagerService service,
1574532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            Context context, MessageQueue messageQueue);
1587e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeStart(long ptr);
1597e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeSetDisplayViewport(long ptr, boolean external,
160d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            int displayId, int rotation,
161d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            int logicalLeft, int logicalTop, int logicalRight, int logicalBottom,
16283d616a9c7b9505153d258511eb5c16b552e268dJeff Brown            int physicalLeft, int physicalTop, int physicalRight, int physicalBottom,
16383d616a9c7b9505153d258511eb5c16b552e268dJeff Brown            int deviceWidth, int deviceHeight);
164d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
1657e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native int nativeGetScanCodeState(long ptr,
1664532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            int deviceId, int sourceMask, int scanCode);
1677e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native int nativeGetKeyCodeState(long ptr,
1684532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            int deviceId, int sourceMask, int keyCode);
1697e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native int nativeGetSwitchState(long ptr,
1704532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            int deviceId, int sourceMask, int sw);
1717e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native boolean nativeHasKeys(long ptr,
1724532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists);
1737e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeRegisterInputChannel(long ptr, InputChannel inputChannel,
174928e054931d357326613c78e62f4d850b7c442ffJeff Brown            InputWindowHandle inputWindowHandle, boolean monitor);
1757e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel);
1767e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeSetInputFilterEnabled(long ptr, boolean enable);
177ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown    private static native int nativeInjectInputEvent(long ptr, InputEvent event, int displayId,
1780029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
1790029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            int policyFlags);
1807e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
1817e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen);
1827e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeSetSystemUiVisibility(long ptr, int visibility);
1837e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeSetFocusedApplication(long ptr,
1844532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            InputApplicationHandle application);
1857e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native boolean nativeTransferTouchFocus(long ptr,
1864532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            InputChannel fromChannel, InputChannel toChannel);
1877e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeSetPointerSpeed(long ptr, int speed);
1887e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeSetShowTouches(long ptr, boolean enabled);
189037c33eae74bee2774897d969d48947f9abe254fJeff Brown    private static native void nativeSetInteractive(long ptr, boolean interactive);
190857aa7be880c53d78f72a9f227cbdf72ee68d587Jason Gerecke    private static native void nativeReloadCalibration(long ptr);
1917e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeVibrate(long ptr, int deviceId, long[] pattern,
192a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            int repeat, int token);
1937e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeCancelVibrate(long ptr, int deviceId, int token);
1947e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeReloadKeyboardLayouts(long ptr);
1957e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeReloadDeviceAliases(long ptr);
1967e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native String nativeDump(long ptr);
1977e2a9dcf1a4044ed3f81c5b736b5027231395b73Ashok Bhat    private static native void nativeMonitor(long ptr);
198ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
1997fbdc84e87dd3a0e196b9803bb04495d11e9cb8aJeff Brown    // Input event injection constants defined in InputDispatcher.h.
200ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
201ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1;
202ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private static final int INPUT_EVENT_INJECTION_FAILED = 2;
203ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3;
204ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
205ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    // Maximum number of milliseconds to wait for input event injection.
206ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
207ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
2086d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    // Key states (may be returned by queries about the current state of a
2096d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    // particular key code, scan code or switch).
2102f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
2116d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /** The key state is unknown or the requested key itself is not supported. */
2126d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public static final int KEY_STATE_UNKNOWN = -1;
2136d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
2146d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /** The key is up. /*/
2156d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public static final int KEY_STATE_UP = 0;
2166d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
2176d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /** The key is down. */
2186d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public static final int KEY_STATE_DOWN = 1;
2196d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
2206d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /** The key is down but is a virtual key press that is being emulated by the system. */
2216d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public static final int KEY_STATE_VIRTUAL = 2;
2226d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
223c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown    /** Scan code: Mouse / trackball button. */
224c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown    public static final int BTN_MOUSE = 0x110;
225c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown
2262f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    // Switch code values must match bionic/libc/kernel/common/linux/input.h
227c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown    /** Switch code: Lid switch.  When set, lid is shut. */
228c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown    public static final int SW_LID = 0x00;
229c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown
230c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown    /** Switch code: Keypad slide.  When set, keyboard is exposed. */
231c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown    public static final int SW_KEYPAD_SLIDE = 0x0a;
232c458ce98ce42c00b98afe00670f822814f3da572Jeff Brown
2332f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    /** Switch code: Headphone.  When set, headphone is inserted. */
2342f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_HEADPHONE_INSERT = 0x02;
2352f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
2362f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    /** Switch code: Microphone.  When set, microphone is inserted. */
2372f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_MICROPHONE_INSERT = 0x04;
2382f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
23943cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund    /** Switch code: Line out.  When set, Line out (hi-Z) is inserted. */
24043cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund    public static final int SW_LINEOUT_INSERT = 0x06;
24143cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund
2422f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    /** Switch code: Headphone/Microphone Jack.  When set, something is inserted. */
2432f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_JACK_PHYSICAL_INSERT = 0x07;
2442f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
2453818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright    /** Switch code: Camera lens cover. When set the lens is covered. */
2463818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright    public static final int SW_CAMERA_LENS_COVER = 0x09;
2473818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright
2482f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_LID_BIT = 1 << SW_LID;
2492f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
2502f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_HEADPHONE_INSERT_BIT = 1 << SW_HEADPHONE_INSERT;
2512f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_MICROPHONE_INSERT_BIT = 1 << SW_MICROPHONE_INSERT;
25243cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund    public static final int SW_LINEOUT_INSERT_BIT = 1 << SW_LINEOUT_INSERT;
2532f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_JACK_PHYSICAL_INSERT_BIT = 1 << SW_JACK_PHYSICAL_INSERT;
2542f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public static final int SW_JACK_BITS =
25543cc8bbbbd5e6418cdfa0fa4b26c9f5c3a28c029Jon Eklund            SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_JACK_PHYSICAL_INSERT_BIT | SW_LINEOUT_INSERT_BIT;
2563818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright    public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER;
2572f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
2582f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */
2592f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    final boolean mUseDevInputEventForAudioJack;
2602f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
2614ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown    public InputManagerService(Context context) {
26246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        this.mContext = context;
2634ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
26405dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown
2652f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        mUseDevInputEventForAudioJack =
2662f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
2672f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
2682f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner                + mUseDevInputEventForAudioJack);
2694532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
2704ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown
2714ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown        LocalServices.addService(InputManagerInternal.class, new LocalService());
27246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
2731a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown
274a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown    public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
275a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown        mWindowManagerCallbacks = callbacks;
276a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown    }
277a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown
2782f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public void setWiredAccessoryCallbacks(WiredAccessoryCallbacks callbacks) {
2792f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        mWiredAccessoryCallbacks = callbacks;
2802f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    }
2812f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
28246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    public void start() {
28346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        Slog.i(TAG, "Starting input manager");
2844532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeStart(mPtr);
2854532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
2864532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        // Add ourself to the Watchdog monitors.
2874532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        Watchdog.getInstance().addMonitor(this);
2881a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown
2891a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown        registerPointerSpeedSettingObserver();
290daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        registerShowTouchesSettingObserver();
291daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown
292d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        mContext.registerReceiver(new BroadcastReceiver() {
293d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            @Override
294d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            public void onReceive(Context context, Intent intent) {
295d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                updatePointerSpeedFromSettings();
296d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                updateShowTouchesFromSettings();
297d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            }
298d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
299d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown
3001a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown        updatePointerSpeedFromSettings();
301daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        updateShowTouchesFromSettings();
30246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
3036ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
3049631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie    // TODO(BT) Pass in paramter for bluetooth system
305a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public void systemRunning() {
3066ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        if (DEBUG) {
3076ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            Slog.d(TAG, "System ready.");
3086ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        }
309cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        mNotificationManager = (NotificationManager)mContext.getSystemService(
310cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                Context.NOTIFICATION_SERVICE);
3116ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        mSystemReady = true;
3126ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
3136ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
3146ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
3156ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
31669b07161bebdb2c726e3a826c2268866f1a94517Jeff Brown        filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
3176ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        filter.addDataScheme("package");
3186ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        mContext.registerReceiver(new BroadcastReceiver() {
3196ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            @Override
3206ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            public void onReceive(Context context, Intent intent) {
321cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                updateKeyboardLayouts();
3226ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            }
3236ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        }, filter, null, mHandler);
3245bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown
3255bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown        filter = new IntentFilter(BluetoothDevice.ACTION_ALIAS_CHANGED);
3265bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown        mContext.registerReceiver(new BroadcastReceiver() {
3275bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown            @Override
3285bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown            public void onReceive(Context context, Intent intent) {
3295bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown                reloadDeviceAliases();
3305bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown            }
3315bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown        }, filter, null, mHandler);
3325bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown
333cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        mHandler.sendEmptyMessage(MSG_RELOAD_DEVICE_ALIASES);
334cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        mHandler.sendEmptyMessage(MSG_UPDATE_KEYBOARD_LAYOUTS);
3354a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent
3364a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent        if (mWiredAccessoryCallbacks != null) {
3374a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent            mWiredAccessoryCallbacks.systemReady();
3384a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent        }
3396ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    }
3406ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
3416ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    private void reloadKeyboardLayouts() {
342cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (DEBUG) {
343cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            Slog.d(TAG, "Reloading keyboard layouts.");
344cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
3456ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        nativeReloadKeyboardLayouts(mPtr);
3466ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    }
3476ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
3485bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown    private void reloadDeviceAliases() {
349cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (DEBUG) {
350cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            Slog.d(TAG, "Reloading device names.");
351cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
3525bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown        nativeReloadDeviceAliases(mPtr);
3535bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown    }
3545bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown
3554ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown    private void setDisplayViewportsInternal(DisplayViewport defaultViewport,
356d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            DisplayViewport externalTouchViewport) {
357d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        if (defaultViewport.valid) {
358d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            setDisplayViewport(false, defaultViewport);
35946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        }
360d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
361d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        if (externalTouchViewport.valid) {
362d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            setDisplayViewport(true, externalTouchViewport);
363d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        } else if (defaultViewport.valid) {
364d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            setDisplayViewport(true, defaultViewport);
365b699726018a0049665d8ad6b90dbc5af0e18f135Jeff Brown        }
36646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
3674ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
368d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    private void setDisplayViewport(boolean external, DisplayViewport viewport) {
369d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        nativeSetDisplayViewport(mPtr, external,
370d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                viewport.displayId, viewport.orientation,
371d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                viewport.logicalFrame.left, viewport.logicalFrame.top,
372d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                viewport.logicalFrame.right, viewport.logicalFrame.bottom,
373d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                viewport.physicalFrame.left, viewport.physicalFrame.top,
37483d616a9c7b9505153d258511eb5c16b552e268dJeff Brown                viewport.physicalFrame.right, viewport.physicalFrame.bottom,
37583d616a9c7b9505153d258511eb5c16b552e268dJeff Brown                viewport.deviceWidth, viewport.deviceHeight);
37646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
377ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
3786d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /**
3796d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * Gets the current state of a key or button by key code.
3806d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param deviceId The input device id, or -1 to consult all devices.
3816d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
3826d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * consider all input sources.  An input device is consulted if at least one of its
3836d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * non-class input source bits matches the specified source mask.
3846d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param keyCode The key code to check.
3856d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @return The key state.
3866d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     */
3876d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) {
3884532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return nativeGetKeyCodeState(mPtr, deviceId, sourceMask, keyCode);
38946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
3902f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
3916d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /**
3926d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * Gets the current state of a key or button by scan code.
3936d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param deviceId The input device id, or -1 to consult all devices.
3946d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
3956d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * consider all input sources.  An input device is consulted if at least one of its
3966d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * non-class input source bits matches the specified source mask.
3976d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param scanCode The scan code to check.
3986d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @return The key state.
3996d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     */
4006d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public int getScanCodeState(int deviceId, int sourceMask, int scanCode) {
4014532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return nativeGetScanCodeState(mPtr, deviceId, sourceMask, scanCode);
40246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
403fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
4046d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /**
4056d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * Gets the current state of a switch by switch code.
4066d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param deviceId The input device id, or -1 to consult all devices.
4076d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
4086d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * consider all input sources.  An input device is consulted if at least one of its
4096d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * non-class input source bits matches the specified source mask.
4106d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param switchCode The switch code to check.
4116d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @return The switch state.
4126d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     */
4136d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public int getSwitchState(int deviceId, int sourceMask, int switchCode) {
4144532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return nativeGetSwitchState(mPtr, deviceId, sourceMask, switchCode);
41546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
41646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
4176d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    /**
4186d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * Determines whether the specified key codes are supported by a particular device.
4196d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param deviceId The input device id, or -1 to consult all devices.
4206d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
4216d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * consider all input sources.  An input device is consulted if at least one of its
4226d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * non-class input source bits matches the specified source mask.
4236d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param keyCodes The array of key codes to check.
4246d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @param keyExists An array at least as large as keyCodes whose entries will be set
4256d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * to true or false based on the presence or absence of support for the corresponding
4266d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * key codes.
4276d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     * @return True if the lookup was successful, false otherwise.
4286d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown     */
4299f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
4306d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) {
43146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        if (keyCodes == null) {
43246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            throw new IllegalArgumentException("keyCodes must not be null.");
43346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        }
4346d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown        if (keyExists == null || keyExists.length < keyCodes.length) {
4356d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown            throw new IllegalArgumentException("keyExists must not be null and must be at "
4366d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown                    + "least as large as keyCodes.");
43746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        }
438fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
4394532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return nativeHasKeys(mPtr, deviceId, sourceMask, keyCodes, keyExists);
44046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
441fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
442a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    /**
443a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     * Creates an input channel that will receive all input from the input dispatcher.
444a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     * @param inputChannelName The input channel name.
445a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     * @return The input channel.
446a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     */
447a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    public InputChannel monitorInput(String inputChannelName) {
448a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown        if (inputChannelName == null) {
449a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown            throw new IllegalArgumentException("inputChannelName must not be null.");
450a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown        }
451fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
452a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown        InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
4534532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeRegisterInputChannel(mPtr, inputChannels[0], null, true);
454a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown        inputChannels[0].dispose(); // don't need to retain the Java object reference
455a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown        return inputChannels[1];
456a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    }
457a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown
458a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    /**
459a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     * Registers an input channel so that it can be used as an input event target.
460a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     * @param inputChannel The input channel to register.
461928e054931d357326613c78e62f4d850b7c442ffJeff Brown     * @param inputWindowHandle The handle of the input window associated with the
462928e054931d357326613c78e62f4d850b7c442ffJeff Brown     * input channel, or null if none.
463a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     */
464928e054931d357326613c78e62f4d850b7c442ffJeff Brown    public void registerInputChannel(InputChannel inputChannel,
465928e054931d357326613c78e62f4d850b7c442ffJeff Brown            InputWindowHandle inputWindowHandle) {
46646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        if (inputChannel == null) {
46746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            throw new IllegalArgumentException("inputChannel must not be null.");
46846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        }
469fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
4704532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
47146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
472fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
473a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown    /**
474a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     * Unregisters an input channel.
475a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     * @param inputChannel The input channel to unregister.
476a41ca77fabe1c7ad12ebb9b69b9e786c07d49fa0Jeff Brown     */
47746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    public void unregisterInputChannel(InputChannel inputChannel) {
47846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        if (inputChannel == null) {
47946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            throw new IllegalArgumentException("inputChannel must not be null.");
48046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        }
481fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
4824532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeUnregisterInputChannel(mPtr, inputChannel);
48346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
4840029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
4850029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    /**
4860029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * Sets an input filter that will receive all input events before they are dispatched.
4870029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * The input filter may then reinterpret input events or inject new ones.
4880029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     *
4890029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * To ensure consistency, the input dispatcher automatically drops all events
4900029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * in progress whenever an input filter is installed or uninstalled.  After an input
4910029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * filter is uninstalled, it can no longer send input events unless it is reinstalled.
4920029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * Any events it attempts to send after it has been uninstalled will be dropped.
4930029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     *
4940029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     * @param filter The input filter, or null to remove the current filter.
4950029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown     */
496c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov    public void setInputFilter(IInputFilter filter) {
4970029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        synchronized (mInputFilterLock) {
498c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov            final IInputFilter oldFilter = mInputFilter;
4990029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            if (oldFilter == filter) {
5000029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                return; // nothing to do
5010029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            }
5020029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
5030029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            if (oldFilter != null) {
5040029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                mInputFilter = null;
5050029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                mInputFilterHost.disconnectLocked();
5060029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                mInputFilterHost = null;
507c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                try {
508c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                    oldFilter.uninstall();
509c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                } catch (RemoteException re) {
510c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                    /* ignore */
511c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                }
5120029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            }
5130029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
5140029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            if (filter != null) {
5150029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                mInputFilter = filter;
5160029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown                mInputFilterHost = new InputFilterHost();
517c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                try {
518c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                    filter.install(mInputFilterHost);
519c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                } catch (RemoteException re) {
520c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                    /* ignore */
521c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                }
5220029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            }
5230029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
5244532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            nativeSetInputFilterEnabled(mPtr, filter != null);
5250029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        }
5260029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
5270029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
5289f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
529ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public boolean injectInputEvent(InputEvent event, int mode) {
530ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown        return injectInputEventInternal(event, Display.DEFAULT_DISPLAY, mode);
531ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown    }
532ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown
533ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown    private boolean injectInputEventInternal(InputEvent event, int displayId, int mode) {
5347fbdc84e87dd3a0e196b9803bb04495d11e9cb8aJeff Brown        if (event == null) {
5357fbdc84e87dd3a0e196b9803bb04495d11e9cb8aJeff Brown            throw new IllegalArgumentException("event must not be null");
5367fbdc84e87dd3a0e196b9803bb04495d11e9cb8aJeff Brown        }
537ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (mode != InputManager.INJECT_INPUT_EVENT_MODE_ASYNC
538ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
539ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
540ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("mode is invalid");
5417fbdc84e87dd3a0e196b9803bb04495d11e9cb8aJeff Brown        }
5426ec402b5ae33c8927694d8522b4cc6a5c8ba974eJeff Brown
543ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        final int pid = Binder.getCallingPid();
544ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        final int uid = Binder.getCallingUid();
545ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        final long ident = Binder.clearCallingIdentity();
546ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        final int result;
547ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
548ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown            result = nativeInjectInputEvent(mPtr, event, displayId, pid, uid, mode,
549ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                    INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
550ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } finally {
551ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            Binder.restoreCallingIdentity(ident);
552ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
553ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        switch (result) {
554ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
555ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                Slog.w(TAG, "Input event injection from pid " + pid + " permission denied.");
556ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                throw new SecurityException(
557ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                        "Injecting to another application requires INJECT_EVENTS permission");
558ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            case INPUT_EVENT_INJECTION_SUCCEEDED:
559ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                return true;
560ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            case INPUT_EVENT_INJECTION_TIMED_OUT:
561ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                Slog.w(TAG, "Input event injection from pid " + pid + " timed out.");
562ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                return false;
563ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            case INPUT_EVENT_INJECTION_FAILED:
564ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            default:
565ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                Slog.w(TAG, "Input event injection from pid " + pid + " failed.");
566ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                return false;
567ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
56846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
5690029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
5708d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown    /**
5718d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown     * Gets information about the input device with the specified id.
5722f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner     * @param deviceId The device id.
5738d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown     * @return The input device or null if not found.
5748d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown     */
5759f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
5768d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown    public InputDevice getInputDevice(int deviceId) {
577af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
578af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int count = mInputDevices.length;
579af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < count; i++) {
580af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                final InputDevice inputDevice = mInputDevices[i];
581af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                if (inputDevice.getId() == deviceId) {
582af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    return inputDevice;
583af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                }
584af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
585af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
586af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        return null;
5878d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown    }
588af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
5898d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown    /**
5908d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown     * Gets the ids of all input devices in the system.
5918d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown     * @return The input device ids.
5928d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown     */
5939f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
5948d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown    public int[] getInputDeviceIds() {
595af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
596af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int count = mInputDevices.length;
597af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int[] ids = new int[count];
598af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < count; i++) {
599af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                ids[i] = mInputDevices[i].getId();
600af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
601af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            return ids;
602af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
603af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
604af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
605daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown    /**
606daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown     * Gets all input devices in the system.
607daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown     * @return The array of input devices.
608daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown     */
609daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown    public InputDevice[] getInputDevices() {
610daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown        synchronized (mInputDevicesLock) {
611daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown            return mInputDevices;
612daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown        }
613daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown    }
614daa3753a04699724d2cfe824ac1f5a266d643a05Jeff Brown
615af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    @Override // Binder call
616af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public void registerInputDevicesChangedListener(IInputDevicesChangedListener listener) {
617af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (listener == null) {
618af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            throw new IllegalArgumentException("listener must not be null");
619af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
620af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
621af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
622af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int callingPid = Binder.getCallingPid();
623af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (mInputDevicesChangedListeners.get(callingPid) != null) {
624af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                throw new SecurityException("The calling process has already "
625af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        + "registered an InputDevicesChangedListener.");
626af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
627af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
628af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            InputDevicesChangedListenerRecord record =
629af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    new InputDevicesChangedListenerRecord(callingPid, listener);
630af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            try {
631af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                IBinder binder = listener.asBinder();
632af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                binder.linkToDeath(record, 0);
633af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            } catch (RemoteException ex) {
634af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                // give up
635af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                throw new RuntimeException(ex);
636af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
637af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
638af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mInputDevicesChangedListeners.put(callingPid, record);
639af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
640af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
641af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
642af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void onInputDevicesChangedListenerDied(int pid) {
643af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
644af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mInputDevicesChangedListeners.remove(pid);
645af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
646af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
647af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
648af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    // Must be called on handler.
649cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private void deliverInputDevicesChanged(InputDevice[] oldInputDevices) {
650cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        // Scan for changes.
651cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        int numFullKeyboardsAdded = 0;
652af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        mTempInputDevicesChangedListenersToNotify.clear();
653cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        mTempFullKeyboards.clear();
654af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        final int numListeners;
655af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        final int[] deviceIdAndGeneration;
656af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
657af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (!mInputDevicesChangedPending) {
658af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                return;
659af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
660af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mInputDevicesChangedPending = false;
661af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
662af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            numListeners = mInputDevicesChangedListeners.size();
663af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < numListeners; i++) {
664af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mTempInputDevicesChangedListenersToNotify.add(
665af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        mInputDevicesChangedListeners.valueAt(i));
666af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
667af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
668af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int numDevices = mInputDevices.length;
669af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            deviceIdAndGeneration = new int[numDevices * 2];
670af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < numDevices; i++) {
671af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                final InputDevice inputDevice = mInputDevices[i];
672af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                deviceIdAndGeneration[i * 2] = inputDevice.getId();
673af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                deviceIdAndGeneration[i * 2 + 1] = inputDevice.getGeneration();
674cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
6757e4ff4b986d626493afb676dd4824d2b3663260aJeff Brown                if (!inputDevice.isVirtual() && inputDevice.isFullKeyboard()) {
676cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    if (!containsInputDeviceWithDescriptor(oldInputDevices,
677cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                            inputDevice.getDescriptor())) {
678cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        mTempFullKeyboards.add(numFullKeyboardsAdded++, inputDevice);
679cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    } else {
680cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        mTempFullKeyboards.add(inputDevice);
681cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    }
682cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
683af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
684af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
685af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
686cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        // Notify listeners.
687af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        for (int i = 0; i < numListeners; i++) {
688af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mTempInputDevicesChangedListenersToNotify.get(i).notifyInputDevicesChanged(
689af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    deviceIdAndGeneration);
690af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
691cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        mTempInputDevicesChangedListenersToNotify.clear();
692cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
693cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        // Check for missing keyboard layouts.
694cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (mNotificationManager != null) {
695cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            final int numFullKeyboards = mTempFullKeyboards.size();
696cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            boolean missingLayoutForExternalKeyboard = false;
697cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            boolean missingLayoutForExternalKeyboardAdded = false;
698c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright            boolean multipleMissingLayoutsForExternalKeyboardsAdded = false;
699c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright            InputDevice keyboardMissingLayout = null;
700cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            synchronized (mDataStore) {
701cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                for (int i = 0; i < numFullKeyboards; i++) {
702cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    final InputDevice inputDevice = mTempFullKeyboards.get(i);
70386aaca682479dea3a4c232edda13cba98e783572Michael Wright                    final String layout =
70486aaca682479dea3a4c232edda13cba98e783572Michael Wright                            getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier());
70586aaca682479dea3a4c232edda13cba98e783572Michael Wright                    if (layout == null) {
706cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        missingLayoutForExternalKeyboard = true;
707cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        if (i < numFullKeyboardsAdded) {
708cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                            missingLayoutForExternalKeyboardAdded = true;
709c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                            if (keyboardMissingLayout == null) {
710c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                                keyboardMissingLayout = inputDevice;
711c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                            } else {
712c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                                multipleMissingLayoutsForExternalKeyboardsAdded = true;
713c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                            }
714cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        }
715cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    }
716cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
717cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
718cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            if (missingLayoutForExternalKeyboard) {
719cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                if (missingLayoutForExternalKeyboardAdded) {
720c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                    if (multipleMissingLayoutsForExternalKeyboardsAdded) {
721c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                        // We have more than one keyboard missing a layout, so drop the
722c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                        // user at the generic input methods page so they can pick which
723c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                        // one to set.
724c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                        showMissingKeyboardLayoutNotification(null);
725c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                    } else {
726c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                        showMissingKeyboardLayoutNotification(keyboardMissingLayout);
727c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                    }
728cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
729cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            } else if (mKeyboardLayoutNotificationShown) {
730cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                hideMissingKeyboardLayoutNotification();
731cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
732cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
733cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        mTempFullKeyboards.clear();
734cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
735cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
736857aa7be880c53d78f72a9f227cbdf72ee68d587Jason Gerecke    @Override // Binder call & native callback
737d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke    public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor,
738d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke            int surfaceRotation) {
739d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        if (inputDeviceDescriptor == null) {
740d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
741d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
742d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke
743d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        synchronized (mDataStore) {
744d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke            return mDataStore.getTouchCalibration(inputDeviceDescriptor, surfaceRotation);
745d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
746d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke    }
747d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke
748d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke    @Override // Binder call
749d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke    public void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation,
750d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            TouchCalibration calibration) {
751d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        if (!checkCallingPermission(android.Manifest.permission.SET_INPUT_CALIBRATION,
752d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke                "setTouchCalibrationForInputDevice()")) {
753d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            throw new SecurityException("Requires SET_INPUT_CALIBRATION permission");
754d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
755d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        if (inputDeviceDescriptor == null) {
756d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
757d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
758d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        if (calibration == null) {
759d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            throw new IllegalArgumentException("calibration must not be null");
760d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
761d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke        if (surfaceRotation < Surface.ROTATION_0 || surfaceRotation > Surface.ROTATION_270) {
762d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke            throw new IllegalArgumentException("surfaceRotation value out of bounds");
763d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke        }
764d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke
765d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        synchronized (mDataStore) {
766d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            try {
767d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke                if (mDataStore.setTouchCalibration(inputDeviceDescriptor, surfaceRotation,
768d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke                        calibration)) {
769857aa7be880c53d78f72a9f227cbdf72ee68d587Jason Gerecke                    nativeReloadCalibration(mPtr);
770857aa7be880c53d78f72a9f227cbdf72ee68d587Jason Gerecke                }
771d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            } finally {
772d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke                mDataStore.saveIfNeeded();
773d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke            }
774d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
775d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke    }
776d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke
777cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    // Must be called on handler.
778c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright    private void showMissingKeyboardLayoutNotification(InputDevice device) {
779cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (!mKeyboardLayoutNotificationShown) {
780c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright            final Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
781c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright            if (device != null) {
782c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                intent.putExtra(Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, device.getIdentifier());
783cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
784c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
785c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
786c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                    | Intent.FLAG_ACTIVITY_CLEAR_TOP);
787c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright            final PendingIntent keyboardLayoutIntent = PendingIntent.getActivityAsUser(mContext, 0,
788c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                    intent, 0, null, UserHandle.CURRENT);
789cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
790cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            Resources r = mContext.getResources();
791cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            Notification notification = new Notification.Builder(mContext)
792cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    .setContentTitle(r.getString(
793cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                            R.string.select_keyboard_layout_notification_title))
794cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    .setContentText(r.getString(
795cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                            R.string.select_keyboard_layout_notification_message))
796c93fbd1fae3d461f2f8a7c039b15f953ed6a8b50Michael Wright                    .setContentIntent(keyboardLayoutIntent)
797cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    .setSmallIcon(R.drawable.ic_settings_language)
798cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    .setPriority(Notification.PRIORITY_LOW)
799255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek                    .setColor(mContext.getResources().getColor(
800255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek                            com.android.internal.R.color.system_notification_accent_color))
801cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    .build();
80250cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn            mNotificationManager.notifyAsUser(null,
80350cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    R.string.select_keyboard_layout_notification_title,
80450cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    notification, UserHandle.ALL);
805cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            mKeyboardLayoutNotificationShown = true;
806cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
807cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
808cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
809cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    // Must be called on handler.
810cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private void hideMissingKeyboardLayoutNotification() {
811cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (mKeyboardLayoutNotificationShown) {
812cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            mKeyboardLayoutNotificationShown = false;
81350cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn            mNotificationManager.cancelAsUser(null,
81450cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    R.string.select_keyboard_layout_notification_title,
81550cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    UserHandle.ALL);
816cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
817cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
818cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
819cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    // Must be called on handler.
820cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private void updateKeyboardLayouts() {
821cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        // Scan all input devices state for keyboard layouts that have been uninstalled.
822cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        final HashSet<String> availableKeyboardLayouts = new HashSet<String>();
823cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
824cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            @Override
8258ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            public void visitKeyboardLayout(Resources resources, String descriptor, String label,
8268ebac231966e27364e5d463b63540a0527d40c4bMichael Wright                    String collection, int keyboardLayoutResId, int priority) {
827cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                availableKeyboardLayouts.add(descriptor);
828cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
829cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        });
830cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        synchronized (mDataStore) {
831cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            try {
832cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                mDataStore.removeUninstalledKeyboardLayouts(availableKeyboardLayouts);
833cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            } finally {
834cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                mDataStore.saveIfNeeded();
835cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
836cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
837cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
838cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        // Reload keyboard layouts.
839cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        reloadKeyboardLayouts();
840cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
841cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
842cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private static boolean containsInputDeviceWithDescriptor(InputDevice[] inputDevices,
843cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            String descriptor) {
844cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        final int numDevices = inputDevices.length;
845cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        for (int i = 0; i < numDevices; i++) {
846cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            final InputDevice inputDevice = inputDevices[i];
847cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            if (inputDevice.getDescriptor().equals(descriptor)) {
848cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                return true;
849cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
850cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
851cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        return false;
8528d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown    }
8539f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
8549f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
8559f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public KeyboardLayout[] getKeyboardLayouts() {
8566ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        final ArrayList<KeyboardLayout> list = new ArrayList<KeyboardLayout>();
8576ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
8586ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            @Override
8598ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            public void visitKeyboardLayout(Resources resources, String descriptor, String label,
8608ebac231966e27364e5d463b63540a0527d40c4bMichael Wright                    String collection, int keyboardLayoutResId, int priority) {
8618ebac231966e27364e5d463b63540a0527d40c4bMichael Wright                list.add(new KeyboardLayout(descriptor, label, collection, priority));
8626ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            }
8636ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        });
8649f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        return list.toArray(new KeyboardLayout[list.size()]);
8659f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    }
8669f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
8679f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
8689f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
8699f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        if (keyboardLayoutDescriptor == null) {
8709f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
8719f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
8729f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
8736ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        final KeyboardLayout[] result = new KeyboardLayout[1];
8746ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
8756ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            @Override
8768ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            public void visitKeyboardLayout(Resources resources, String descriptor,
8778ebac231966e27364e5d463b63540a0527d40c4bMichael Wright                    String label, String collection, int keyboardLayoutResId, int priority) {
8788ebac231966e27364e5d463b63540a0527d40c4bMichael Wright                result[0] = new KeyboardLayout(descriptor, label, collection, priority);
8796ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            }
8806ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        });
8816ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        if (result[0] == null) {
8826ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            Log.w(TAG, "Could not get keyboard layout with descriptor '"
8836ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                    + keyboardLayoutDescriptor + "'.");
8849f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
8856ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        return result[0];
8866ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    }
8879f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
8886ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    private void visitAllKeyboardLayouts(KeyboardLayoutVisitor visitor) {
8899f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        final PackageManager pm = mContext.getPackageManager();
8906ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        Intent intent = new Intent(InputManager.ACTION_QUERY_KEYBOARD_LAYOUTS);
8916ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent,
8926ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                PackageManager.GET_META_DATA)) {
8938ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            final ActivityInfo activityInfo = resolveInfo.activityInfo;
8948ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            final int priority = resolveInfo.priority;
8958ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            visitKeyboardLayoutsInPackage(pm, activityInfo, null, priority, visitor);
8966ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        }
8976ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    }
8986ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
8996ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    private void visitKeyboardLayout(String keyboardLayoutDescriptor,
9006ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            KeyboardLayoutVisitor visitor) {
9016ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        KeyboardLayoutDescriptor d = KeyboardLayoutDescriptor.parse(keyboardLayoutDescriptor);
9026ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        if (d != null) {
9036ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            final PackageManager pm = mContext.getPackageManager();
9046ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            try {
9056ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                ActivityInfo receiver = pm.getReceiverInfo(
9066ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                        new ComponentName(d.packageName, d.receiverName),
9076ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                        PackageManager.GET_META_DATA);
9088ebac231966e27364e5d463b63540a0527d40c4bMichael Wright                visitKeyboardLayoutsInPackage(pm, receiver, d.keyboardLayoutName, 0, visitor);
9096ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            } catch (NameNotFoundException ex) {
9106ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            }
9119f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
9129f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    }
9139f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
9146ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    private void visitKeyboardLayoutsInPackage(PackageManager pm, ActivityInfo receiver,
9158ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            String keyboardName, int requestedPriority, KeyboardLayoutVisitor visitor) {
9169f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        Bundle metaData = receiver.metaData;
9179f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        if (metaData == null) {
9186ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            return;
9199f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
9209f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
9219f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        int configResId = metaData.getInt(InputManager.META_DATA_KEYBOARD_LAYOUTS);
9229f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        if (configResId == 0) {
9239f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            Log.w(TAG, "Missing meta-data '" + InputManager.META_DATA_KEYBOARD_LAYOUTS
9249f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    + "' on receiver " + receiver.packageName + "/" + receiver.name);
9256ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            return;
9269f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
9279f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
928d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown        CharSequence receiverLabel = receiver.loadLabel(pm);
929d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown        String collection = receiverLabel != null ? receiverLabel.toString() : "";
9308ebac231966e27364e5d463b63540a0527d40c4bMichael Wright        int priority;
9318ebac231966e27364e5d463b63540a0527d40c4bMichael Wright        if ((receiver.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
9328ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            priority = requestedPriority;
9338ebac231966e27364e5d463b63540a0527d40c4bMichael Wright        } else {
9348ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            priority = 0;
9358ebac231966e27364e5d463b63540a0527d40c4bMichael Wright        }
936d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown
9379f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        try {
9389f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            Resources resources = pm.getResourcesForApplication(receiver.applicationInfo);
9399f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            XmlResourceParser parser = resources.getXml(configResId);
9409f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            try {
9419f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                XmlUtils.beginDocument(parser, "keyboard-layouts");
9429f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
9439f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                for (;;) {
9449f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    XmlUtils.nextElement(parser);
9459f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    String element = parser.getName();
9469f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    if (element == null) {
9479f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                        break;
9489f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    }
9499f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    if (element.equals("keyboard-layout")) {
9509f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                        TypedArray a = resources.obtainAttributes(
9519f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                parser, com.android.internal.R.styleable.KeyboardLayout);
9529f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                        try {
9539f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                            String name = a.getString(
9549f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                    com.android.internal.R.styleable.KeyboardLayout_name);
9559f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                            String label = a.getString(
9569f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                    com.android.internal.R.styleable.KeyboardLayout_label);
9572f0957607411b99810226ad38d59cf18718b86d0Jeff Brown                            int keyboardLayoutResId = a.getResourceId(
9582f0957607411b99810226ad38d59cf18718b86d0Jeff Brown                                    com.android.internal.R.styleable.KeyboardLayout_keyboardLayout,
9592f0957607411b99810226ad38d59cf18718b86d0Jeff Brown                                    0);
9602f0957607411b99810226ad38d59cf18718b86d0Jeff Brown                            if (name == null || label == null || keyboardLayoutResId == 0) {
9612f0957607411b99810226ad38d59cf18718b86d0Jeff Brown                                Log.w(TAG, "Missing required 'name', 'label' or 'keyboardLayout' "
9629f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                        + "attributes in keyboard layout "
9639f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                        + "resource from receiver "
9649f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                        + receiver.packageName + "/" + receiver.name);
9659f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                            } else {
9669f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                String descriptor = KeyboardLayoutDescriptor.format(
9679f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                        receiver.packageName, receiver.name, name);
9686ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                                if (keyboardName == null || name.equals(keyboardName)) {
9696ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                                    visitor.visitKeyboardLayout(resources, descriptor,
9708ebac231966e27364e5d463b63540a0527d40c4bMichael Wright                                            label, collection, keyboardLayoutResId, priority);
9719f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                }
9729f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                            }
9739f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                        } finally {
9749f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                            a.recycle();
9759f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                        }
9769f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    } else {
9779f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                        Log.w(TAG, "Skipping unrecognized element '" + element
9789f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                + "' in keyboard layout resource from receiver "
9799f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                                + receiver.packageName + "/" + receiver.name);
9809f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    }
9819f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                }
9829f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            } finally {
9839f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                parser.close();
9849f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            }
9859f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (Exception ex) {
9866ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            Log.w(TAG, "Could not parse keyboard layout resource from receiver "
9879f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                    + receiver.packageName + "/" + receiver.name, ex);
9889f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
9899f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    }
9909f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
991fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    /**
992fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * Builds a layout descriptor for the vendor/product. This returns the
993fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * descriptor for ids that aren't useful (such as the default 0, 0).
994fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     */
995fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    private String getLayoutDescriptor(InputDeviceIdentifier identifier) {
996fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier == null || identifier.getDescriptor() == null) {
997fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            throw new IllegalArgumentException("identifier and descriptor must not be null");
998fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        }
999fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
1000fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier.getVendorId() == 0 && identifier.getProductId() == 0) {
1001fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            return identifier.getDescriptor();
10029f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
1003fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        StringBuilder bob = new StringBuilder();
1004fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        bob.append("vendor:").append(identifier.getVendorId());
1005fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        bob.append(",product:").append(identifier.getProductId());
1006fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        return bob.toString();
1007fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    }
1008fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
1009fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    @Override // Binder call
1010fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
10119f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
1012fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        String key = getLayoutDescriptor(identifier);
1013a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown        synchronized (mDataStore) {
1014fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            String layout = null;
1015fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            // try loading it using the layout descriptor if we have it
1016fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            layout = mDataStore.getCurrentKeyboardLayout(key);
1017fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            if (layout == null && !key.equals(identifier.getDescriptor())) {
1018fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                // if it doesn't exist fall back to the device descriptor
1019fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                layout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1020fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            }
1021fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            if (DEBUG) {
1022fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                Slog.d(TAG, "Loaded keyboard layout id for " + key + " and got "
1023fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                        + layout);
1024fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            }
1025fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            return layout;
1026a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown        }
10279f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    }
10289f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
10299f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
1030fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
10319f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            String keyboardLayoutDescriptor) {
10329f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1033cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                "setCurrentKeyboardLayoutForInputDevice()")) {
10349f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
10359f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
1036cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (keyboardLayoutDescriptor == null) {
1037cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1038cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1039cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1040fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        String key = getLayoutDescriptor(identifier);
1041cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        synchronized (mDataStore) {
1042cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            try {
1043fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                if (mDataStore.setCurrentKeyboardLayout(key, keyboardLayoutDescriptor)) {
1044fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                    if (DEBUG) {
1045fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                        Slog.d(TAG, "Saved keyboard layout using " + key);
1046fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                    }
1047cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1048cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
1049cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            } finally {
1050cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                mDataStore.saveIfNeeded();
1051cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
1052cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1053cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
10549f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
1055cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    @Override // Binder call
1056fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public String[] getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
1057fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        String key = getLayoutDescriptor(identifier);
1058cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        synchronized (mDataStore) {
1059fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            String[] layouts = mDataStore.getKeyboardLayouts(key);
1060fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            if ((layouts == null || layouts.length == 0)
1061fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                    && !key.equals(identifier.getDescriptor())) {
1062fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                layouts = mDataStore.getKeyboardLayouts(identifier.getDescriptor());
1063fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            }
1064fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            return layouts;
1065cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1066cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
1067cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1068cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    @Override // Binder call
1069fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
1070cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            String keyboardLayoutDescriptor) {
1071cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1072cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                "addKeyboardLayoutForInputDevice()")) {
1073cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1074cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1075cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (keyboardLayoutDescriptor == null) {
1076cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1077cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1078cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1079fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        String key = getLayoutDescriptor(identifier);
1080a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown        synchronized (mDataStore) {
1081a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown            try {
1082fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
1083fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
1084fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                    oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1085fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                }
1086fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                if (mDataStore.addKeyboardLayout(key, keyboardLayoutDescriptor)
1087cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        && !Objects.equal(oldLayout,
1088fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                                mDataStore.getCurrentKeyboardLayout(key))) {
1089cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1090cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
1091a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown            } finally {
1092a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown                mDataStore.saveIfNeeded();
1093a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown            }
1094a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown        }
1095cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
10969f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
1097cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    @Override // Binder call
1098fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
1099cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            String keyboardLayoutDescriptor) {
1100cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1101cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                "removeKeyboardLayoutForInputDevice()")) {
1102cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1103cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1104cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (keyboardLayoutDescriptor == null) {
1105cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1106cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1107cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1108fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        String key = getLayoutDescriptor(identifier);
1109cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        synchronized (mDataStore) {
1110cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            try {
1111fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
1112fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
1113fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                    oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1114fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                }
1115fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                boolean removed = mDataStore.removeKeyboardLayout(key, keyboardLayoutDescriptor);
1116fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                if (!key.equals(identifier.getDescriptor())) {
1117fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                    // We need to remove from both places to ensure it is gone
1118fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                    removed |= mDataStore.removeKeyboardLayout(identifier.getDescriptor(),
1119fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                            keyboardLayoutDescriptor);
1120fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                }
1121fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                if (removed && !Objects.equal(oldLayout,
1122fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                                mDataStore.getCurrentKeyboardLayout(key))) {
1123cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1124cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
1125cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            } finally {
1126cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                mDataStore.saveIfNeeded();
1127cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
1128cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
1129cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
1130cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1131cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    public void switchKeyboardLayout(int deviceId, int direction) {
1132cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, deviceId, direction).sendToTarget();
1133cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
1134cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1135cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    // Must be called on handler.
1136cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    private void handleSwitchKeyboardLayout(int deviceId, int direction) {
1137cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        final InputDevice device = getInputDevice(deviceId);
1138cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (device != null) {
1139cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            final boolean changed;
1140cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            final String keyboardLayoutDescriptor;
1141fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
1142fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            String key = getLayoutDescriptor(device.getIdentifier());
1143cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            synchronized (mDataStore) {
1144cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                try {
1145fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                    changed = mDataStore.switchKeyboardLayout(key, direction);
1146cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    keyboardLayoutDescriptor = mDataStore.getCurrentKeyboardLayout(
1147fb290df3c9a6f37ec050163029e25844de2f8590RoboErik                            key);
1148cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                } finally {
1149cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    mDataStore.saveIfNeeded();
1150cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
1151cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
1152cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1153cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            if (changed) {
1154cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                if (mSwitchedKeyboardLayoutToast != null) {
1155cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    mSwitchedKeyboardLayoutToast.cancel();
1156cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    mSwitchedKeyboardLayoutToast = null;
1157cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
1158cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                if (keyboardLayoutDescriptor != null) {
1159cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    KeyboardLayout keyboardLayout = getKeyboardLayout(keyboardLayoutDescriptor);
1160cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    if (keyboardLayout != null) {
1161cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        mSwitchedKeyboardLayoutToast = Toast.makeText(
1162cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                                mContext, keyboardLayout.getLabel(), Toast.LENGTH_SHORT);
1163cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        mSwitchedKeyboardLayoutToast.show();
1164cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    }
1165cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
1166cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1167cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                reloadKeyboardLayouts();
11689f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            }
11699f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
11706ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    }
11719f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
11729302c8796fc4dcda08d4bd1e11733848fd4fafafJeff Brown    public void setInputWindows(InputWindowHandle[] windowHandles) {
11734532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeSetInputWindows(mPtr, windowHandles);
1174349703effce5acc53ed96f7ed8556131f0c65e18Jeff Brown    }
1175fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
11769302c8796fc4dcda08d4bd1e11733848fd4fafafJeff Brown    public void setFocusedApplication(InputApplicationHandle application) {
11774532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeSetFocusedApplication(mPtr, application);
1178349703effce5acc53ed96f7ed8556131f0c65e18Jeff Brown    }
1179fb290df3c9a6f37ec050163029e25844de2f8590RoboErik
1180349703effce5acc53ed96f7ed8556131f0c65e18Jeff Brown    public void setInputDispatchMode(boolean enabled, boolean frozen) {
11814532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeSetInputDispatchMode(mPtr, enabled, frozen);
1182349703effce5acc53ed96f7ed8556131f0c65e18Jeff Brown    }
118305dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown
118405dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown    public void setSystemUiVisibility(int visibility) {
11854532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeSetSystemUiVisibility(mPtr, visibility);
118605dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown    }
118705dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown
1188e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown    /**
1189e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * Atomically transfers touch focus from one window to another as identified by
1190e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * their input channels.  It is possible for multiple windows to have
1191e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * touch focus if they support split touch dispatch
1192e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * {@link android.view.WindowManager.LayoutParams#FLAG_SPLIT_TOUCH} but this
1193e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * method only transfers touch focus of the specified window without affecting
1194e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * other windows that may also have touch focus at the same time.
1195e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * @param fromChannel The channel of a window that currently has touch focus.
1196e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * @param toChannel The channel of the window that should receive touch focus in
1197e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * place of the first.
1198e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * @return True if the transfer was successful.  False if the window with the
1199e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     * specified channel did not actually have touch focus at the time of the request.
1200e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown     */
1201e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown    public boolean transferTouchFocus(InputChannel fromChannel, InputChannel toChannel) {
1202e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown        if (fromChannel == null) {
1203e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown            throw new IllegalArgumentException("fromChannel must not be null.");
1204e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown        }
1205e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown        if (toChannel == null) {
1206e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown            throw new IllegalArgumentException("toChannel must not be null.");
1207e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown        }
12084532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return nativeTransferTouchFocus(mPtr, fromChannel, toChannel);
1209e65041225ec0bbc3d67a3b70cdc6d598a5760043Jeff Brown    }
121005dc66ada6b61a6bdf806ffaa62617ac5394695dJeff Brown
12119f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    @Override // Binder call
1212ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public void tryPointerSpeed(int speed) {
1213ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED,
1214ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                "tryPointerSpeed()")) {
1215ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new SecurityException("Requires SET_POINTER_SPEED permission");
1216ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
1217ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
12189f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        if (speed < InputManager.MIN_POINTER_SPEED || speed > InputManager.MAX_POINTER_SPEED) {
12199f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            throw new IllegalArgumentException("speed out of range");
12209f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
12219f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
1222ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        setPointerSpeedUnchecked(speed);
12231a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown    }
12241a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown
12251a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown    public void updatePointerSpeedFromSettings() {
1226ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        int speed = getPointerSpeedSetting();
1227ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        setPointerSpeedUnchecked(speed);
1228ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
1229ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
1230ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private void setPointerSpeedUnchecked(int speed) {
1231ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        speed = Math.min(Math.max(speed, InputManager.MIN_POINTER_SPEED),
1232ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                InputManager.MAX_POINTER_SPEED);
1233ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        nativeSetPointerSpeed(mPtr, speed);
12341a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown    }
12351a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown
12361a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown    private void registerPointerSpeedSettingObserver() {
12371a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown        mContext.getContentResolver().registerContentObserver(
12381a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown                Settings.System.getUriFor(Settings.System.POINTER_SPEED), true,
12394532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                new ContentObserver(mHandler) {
12401a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown                    @Override
12411a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown                    public void onChange(boolean selfChange) {
12421a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown                        updatePointerSpeedFromSettings();
12431a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown                    }
1244d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                }, UserHandle.USER_ALL);
12451a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown    }
12461a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown
1247ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private int getPointerSpeedSetting() {
1248ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        int speed = InputManager.DEFAULT_POINTER_SPEED;
12491a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown        try {
1250d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            speed = Settings.System.getIntForUser(mContext.getContentResolver(),
1251d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                    Settings.System.POINTER_SPEED, UserHandle.USER_CURRENT);
12521a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown        } catch (SettingNotFoundException snfe) {
12531a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown        }
12541a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown        return speed;
12551a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown    }
12561a84fd1fb7a51f3fe4f8865e1cdd09f3490f696cJeff Brown
1257daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown    public void updateShowTouchesFromSettings() {
1258daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        int setting = getShowTouchesSetting(0);
12594532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeSetShowTouches(mPtr, setting != 0);
1260daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown    }
1261daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown
1262daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown    private void registerShowTouchesSettingObserver() {
1263daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        mContext.getContentResolver().registerContentObserver(
1264daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown                Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), true,
12654532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                new ContentObserver(mHandler) {
1266daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown                    @Override
1267daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown                    public void onChange(boolean selfChange) {
1268daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown                        updateShowTouchesFromSettings();
1269daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown                    }
1270d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                }, UserHandle.USER_ALL);
1271daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown    }
1272daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown
1273daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown    private int getShowTouchesSetting(int defaultValue) {
1274daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        int result = defaultValue;
1275daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        try {
1276d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            result = Settings.System.getIntForUser(mContext.getContentResolver(),
1277d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                    Settings.System.SHOW_TOUCHES, UserHandle.USER_CURRENT);
1278daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        } catch (SettingNotFoundException snfe) {
1279daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        }
1280daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown        return result;
1281daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown    }
1282daf4a127ba2af82a3fb477044b872719a0ab1827Jeff Brown
1283a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    // Binder call
1284a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    @Override
1285a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    public void vibrate(int deviceId, long[] pattern, int repeat, IBinder token) {
1286a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        if (repeat >= pattern.length) {
1287a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            throw new ArrayIndexOutOfBoundsException();
1288a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1289a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1290a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        VibratorToken v;
1291a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        synchronized (mVibratorLock) {
1292a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            v = mVibratorTokens.get(token);
1293a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            if (v == null) {
1294a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                v = new VibratorToken(deviceId, token, mNextVibratorTokenValue++);
1295a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                try {
1296a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                    token.linkToDeath(v, 0);
1297a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                } catch (RemoteException ex) {
1298a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                    // give up
1299a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                    throw new RuntimeException(ex);
1300a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                }
1301a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                mVibratorTokens.put(token, v);
1302a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
1303a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1304a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1305a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        synchronized (v) {
1306a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            v.mVibrating = true;
1307a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            nativeVibrate(mPtr, deviceId, pattern, repeat, v.mTokenValue);
1308a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1309a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
1310a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1311a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    // Binder call
1312a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    @Override
1313a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    public void cancelVibrate(int deviceId, IBinder token) {
1314a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        VibratorToken v;
1315a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        synchronized (mVibratorLock) {
1316a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            v = mVibratorTokens.get(token);
1317a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            if (v == null || v.mDeviceId != deviceId) {
1318a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                return; // nothing to cancel
1319a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
1320a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1321a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1322a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        cancelVibrateIfNeeded(v);
1323a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
1324a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1325a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    void onVibratorTokenDied(VibratorToken v) {
1326a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        synchronized (mVibratorLock) {
1327a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mVibratorTokens.remove(v.mToken);
1328a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1329a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1330a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        cancelVibrateIfNeeded(v);
1331a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
1332a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1333a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    private void cancelVibrateIfNeeded(VibratorToken v) {
1334a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        synchronized (v) {
1335a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            if (v.mVibrating) {
1336a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                nativeCancelVibrate(mPtr, v.mDeviceId, v.mTokenValue);
1337a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                v.mVibrating = false;
1338a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
1339a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1340a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
1341a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
13424532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    @Override
13434532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1344a3bc565882dd3984e995363642b1295fe3d24d10Jeff Brown        if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
13454532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                != PackageManager.PERMISSION_GRANTED) {
13464532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            pw.println("Permission Denial: can't dump InputManager from from pid="
13474532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                    + Binder.getCallingPid()
13484532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                    + ", uid=" + Binder.getCallingUid());
13494532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            return;
13504532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        }
13514532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
13524532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        pw.println("INPUT MANAGER (dumpsys input)\n");
13534532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        String dumpStr = nativeDump(mPtr);
1354e33348ba54cd68d6936cffd4507037c14d4b10c2Jeff Brown        if (dumpStr != null) {
1355e33348ba54cd68d6936cffd4507037c14d4b10c2Jeff Brown            pw.println(dumpStr);
1356e33348ba54cd68d6936cffd4507037c14d4b10c2Jeff Brown        }
135746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
1358b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown
1359ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    private boolean checkCallingPermission(String permission, String func) {
1360ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        // Quick check: if the calling permission is me, it's all okay.
1361ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (Binder.getCallingPid() == Process.myPid()) {
1362ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            return true;
1363ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
1364ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
1365ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
1366ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            return true;
1367ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
1368ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        String msg = "Permission Denial: " + func + " from pid="
1369ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                + Binder.getCallingPid()
1370ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                + ", uid=" + Binder.getCallingUid()
1371ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                + " requires " + permission;
1372ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        Slog.w(TAG, msg);
1373ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        return false;
1374ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
1375ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
13764532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection).
13772f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    @Override
137889ef0720ee8e0ac6ae1758faa917e4d6c9606fb4Jeff Brown    public void monitor() {
137989ef0720ee8e0ac6ae1758faa917e4d6c9606fb4Jeff Brown        synchronized (mInputFilterLock) { }
13804532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        nativeMonitor(mPtr);
138189ef0720ee8e0ac6ae1758faa917e4d6c9606fb4Jeff Brown    }
138289ef0720ee8e0ac6ae1758faa917e4d6c9606fb4Jeff Brown
13834532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
13844532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private void notifyConfigurationChanged(long whenNanos) {
1385a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown        mWindowManagerCallbacks.notifyConfigurationChanged();
13864532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
13870029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
13884532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
1389af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void notifyInputDevicesChanged(InputDevice[] inputDevices) {
1390af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
1391af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (!mInputDevicesChangedPending) {
1392af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mInputDevicesChangedPending = true;
1393cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                mHandler.obtainMessage(MSG_DELIVER_INPUT_DEVICES_CHANGED,
1394cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        mInputDevices).sendToTarget();
1395af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
1396cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
1397cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            mInputDevices = inputDevices;
1398af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
1399af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
1400af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1401af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    // Native callback.
1402bcc046af4ef171aa3aa3c6b64efb5cafc1e46cd3Jeff Brown    private void notifySwitch(long whenNanos, int switchValues, int switchMask) {
1403bcc046af4ef171aa3aa3c6b64efb5cafc1e46cd3Jeff Brown        if (DEBUG) {
1404bcc046af4ef171aa3aa3c6b64efb5cafc1e46cd3Jeff Brown            Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues)
1405bcc046af4ef171aa3aa3c6b64efb5cafc1e46cd3Jeff Brown                    + ", mask=" + Integer.toHexString(switchMask));
1406bcc046af4ef171aa3aa3c6b64efb5cafc1e46cd3Jeff Brown        }
1407bcc046af4ef171aa3aa3c6b64efb5cafc1e46cd3Jeff Brown
14082f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        if ((switchMask & SW_LID_BIT) != 0) {
14092f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner            final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
1410bcc046af4ef171aa3aa3c6b64efb5cafc1e46cd3Jeff Brown            mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
14115338428ddbe662283bf88171c7ca361d51d78da8Jeff Brown        }
14122f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
14133818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright        if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) {
14149e10d25732518f3d5740b5ede88f43cb28f51a14Michael Wright            final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) != 0);
14153818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright            mWindowManagerCallbacks.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
14163818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright        }
14173818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright
14182f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
14192f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner            mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
14202f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner                    switchMask);
14212f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        }
14224532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
14230029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
14244532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
14254532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
1426a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown        mWindowManagerCallbacks.notifyInputChannelBroken(inputWindowHandle);
14274532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
14280029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
14294532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
14304532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private long notifyANR(InputApplicationHandle inputApplicationHandle,
1431bd181bb83282571eb793d2e4a48b4d19585de7f2Jeff Brown            InputWindowHandle inputWindowHandle, String reason) {
1432bd181bb83282571eb793d2e4a48b4d19585de7f2Jeff Brown        return mWindowManagerCallbacks.notifyANR(
1433bd181bb83282571eb793d2e4a48b4d19585de7f2Jeff Brown                inputApplicationHandle, inputWindowHandle, reason);
14344532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
14354532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
14364532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
14374532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    final boolean filterInputEvent(InputEvent event, int policyFlags) {
14384532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        synchronized (mInputFilterLock) {
14394532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            if (mInputFilter != null) {
1440c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                try {
1441c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                    mInputFilter.filterInputEvent(event, policyFlags);
1442c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                } catch (RemoteException e) {
1443c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                    /* ignore */
1444c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov                }
14454532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                return false;
14460029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown            }
14470029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown        }
14484532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        event.recycle();
14494532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return true;
14500029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown    }
14510029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
14524532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
1453037c33eae74bee2774897d969d48947f9abe254fJeff Brown    private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
1454037c33eae74bee2774897d969d48947f9abe254fJeff Brown        return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
14554532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
14560029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
14574532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
145870af00abf73160235d4efe114fcf4753007a8ff3Michael Wright    private int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
145970af00abf73160235d4efe114fcf4753007a8ff3Michael Wright        return mWindowManagerCallbacks.interceptMotionBeforeQueueingNonInteractive(
14602687550272ba061448f5d5b914700dc335299ee7Jeff Brown                whenNanos, policyFlags);
14614532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
14620029c66203ab9ded4342976bf7a17bb63af8c44aJeff Brown
14634532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
14644532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private long interceptKeyBeforeDispatching(InputWindowHandle focus,
14654532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            KeyEvent event, int policyFlags) {
1466a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown        return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
14674532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
146856194ebec6212e229f4ccdaa4b187166d20013efJeff Brown
14694532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
14704532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
14714532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            KeyEvent event, int policyFlags) {
1472a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown        return mWindowManagerCallbacks.dispatchUnhandledKey(focus, event, policyFlags);
14734532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
147456194ebec6212e229f4ccdaa4b187166d20013efJeff Brown
14754532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
14764532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
14774532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return mContext.checkPermission(android.Manifest.permission.INJECT_EVENTS,
14784532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                injectorPid, injectorUid) == PackageManager.PERMISSION_GRANTED;
14794532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
1480fe50892af3b365806a767298dfd8e86447682581Jeff Brown
14814532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
14824532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getVirtualKeyQuietTimeMillis() {
14834532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return mContext.getResources().getInteger(
14844532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                com.android.internal.R.integer.config_virtualKeyQuietTimeMillis);
14854532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
1486fe50892af3b365806a767298dfd8e86447682581Jeff Brown
14874532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
14884532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private String[] getExcludedDeviceNames() {
14894532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        ArrayList<String> names = new ArrayList<String>();
14904532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
14914532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        // Read partner-provided list of excluded input devices
14924532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        XmlPullParser parser = null;
14934532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
14944532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH);
14954532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        FileReader confreader = null;
14964532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        try {
14974532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            confreader = new FileReader(confFile);
14984532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            parser = Xml.newPullParser();
14994532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            parser.setInput(confreader);
15004532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            XmlUtils.beginDocument(parser, "devices");
15014532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
15024532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            while (true) {
15034532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                XmlUtils.nextElement(parser);
15044532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                if (!"device".equals(parser.getName())) {
15054532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                    break;
15064532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                }
15074532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                String name = parser.getAttributeValue(null, "name");
15084532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                if (name != null) {
15094532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                    names.add(name);
151046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown                }
151146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown            }
15124532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        } catch (FileNotFoundException e) {
15134532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            // It's ok if the file does not exist.
15144532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        } catch (Exception e) {
15154532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
15164532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        } finally {
15174532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            try { if (confreader != null) confreader.close(); } catch (IOException e) { }
151846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        }
1519a454767b09ecb7d25d00beae0e5a1fdd48605c63Jeff Brown
15204532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return names.toArray(new String[names.size()]);
15214532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
1522a454767b09ecb7d25d00beae0e5a1fdd48605c63Jeff Brown
15234532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
15244532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getKeyRepeatTimeout() {
15254532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return ViewConfiguration.getKeyRepeatTimeout();
15264532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
1527a454767b09ecb7d25d00beae0e5a1fdd48605c63Jeff Brown
15284532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
15294532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getKeyRepeatDelay() {
15304532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return ViewConfiguration.getKeyRepeatDelay();
15314532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
1532bb3fcba0caf697f1d238a2cbefdf1efe06eded99Jeff Brown
15334532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
15344532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getHoverTapTimeout() {
15354532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return ViewConfiguration.getHoverTapTimeout();
15364532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
1537214eaf48878bba00cbd5831871bcbd82632b6e34Jeff Brown
15384532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
15394532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getHoverTapSlop() {
15404532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return ViewConfiguration.getHoverTapSlop();
15414532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
1542214eaf48878bba00cbd5831871bcbd82632b6e34Jeff Brown
15434532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
15444532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getDoubleTapTimeout() {
15454532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return ViewConfiguration.getDoubleTapTimeout();
15464532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
1547214eaf48878bba00cbd5831871bcbd82632b6e34Jeff Brown
15484532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
15494532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getLongPressTimeout() {
15504532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return ViewConfiguration.getLongPressTimeout();
15514532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
15524532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
15534532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
15544532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private int getPointerLayer() {
1555a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown        return mWindowManagerCallbacks.getPointerLayer();
15564532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
15574532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
15584532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    // Native callback.
15594532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    private PointerIcon getPointerIcon() {
15604532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        return PointerIcon.getDefaultIcon(mContext);
15614532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
15624532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
15636ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    // Native callback.
1564fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    private String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier) {
15656ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        if (!mSystemReady) {
15666ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            return null;
15676ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        }
15686ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
1569fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        String keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier);
15706ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        if (keyboardLayoutDescriptor == null) {
15716ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            return null;
15726ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        }
15736ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
15746ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        final String[] result = new String[2];
15756ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
15766ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            @Override
15778ebac231966e27364e5d463b63540a0527d40c4bMichael Wright            public void visitKeyboardLayout(Resources resources, String descriptor, String label,
15788ebac231966e27364e5d463b63540a0527d40c4bMichael Wright                    String collection, int keyboardLayoutResId, int priority) {
15796ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                try {
15806ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                    result[0] = descriptor;
15816ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                    result[1] = Streams.readFully(new InputStreamReader(
15822f0957607411b99810226ad38d59cf18718b86d0Jeff Brown                            resources.openRawResource(keyboardLayoutResId)));
15836ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                } catch (IOException ex) {
15846ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                } catch (NotFoundException ex) {
15856ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                }
15866ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            }
15876ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        });
15886ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        if (result[0] == null) {
15896ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            Log.w(TAG, "Could not get keyboard layout with descriptor '"
15906ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown                    + keyboardLayoutDescriptor + "'.");
15916ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown            return null;
15926ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        }
15936ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown        return result;
15946ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    }
15956ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
15965bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown    // Native callback.
15975bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown    private String getDeviceAlias(String uniqueId) {
15989631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie        if (BluetoothAdapter.checkBluetoothAddress(uniqueId)) {
15999631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie            // TODO(BT) mBluetoothService.getRemoteAlias(uniqueId)
16009631314e3d28b6e96ef0b7cc777f1a7747a0ac39Matthew Xie            return null;
16015bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown        }
16025bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown        return null;
16035bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown    }
16045bbd4b4f5fc19302fa017ad6afee6eb2d489d91aJeff Brown
16054532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    /**
16064532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown     * Callback interface implemented by the Window Manager.
16074532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown     */
1608a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown    public interface WindowManagerCallbacks {
16094532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public void notifyConfigurationChanged();
16104532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
16114532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
16124532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
16133818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright        public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered);
16143818c9261ceaa3a700ff984fbcd245faeede38d7Michael Wright
16154532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle);
16164532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
16174532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public long notifyANR(InputApplicationHandle inputApplicationHandle,
1618bd181bb83282571eb793d2e4a48b4d19585de7f2Jeff Brown                InputWindowHandle inputWindowHandle, String reason);
16194532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
1620037c33eae74bee2774897d969d48947f9abe254fJeff Brown        public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
16214532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
162270af00abf73160235d4efe114fcf4753007a8ff3Michael Wright        public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
16234532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
16244532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public long interceptKeyBeforeDispatching(InputWindowHandle focus,
16254532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                KeyEvent event, int policyFlags);
16264532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
16274532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
16284532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                KeyEvent event, int policyFlags);
16294532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
16304532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public int getPointerLayer();
16314532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    }
16324532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
16334532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown    /**
16342f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner     * Callback interface implemented by WiredAccessoryObserver.
16352f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner     */
16362f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    public interface WiredAccessoryCallbacks {
16372f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask);
16384a5eeb9c727d77bb57fef87a70c8c9cc23dbfee3Eric Laurent        public void systemReady();
16392f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    }
16402f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner
16412f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner    /**
1642af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Private handler for the input manager.
1643af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
1644af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final class InputManagerHandler extends Handler {
1645a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown        public InputManagerHandler(Looper looper) {
1646a9d131c30878cacdaeacb4f43a82a7cc5b872453Jeff Brown            super(looper, null, true /*async*/);
1647a2910d0abbbe18ba1710dfd4a31af45769632255Jeff Brown        }
1648a2910d0abbbe18ba1710dfd4a31af45769632255Jeff Brown
1649af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        @Override
1650af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public void handleMessage(Message msg) {
1651af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            switch (msg.what) {
1652af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                case MSG_DELIVER_INPUT_DEVICES_CHANGED:
1653cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    deliverInputDevicesChanged((InputDevice[])msg.obj);
1654cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    break;
1655cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                case MSG_SWITCH_KEYBOARD_LAYOUT:
1656cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
1657cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    break;
1658cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                case MSG_RELOAD_KEYBOARD_LAYOUTS:
1659cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    reloadKeyboardLayouts();
1660cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    break;
1661cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                case MSG_UPDATE_KEYBOARD_LAYOUTS:
1662cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    updateKeyboardLayouts();
1663cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    break;
1664cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                case MSG_RELOAD_DEVICE_ALIASES:
1665cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    reloadDeviceAliases();
1666af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    break;
1667af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
1668af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
1669af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
1670af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1671af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
16724532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown     * Hosting interface for input filters to call back into the input manager.
16734532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown     */
1674c9c9a48e7bafae63cb35a9aa69255e80aba83988Svetoslav Ganov    private final class InputFilterHost extends IInputFilterHost.Stub {
16754532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        private boolean mDisconnected;
16764532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
16774532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public void disconnectLocked() {
16784532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            mDisconnected = true;
167983c09685f2e62bc3cf7e71bc61d903f4b9ccaeb4Jeff Brown        }
1680b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown
16812f39e9f8333183312b7f7d423c2ea60a93a25e32Craig Mautner        @Override
16824532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown        public void sendInputEvent(InputEvent event, int policyFlags) {
16834532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            if (event == null) {
16844532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                throw new IllegalArgumentException("event must not be null");
16854532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            }
16864532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown
16874532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            synchronized (mInputFilterLock) {
16884532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                if (!mDisconnected) {
1689ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown                    nativeInjectInputEvent(mPtr, event, Display.DEFAULT_DISPLAY, 0, 0,
1690ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                            InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0,
16914532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                            policyFlags | WindowManagerPolicy.FLAG_FILTERED);
16924532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown                }
16934532e6158474a263d9d26c2b42240bcf7ce9b172Jeff Brown            }
1694b4ff35df5c04aec71fce7e90a6d6f9ef7180c2adJeff Brown        }
169546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    }
16969f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
16979f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    private static final class KeyboardLayoutDescriptor {
16989f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        public String packageName;
16999f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        public String receiverName;
17009f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        public String keyboardLayoutName;
17019f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
17029f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        public static String format(String packageName,
17039f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                String receiverName, String keyboardName) {
17049f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return packageName + "/" + receiverName + "/" + keyboardName;
17059f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
17069f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
17079f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        public static KeyboardLayoutDescriptor parse(String descriptor) {
17089f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            int pos = descriptor.indexOf('/');
17099f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            if (pos < 0 || pos + 1 == descriptor.length()) {
17109f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                return null;
17119f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            }
17129f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            int pos2 = descriptor.indexOf('/', pos + 1);
17139f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            if (pos2 < pos + 2 || pos2 + 1 == descriptor.length()) {
17149f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                return null;
17159f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            }
17169f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown
17179f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            KeyboardLayoutDescriptor result = new KeyboardLayoutDescriptor();
17189f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            result.packageName = descriptor.substring(0, pos);
17199f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            result.receiverName = descriptor.substring(pos + 1, pos2);
17209f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            result.keyboardLayoutName = descriptor.substring(pos2 + 1);
17219f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return result;
17229f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
17239f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    }
1724af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
17256ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    private interface KeyboardLayoutVisitor {
17268ebac231966e27364e5d463b63540a0527d40c4bMichael Wright        void visitKeyboardLayout(Resources resources, String descriptor, String label,
17278ebac231966e27364e5d463b63540a0527d40c4bMichael Wright                String collection, int keyboardLayoutResId, int priority);
17286ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    }
17296ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown
1730af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final class InputDevicesChangedListenerRecord implements DeathRecipient {
1731af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        private final int mPid;
1732af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        private final IInputDevicesChangedListener mListener;
1733af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1734af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public InputDevicesChangedListenerRecord(int pid, IInputDevicesChangedListener listener) {
1735af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mPid = pid;
1736af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mListener = listener;
1737af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
1738af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1739af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        @Override
1740af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public void binderDied() {
1741af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (DEBUG) {
1742af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                Slog.d(TAG, "Input devices changed listener for pid " + mPid + " died.");
1743af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
1744af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            onInputDevicesChangedListenerDied(mPid);
1745af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
1746af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1747af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public void notifyInputDevicesChanged(int[] info) {
1748af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            try {
1749af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mListener.onInputDevicesChanged(info);
1750af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            } catch (RemoteException ex) {
1751af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                Slog.w(TAG, "Failed to notify process "
1752af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        + mPid + " that input devices changed, assuming it died.", ex);
1753af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                binderDied();
1754af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
1755af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
1756af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
1757a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1758a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    private final class VibratorToken implements DeathRecipient {
1759a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public final int mDeviceId;
1760a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public final IBinder mToken;
1761a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public final int mTokenValue;
1762a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1763a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public boolean mVibrating;
1764a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1765a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public VibratorToken(int deviceId, IBinder token, int tokenValue) {
1766a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mDeviceId = deviceId;
1767a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mToken = token;
1768a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mTokenValue = tokenValue;
1769a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1770a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1771a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
1772a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public void binderDied() {
1773a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            if (DEBUG) {
1774a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                Slog.d(TAG, "Vibrator token died.");
1775a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
1776a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            onVibratorTokenDied(this);
1777a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1778a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
17794ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown
17804ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown    private final class LocalService extends InputManagerInternal {
17814ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown        @Override
17824ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown        public void setDisplayViewports(
17834ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown                DisplayViewport defaultViewport, DisplayViewport externalTouchViewport) {
17844ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown            setDisplayViewportsInternal(defaultViewport, externalTouchViewport);
17854ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown        }
1786ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown
1787ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown        @Override
1788ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown        public boolean injectInputEvent(InputEvent event, int displayId, int mode) {
1789ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown            return injectInputEventInternal(event, displayId, mode);
1790ca9bc702df5c14a89c9b8b0109a05894bf74962eJeff Brown        }
1791037c33eae74bee2774897d969d48947f9abe254fJeff Brown
1792037c33eae74bee2774897d969d48947f9abe254fJeff Brown        @Override
1793037c33eae74bee2774897d969d48947f9abe254fJeff Brown        public void setInteractive(boolean interactive) {
1794037c33eae74bee2774897d969d48947f9abe254fJeff Brown            nativeSetInteractive(mPtr, interactive);
1795037c33eae74bee2774897d969d48947f9abe254fJeff Brown        }
17964ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brown    }
179746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
1798