1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.input;
18 
19 import android.view.Display;
20 import com.android.internal.R;
21 import com.android.internal.util.XmlUtils;
22 import com.android.server.DisplayThread;
23 import com.android.server.LocalServices;
24 import com.android.server.Watchdog;
25 
26 import org.xmlpull.v1.XmlPullParser;
27 
28 import android.Manifest;
29 import android.app.Notification;
30 import android.app.NotificationManager;
31 import android.app.PendingIntent;
32 import android.bluetooth.BluetoothAdapter;
33 import android.bluetooth.BluetoothDevice;
34 import android.content.BroadcastReceiver;
35 import android.content.ComponentName;
36 import android.content.Context;
37 import android.content.Intent;
38 import android.content.IntentFilter;
39 import android.content.pm.ActivityInfo;
40 import android.content.pm.ApplicationInfo;
41 import android.content.pm.PackageManager;
42 import android.content.pm.ResolveInfo;
43 import android.content.pm.PackageManager.NameNotFoundException;
44 import android.content.res.Resources;
45 import android.content.res.Resources.NotFoundException;
46 import android.content.res.TypedArray;
47 import android.content.res.XmlResourceParser;
48 import android.database.ContentObserver;
49 import android.hardware.display.DisplayViewport;
50 import android.hardware.input.IInputDevicesChangedListener;
51 import android.hardware.input.IInputManager;
52 import android.hardware.input.InputDeviceIdentifier;
53 import android.hardware.input.InputManager;
54 import android.hardware.input.InputManagerInternal;
55 import android.hardware.input.KeyboardLayout;
56 import android.hardware.input.TouchCalibration;
57 import android.os.Binder;
58 import android.os.Bundle;
59 import android.os.Environment;
60 import android.os.Handler;
61 import android.os.IBinder;
62 import android.os.Looper;
63 import android.os.Message;
64 import android.os.MessageQueue;
65 import android.os.Process;
66 import android.os.RemoteException;
67 import android.os.UserHandle;
68 import android.provider.Settings;
69 import android.provider.Settings.SettingNotFoundException;
70 import android.util.Log;
71 import android.util.Slog;
72 import android.util.SparseArray;
73 import android.util.Xml;
74 import android.view.IInputFilter;
75 import android.view.IInputFilterHost;
76 import android.view.InputChannel;
77 import android.view.InputDevice;
78 import android.view.InputEvent;
79 import android.view.KeyEvent;
80 import android.view.PointerIcon;
81 import android.view.Surface;
82 import android.view.ViewConfiguration;
83 import android.view.WindowManagerPolicy;
84 import android.widget.Toast;
85 
86 import java.io.File;
87 import java.io.FileDescriptor;
88 import java.io.FileNotFoundException;
89 import java.io.FileReader;
90 import java.io.IOException;
91 import java.io.InputStreamReader;
92 import java.io.PrintWriter;
93 import java.util.ArrayList;
94 import java.util.HashMap;
95 import java.util.HashSet;
96 
97 import libcore.io.Streams;
98 import libcore.util.Objects;
99 
100 /*
101  * Wraps the C++ InputManager and provides its callbacks.
102  */
103 public class InputManagerService extends IInputManager.Stub
104         implements Watchdog.Monitor {
105     static final String TAG = "InputManager";
106     static final boolean DEBUG = false;
107 
108     private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
109 
110     private static final int MSG_DELIVER_INPUT_DEVICES_CHANGED = 1;
111     private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 2;
112     private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 3;
113     private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 4;
114     private static final int MSG_RELOAD_DEVICE_ALIASES = 5;
115 
116     // Pointer to native input manager service object.
117     private final long mPtr;
118 
119     private final Context mContext;
120     private final InputManagerHandler mHandler;
121 
122     private WindowManagerCallbacks mWindowManagerCallbacks;
123     private WiredAccessoryCallbacks mWiredAccessoryCallbacks;
124     private boolean mSystemReady;
125     private NotificationManager mNotificationManager;
126 
127     // Persistent data store.  Must be locked each time during use.
128     private final PersistentDataStore mDataStore = new PersistentDataStore();
129 
130     // List of currently registered input devices changed listeners by process id.
131     private Object mInputDevicesLock = new Object();
132     private boolean mInputDevicesChangedPending; // guarded by mInputDevicesLock
133     private InputDevice[] mInputDevices = new InputDevice[0];
134     private final SparseArray<InputDevicesChangedListenerRecord> mInputDevicesChangedListeners =
135             new SparseArray<InputDevicesChangedListenerRecord>(); // guarded by mInputDevicesLock
136     private final ArrayList<InputDevicesChangedListenerRecord>
137             mTempInputDevicesChangedListenersToNotify =
138                     new ArrayList<InputDevicesChangedListenerRecord>(); // handler thread only
139     private final ArrayList<InputDevice>
140             mTempFullKeyboards = new ArrayList<InputDevice>(); // handler thread only
141     private boolean mKeyboardLayoutNotificationShown;
142     private PendingIntent mKeyboardLayoutIntent;
143     private Toast mSwitchedKeyboardLayoutToast;
144 
145     // State for vibrator tokens.
146     private Object mVibratorLock = new Object();
147     private HashMap<IBinder, VibratorToken> mVibratorTokens =
148             new HashMap<IBinder, VibratorToken>();
149     private int mNextVibratorTokenValue;
150 
151     // State for the currently installed input filter.
152     final Object mInputFilterLock = new Object();
153     IInputFilter mInputFilter; // guarded by mInputFilterLock
154     InputFilterHost mInputFilterHost; // guarded by mInputFilterLock
155 
nativeInit(InputManagerService service, Context context, MessageQueue messageQueue)156     private static native long nativeInit(InputManagerService service,
157             Context context, MessageQueue messageQueue);
nativeStart(long ptr)158     private static native void nativeStart(long ptr);
nativeSetDisplayViewport(long ptr, boolean external, int displayId, int rotation, int logicalLeft, int logicalTop, int logicalRight, int logicalBottom, int physicalLeft, int physicalTop, int physicalRight, int physicalBottom, int deviceWidth, int deviceHeight)159     private static native void nativeSetDisplayViewport(long ptr, boolean external,
160             int displayId, int rotation,
161             int logicalLeft, int logicalTop, int logicalRight, int logicalBottom,
162             int physicalLeft, int physicalTop, int physicalRight, int physicalBottom,
163             int deviceWidth, int deviceHeight);
164 
nativeGetScanCodeState(long ptr, int deviceId, int sourceMask, int scanCode)165     private static native int nativeGetScanCodeState(long ptr,
166             int deviceId, int sourceMask, int scanCode);
nativeGetKeyCodeState(long ptr, int deviceId, int sourceMask, int keyCode)167     private static native int nativeGetKeyCodeState(long ptr,
168             int deviceId, int sourceMask, int keyCode);
nativeGetSwitchState(long ptr, int deviceId, int sourceMask, int sw)169     private static native int nativeGetSwitchState(long ptr,
170             int deviceId, int sourceMask, int sw);
nativeHasKeys(long ptr, int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists)171     private static native boolean nativeHasKeys(long ptr,
172             int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists);
nativeRegisterInputChannel(long ptr, InputChannel inputChannel, InputWindowHandle inputWindowHandle, boolean monitor)173     private static native void nativeRegisterInputChannel(long ptr, InputChannel inputChannel,
174             InputWindowHandle inputWindowHandle, boolean monitor);
nativeUnregisterInputChannel(long ptr, InputChannel inputChannel)175     private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel);
nativeSetInputFilterEnabled(long ptr, boolean enable)176     private static native void nativeSetInputFilterEnabled(long ptr, boolean enable);
nativeInjectInputEvent(long ptr, InputEvent event, int displayId, int injectorPid, int injectorUid, int syncMode, int timeoutMillis, int policyFlags)177     private static native int nativeInjectInputEvent(long ptr, InputEvent event, int displayId,
178             int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
179             int policyFlags);
nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles)180     private static native void nativeSetInputWindows(long ptr, InputWindowHandle[] windowHandles);
nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen)181     private static native void nativeSetInputDispatchMode(long ptr, boolean enabled, boolean frozen);
nativeSetSystemUiVisibility(long ptr, int visibility)182     private static native void nativeSetSystemUiVisibility(long ptr, int visibility);
nativeSetFocusedApplication(long ptr, InputApplicationHandle application)183     private static native void nativeSetFocusedApplication(long ptr,
184             InputApplicationHandle application);
nativeTransferTouchFocus(long ptr, InputChannel fromChannel, InputChannel toChannel)185     private static native boolean nativeTransferTouchFocus(long ptr,
186             InputChannel fromChannel, InputChannel toChannel);
nativeSetPointerSpeed(long ptr, int speed)187     private static native void nativeSetPointerSpeed(long ptr, int speed);
nativeSetShowTouches(long ptr, boolean enabled)188     private static native void nativeSetShowTouches(long ptr, boolean enabled);
nativeSetInteractive(long ptr, boolean interactive)189     private static native void nativeSetInteractive(long ptr, boolean interactive);
nativeReloadCalibration(long ptr)190     private static native void nativeReloadCalibration(long ptr);
nativeVibrate(long ptr, int deviceId, long[] pattern, int repeat, int token)191     private static native void nativeVibrate(long ptr, int deviceId, long[] pattern,
192             int repeat, int token);
nativeCancelVibrate(long ptr, int deviceId, int token)193     private static native void nativeCancelVibrate(long ptr, int deviceId, int token);
nativeReloadKeyboardLayouts(long ptr)194     private static native void nativeReloadKeyboardLayouts(long ptr);
nativeReloadDeviceAliases(long ptr)195     private static native void nativeReloadDeviceAliases(long ptr);
nativeDump(long ptr)196     private static native String nativeDump(long ptr);
nativeMonitor(long ptr)197     private static native void nativeMonitor(long ptr);
198 
199     // Input event injection constants defined in InputDispatcher.h.
200     private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
201     private static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1;
202     private static final int INPUT_EVENT_INJECTION_FAILED = 2;
203     private static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3;
204 
205     // Maximum number of milliseconds to wait for input event injection.
206     private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
207 
208     // Key states (may be returned by queries about the current state of a
209     // particular key code, scan code or switch).
210 
211     /** The key state is unknown or the requested key itself is not supported. */
212     public static final int KEY_STATE_UNKNOWN = -1;
213 
214     /** The key is up. /*/
215     public static final int KEY_STATE_UP = 0;
216 
217     /** The key is down. */
218     public static final int KEY_STATE_DOWN = 1;
219 
220     /** The key is down but is a virtual key press that is being emulated by the system. */
221     public static final int KEY_STATE_VIRTUAL = 2;
222 
223     /** Scan code: Mouse / trackball button. */
224     public static final int BTN_MOUSE = 0x110;
225 
226     // Switch code values must match bionic/libc/kernel/common/linux/input.h
227     /** Switch code: Lid switch.  When set, lid is shut. */
228     public static final int SW_LID = 0x00;
229 
230     /** Switch code: Keypad slide.  When set, keyboard is exposed. */
231     public static final int SW_KEYPAD_SLIDE = 0x0a;
232 
233     /** Switch code: Headphone.  When set, headphone is inserted. */
234     public static final int SW_HEADPHONE_INSERT = 0x02;
235 
236     /** Switch code: Microphone.  When set, microphone is inserted. */
237     public static final int SW_MICROPHONE_INSERT = 0x04;
238 
239     /** Switch code: Line out.  When set, Line out (hi-Z) is inserted. */
240     public static final int SW_LINEOUT_INSERT = 0x06;
241 
242     /** Switch code: Headphone/Microphone Jack.  When set, something is inserted. */
243     public static final int SW_JACK_PHYSICAL_INSERT = 0x07;
244 
245     /** Switch code: Camera lens cover. When set the lens is covered. */
246     public static final int SW_CAMERA_LENS_COVER = 0x09;
247 
248     public static final int SW_LID_BIT = 1 << SW_LID;
249     public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
250     public static final int SW_HEADPHONE_INSERT_BIT = 1 << SW_HEADPHONE_INSERT;
251     public static final int SW_MICROPHONE_INSERT_BIT = 1 << SW_MICROPHONE_INSERT;
252     public static final int SW_LINEOUT_INSERT_BIT = 1 << SW_LINEOUT_INSERT;
253     public static final int SW_JACK_PHYSICAL_INSERT_BIT = 1 << SW_JACK_PHYSICAL_INSERT;
254     public static final int SW_JACK_BITS =
255             SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_JACK_PHYSICAL_INSERT_BIT | SW_LINEOUT_INSERT_BIT;
256     public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER;
257 
258     /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */
259     final boolean mUseDevInputEventForAudioJack;
260 
InputManagerService(Context context)261     public InputManagerService(Context context) {
262         this.mContext = context;
263         this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
264 
265         mUseDevInputEventForAudioJack =
266                 context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
267         Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
268                 + mUseDevInputEventForAudioJack);
269         mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
270 
271         LocalServices.addService(InputManagerInternal.class, new LocalService());
272     }
273 
setWindowManagerCallbacks(WindowManagerCallbacks callbacks)274     public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
275         mWindowManagerCallbacks = callbacks;
276     }
277 
setWiredAccessoryCallbacks(WiredAccessoryCallbacks callbacks)278     public void setWiredAccessoryCallbacks(WiredAccessoryCallbacks callbacks) {
279         mWiredAccessoryCallbacks = callbacks;
280     }
281 
start()282     public void start() {
283         Slog.i(TAG, "Starting input manager");
284         nativeStart(mPtr);
285 
286         // Add ourself to the Watchdog monitors.
287         Watchdog.getInstance().addMonitor(this);
288 
289         registerPointerSpeedSettingObserver();
290         registerShowTouchesSettingObserver();
291 
292         mContext.registerReceiver(new BroadcastReceiver() {
293             @Override
294             public void onReceive(Context context, Intent intent) {
295                 updatePointerSpeedFromSettings();
296                 updateShowTouchesFromSettings();
297             }
298         }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
299 
300         updatePointerSpeedFromSettings();
301         updateShowTouchesFromSettings();
302     }
303 
304     // TODO(BT) Pass in paramter for bluetooth system
systemRunning()305     public void systemRunning() {
306         if (DEBUG) {
307             Slog.d(TAG, "System ready.");
308         }
309         mNotificationManager = (NotificationManager)mContext.getSystemService(
310                 Context.NOTIFICATION_SERVICE);
311         mSystemReady = true;
312 
313         IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
314         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
315         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
316         filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
317         filter.addDataScheme("package");
318         mContext.registerReceiver(new BroadcastReceiver() {
319             @Override
320             public void onReceive(Context context, Intent intent) {
321                 updateKeyboardLayouts();
322             }
323         }, filter, null, mHandler);
324 
325         filter = new IntentFilter(BluetoothDevice.ACTION_ALIAS_CHANGED);
326         mContext.registerReceiver(new BroadcastReceiver() {
327             @Override
328             public void onReceive(Context context, Intent intent) {
329                 reloadDeviceAliases();
330             }
331         }, filter, null, mHandler);
332 
333         mHandler.sendEmptyMessage(MSG_RELOAD_DEVICE_ALIASES);
334         mHandler.sendEmptyMessage(MSG_UPDATE_KEYBOARD_LAYOUTS);
335 
336         if (mWiredAccessoryCallbacks != null) {
337             mWiredAccessoryCallbacks.systemReady();
338         }
339     }
340 
reloadKeyboardLayouts()341     private void reloadKeyboardLayouts() {
342         if (DEBUG) {
343             Slog.d(TAG, "Reloading keyboard layouts.");
344         }
345         nativeReloadKeyboardLayouts(mPtr);
346     }
347 
reloadDeviceAliases()348     private void reloadDeviceAliases() {
349         if (DEBUG) {
350             Slog.d(TAG, "Reloading device names.");
351         }
352         nativeReloadDeviceAliases(mPtr);
353     }
354 
setDisplayViewportsInternal(DisplayViewport defaultViewport, DisplayViewport externalTouchViewport)355     private void setDisplayViewportsInternal(DisplayViewport defaultViewport,
356             DisplayViewport externalTouchViewport) {
357         if (defaultViewport.valid) {
358             setDisplayViewport(false, defaultViewport);
359         }
360 
361         if (externalTouchViewport.valid) {
362             setDisplayViewport(true, externalTouchViewport);
363         } else if (defaultViewport.valid) {
364             setDisplayViewport(true, defaultViewport);
365         }
366     }
367 
setDisplayViewport(boolean external, DisplayViewport viewport)368     private void setDisplayViewport(boolean external, DisplayViewport viewport) {
369         nativeSetDisplayViewport(mPtr, external,
370                 viewport.displayId, viewport.orientation,
371                 viewport.logicalFrame.left, viewport.logicalFrame.top,
372                 viewport.logicalFrame.right, viewport.logicalFrame.bottom,
373                 viewport.physicalFrame.left, viewport.physicalFrame.top,
374                 viewport.physicalFrame.right, viewport.physicalFrame.bottom,
375                 viewport.deviceWidth, viewport.deviceHeight);
376     }
377 
378     /**
379      * Gets the current state of a key or button by key code.
380      * @param deviceId The input device id, or -1 to consult all devices.
381      * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
382      * consider all input sources.  An input device is consulted if at least one of its
383      * non-class input source bits matches the specified source mask.
384      * @param keyCode The key code to check.
385      * @return The key state.
386      */
getKeyCodeState(int deviceId, int sourceMask, int keyCode)387     public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) {
388         return nativeGetKeyCodeState(mPtr, deviceId, sourceMask, keyCode);
389     }
390 
391     /**
392      * Gets the current state of a key or button by scan code.
393      * @param deviceId The input device id, or -1 to consult all devices.
394      * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
395      * consider all input sources.  An input device is consulted if at least one of its
396      * non-class input source bits matches the specified source mask.
397      * @param scanCode The scan code to check.
398      * @return The key state.
399      */
getScanCodeState(int deviceId, int sourceMask, int scanCode)400     public int getScanCodeState(int deviceId, int sourceMask, int scanCode) {
401         return nativeGetScanCodeState(mPtr, deviceId, sourceMask, scanCode);
402     }
403 
404     /**
405      * Gets the current state of a switch by switch code.
406      * @param deviceId The input device id, or -1 to consult all devices.
407      * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
408      * consider all input sources.  An input device is consulted if at least one of its
409      * non-class input source bits matches the specified source mask.
410      * @param switchCode The switch code to check.
411      * @return The switch state.
412      */
getSwitchState(int deviceId, int sourceMask, int switchCode)413     public int getSwitchState(int deviceId, int sourceMask, int switchCode) {
414         return nativeGetSwitchState(mPtr, deviceId, sourceMask, switchCode);
415     }
416 
417     /**
418      * Determines whether the specified key codes are supported by a particular device.
419      * @param deviceId The input device id, or -1 to consult all devices.
420      * @param sourceMask The input sources to consult, or {@link InputDevice#SOURCE_ANY} to
421      * consider all input sources.  An input device is consulted if at least one of its
422      * non-class input source bits matches the specified source mask.
423      * @param keyCodes The array of key codes to check.
424      * @param keyExists An array at least as large as keyCodes whose entries will be set
425      * to true or false based on the presence or absence of support for the corresponding
426      * key codes.
427      * @return True if the lookup was successful, false otherwise.
428      */
429     @Override // Binder call
hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists)430     public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) {
431         if (keyCodes == null) {
432             throw new IllegalArgumentException("keyCodes must not be null.");
433         }
434         if (keyExists == null || keyExists.length < keyCodes.length) {
435             throw new IllegalArgumentException("keyExists must not be null and must be at "
436                     + "least as large as keyCodes.");
437         }
438 
439         return nativeHasKeys(mPtr, deviceId, sourceMask, keyCodes, keyExists);
440     }
441 
442     /**
443      * Creates an input channel that will receive all input from the input dispatcher.
444      * @param inputChannelName The input channel name.
445      * @return The input channel.
446      */
monitorInput(String inputChannelName)447     public InputChannel monitorInput(String inputChannelName) {
448         if (inputChannelName == null) {
449             throw new IllegalArgumentException("inputChannelName must not be null.");
450         }
451 
452         InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
453         nativeRegisterInputChannel(mPtr, inputChannels[0], null, true);
454         inputChannels[0].dispose(); // don't need to retain the Java object reference
455         return inputChannels[1];
456     }
457 
458     /**
459      * Registers an input channel so that it can be used as an input event target.
460      * @param inputChannel The input channel to register.
461      * @param inputWindowHandle The handle of the input window associated with the
462      * input channel, or null if none.
463      */
registerInputChannel(InputChannel inputChannel, InputWindowHandle inputWindowHandle)464     public void registerInputChannel(InputChannel inputChannel,
465             InputWindowHandle inputWindowHandle) {
466         if (inputChannel == null) {
467             throw new IllegalArgumentException("inputChannel must not be null.");
468         }
469 
470         nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
471     }
472 
473     /**
474      * Unregisters an input channel.
475      * @param inputChannel The input channel to unregister.
476      */
unregisterInputChannel(InputChannel inputChannel)477     public void unregisterInputChannel(InputChannel inputChannel) {
478         if (inputChannel == null) {
479             throw new IllegalArgumentException("inputChannel must not be null.");
480         }
481 
482         nativeUnregisterInputChannel(mPtr, inputChannel);
483     }
484 
485     /**
486      * Sets an input filter that will receive all input events before they are dispatched.
487      * The input filter may then reinterpret input events or inject new ones.
488      *
489      * To ensure consistency, the input dispatcher automatically drops all events
490      * in progress whenever an input filter is installed or uninstalled.  After an input
491      * filter is uninstalled, it can no longer send input events unless it is reinstalled.
492      * Any events it attempts to send after it has been uninstalled will be dropped.
493      *
494      * @param filter The input filter, or null to remove the current filter.
495      */
setInputFilter(IInputFilter filter)496     public void setInputFilter(IInputFilter filter) {
497         synchronized (mInputFilterLock) {
498             final IInputFilter oldFilter = mInputFilter;
499             if (oldFilter == filter) {
500                 return; // nothing to do
501             }
502 
503             if (oldFilter != null) {
504                 mInputFilter = null;
505                 mInputFilterHost.disconnectLocked();
506                 mInputFilterHost = null;
507                 try {
508                     oldFilter.uninstall();
509                 } catch (RemoteException re) {
510                     /* ignore */
511                 }
512             }
513 
514             if (filter != null) {
515                 mInputFilter = filter;
516                 mInputFilterHost = new InputFilterHost();
517                 try {
518                     filter.install(mInputFilterHost);
519                 } catch (RemoteException re) {
520                     /* ignore */
521                 }
522             }
523 
524             nativeSetInputFilterEnabled(mPtr, filter != null);
525         }
526     }
527 
528     @Override // Binder call
injectInputEvent(InputEvent event, int mode)529     public boolean injectInputEvent(InputEvent event, int mode) {
530         return injectInputEventInternal(event, Display.DEFAULT_DISPLAY, mode);
531     }
532 
injectInputEventInternal(InputEvent event, int displayId, int mode)533     private boolean injectInputEventInternal(InputEvent event, int displayId, int mode) {
534         if (event == null) {
535             throw new IllegalArgumentException("event must not be null");
536         }
537         if (mode != InputManager.INJECT_INPUT_EVENT_MODE_ASYNC
538                 && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
539                 && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
540             throw new IllegalArgumentException("mode is invalid");
541         }
542 
543         final int pid = Binder.getCallingPid();
544         final int uid = Binder.getCallingUid();
545         final long ident = Binder.clearCallingIdentity();
546         final int result;
547         try {
548             result = nativeInjectInputEvent(mPtr, event, displayId, pid, uid, mode,
549                     INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
550         } finally {
551             Binder.restoreCallingIdentity(ident);
552         }
553         switch (result) {
554             case INPUT_EVENT_INJECTION_PERMISSION_DENIED:
555                 Slog.w(TAG, "Input event injection from pid " + pid + " permission denied.");
556                 throw new SecurityException(
557                         "Injecting to another application requires INJECT_EVENTS permission");
558             case INPUT_EVENT_INJECTION_SUCCEEDED:
559                 return true;
560             case INPUT_EVENT_INJECTION_TIMED_OUT:
561                 Slog.w(TAG, "Input event injection from pid " + pid + " timed out.");
562                 return false;
563             case INPUT_EVENT_INJECTION_FAILED:
564             default:
565                 Slog.w(TAG, "Input event injection from pid " + pid + " failed.");
566                 return false;
567         }
568     }
569 
570     /**
571      * Gets information about the input device with the specified id.
572      * @param deviceId The device id.
573      * @return The input device or null if not found.
574      */
575     @Override // Binder call
getInputDevice(int deviceId)576     public InputDevice getInputDevice(int deviceId) {
577         synchronized (mInputDevicesLock) {
578             final int count = mInputDevices.length;
579             for (int i = 0; i < count; i++) {
580                 final InputDevice inputDevice = mInputDevices[i];
581                 if (inputDevice.getId() == deviceId) {
582                     return inputDevice;
583                 }
584             }
585         }
586         return null;
587     }
588 
589     /**
590      * Gets the ids of all input devices in the system.
591      * @return The input device ids.
592      */
593     @Override // Binder call
getInputDeviceIds()594     public int[] getInputDeviceIds() {
595         synchronized (mInputDevicesLock) {
596             final int count = mInputDevices.length;
597             int[] ids = new int[count];
598             for (int i = 0; i < count; i++) {
599                 ids[i] = mInputDevices[i].getId();
600             }
601             return ids;
602         }
603     }
604 
605     /**
606      * Gets all input devices in the system.
607      * @return The array of input devices.
608      */
getInputDevices()609     public InputDevice[] getInputDevices() {
610         synchronized (mInputDevicesLock) {
611             return mInputDevices;
612         }
613     }
614 
615     @Override // Binder call
registerInputDevicesChangedListener(IInputDevicesChangedListener listener)616     public void registerInputDevicesChangedListener(IInputDevicesChangedListener listener) {
617         if (listener == null) {
618             throw new IllegalArgumentException("listener must not be null");
619         }
620 
621         synchronized (mInputDevicesLock) {
622             int callingPid = Binder.getCallingPid();
623             if (mInputDevicesChangedListeners.get(callingPid) != null) {
624                 throw new SecurityException("The calling process has already "
625                         + "registered an InputDevicesChangedListener.");
626             }
627 
628             InputDevicesChangedListenerRecord record =
629                     new InputDevicesChangedListenerRecord(callingPid, listener);
630             try {
631                 IBinder binder = listener.asBinder();
632                 binder.linkToDeath(record, 0);
633             } catch (RemoteException ex) {
634                 // give up
635                 throw new RuntimeException(ex);
636             }
637 
638             mInputDevicesChangedListeners.put(callingPid, record);
639         }
640     }
641 
onInputDevicesChangedListenerDied(int pid)642     private void onInputDevicesChangedListenerDied(int pid) {
643         synchronized (mInputDevicesLock) {
644             mInputDevicesChangedListeners.remove(pid);
645         }
646     }
647 
648     // Must be called on handler.
deliverInputDevicesChanged(InputDevice[] oldInputDevices)649     private void deliverInputDevicesChanged(InputDevice[] oldInputDevices) {
650         // Scan for changes.
651         int numFullKeyboardsAdded = 0;
652         mTempInputDevicesChangedListenersToNotify.clear();
653         mTempFullKeyboards.clear();
654         final int numListeners;
655         final int[] deviceIdAndGeneration;
656         synchronized (mInputDevicesLock) {
657             if (!mInputDevicesChangedPending) {
658                 return;
659             }
660             mInputDevicesChangedPending = false;
661 
662             numListeners = mInputDevicesChangedListeners.size();
663             for (int i = 0; i < numListeners; i++) {
664                 mTempInputDevicesChangedListenersToNotify.add(
665                         mInputDevicesChangedListeners.valueAt(i));
666             }
667 
668             final int numDevices = mInputDevices.length;
669             deviceIdAndGeneration = new int[numDevices * 2];
670             for (int i = 0; i < numDevices; i++) {
671                 final InputDevice inputDevice = mInputDevices[i];
672                 deviceIdAndGeneration[i * 2] = inputDevice.getId();
673                 deviceIdAndGeneration[i * 2 + 1] = inputDevice.getGeneration();
674 
675                 if (!inputDevice.isVirtual() && inputDevice.isFullKeyboard()) {
676                     if (!containsInputDeviceWithDescriptor(oldInputDevices,
677                             inputDevice.getDescriptor())) {
678                         mTempFullKeyboards.add(numFullKeyboardsAdded++, inputDevice);
679                     } else {
680                         mTempFullKeyboards.add(inputDevice);
681                     }
682                 }
683             }
684         }
685 
686         // Notify listeners.
687         for (int i = 0; i < numListeners; i++) {
688             mTempInputDevicesChangedListenersToNotify.get(i).notifyInputDevicesChanged(
689                     deviceIdAndGeneration);
690         }
691         mTempInputDevicesChangedListenersToNotify.clear();
692 
693         // Check for missing keyboard layouts.
694         if (mNotificationManager != null) {
695             final int numFullKeyboards = mTempFullKeyboards.size();
696             boolean missingLayoutForExternalKeyboard = false;
697             boolean missingLayoutForExternalKeyboardAdded = false;
698             boolean multipleMissingLayoutsForExternalKeyboardsAdded = false;
699             InputDevice keyboardMissingLayout = null;
700             synchronized (mDataStore) {
701                 for (int i = 0; i < numFullKeyboards; i++) {
702                     final InputDevice inputDevice = mTempFullKeyboards.get(i);
703                     final String layout =
704                             getCurrentKeyboardLayoutForInputDevice(inputDevice.getIdentifier());
705                     if (layout == null) {
706                         missingLayoutForExternalKeyboard = true;
707                         if (i < numFullKeyboardsAdded) {
708                             missingLayoutForExternalKeyboardAdded = true;
709                             if (keyboardMissingLayout == null) {
710                                 keyboardMissingLayout = inputDevice;
711                             } else {
712                                 multipleMissingLayoutsForExternalKeyboardsAdded = true;
713                             }
714                         }
715                     }
716                 }
717             }
718             if (missingLayoutForExternalKeyboard) {
719                 if (missingLayoutForExternalKeyboardAdded) {
720                     if (multipleMissingLayoutsForExternalKeyboardsAdded) {
721                         // We have more than one keyboard missing a layout, so drop the
722                         // user at the generic input methods page so they can pick which
723                         // one to set.
724                         showMissingKeyboardLayoutNotification(null);
725                     } else {
726                         showMissingKeyboardLayoutNotification(keyboardMissingLayout);
727                     }
728                 }
729             } else if (mKeyboardLayoutNotificationShown) {
730                 hideMissingKeyboardLayoutNotification();
731             }
732         }
733         mTempFullKeyboards.clear();
734     }
735 
736     @Override // Binder call & native callback
getTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation)737     public TouchCalibration getTouchCalibrationForInputDevice(String inputDeviceDescriptor,
738             int surfaceRotation) {
739         if (inputDeviceDescriptor == null) {
740             throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
741         }
742 
743         synchronized (mDataStore) {
744             return mDataStore.getTouchCalibration(inputDeviceDescriptor, surfaceRotation);
745         }
746     }
747 
748     @Override // Binder call
setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation, TouchCalibration calibration)749     public void setTouchCalibrationForInputDevice(String inputDeviceDescriptor, int surfaceRotation,
750             TouchCalibration calibration) {
751         if (!checkCallingPermission(android.Manifest.permission.SET_INPUT_CALIBRATION,
752                 "setTouchCalibrationForInputDevice()")) {
753             throw new SecurityException("Requires SET_INPUT_CALIBRATION permission");
754         }
755         if (inputDeviceDescriptor == null) {
756             throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
757         }
758         if (calibration == null) {
759             throw new IllegalArgumentException("calibration must not be null");
760         }
761         if (surfaceRotation < Surface.ROTATION_0 || surfaceRotation > Surface.ROTATION_270) {
762             throw new IllegalArgumentException("surfaceRotation value out of bounds");
763         }
764 
765         synchronized (mDataStore) {
766             try {
767                 if (mDataStore.setTouchCalibration(inputDeviceDescriptor, surfaceRotation,
768                         calibration)) {
769                     nativeReloadCalibration(mPtr);
770                 }
771             } finally {
772                 mDataStore.saveIfNeeded();
773             }
774         }
775     }
776 
777     // Must be called on handler.
showMissingKeyboardLayoutNotification(InputDevice device)778     private void showMissingKeyboardLayoutNotification(InputDevice device) {
779         if (!mKeyboardLayoutNotificationShown) {
780             final Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
781             if (device != null) {
782                 intent.putExtra(Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, device.getIdentifier());
783             }
784             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
785                     | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
786                     | Intent.FLAG_ACTIVITY_CLEAR_TOP);
787             final PendingIntent keyboardLayoutIntent = PendingIntent.getActivityAsUser(mContext, 0,
788                     intent, 0, null, UserHandle.CURRENT);
789 
790             Resources r = mContext.getResources();
791             Notification notification = new Notification.Builder(mContext)
792                     .setContentTitle(r.getString(
793                             R.string.select_keyboard_layout_notification_title))
794                     .setContentText(r.getString(
795                             R.string.select_keyboard_layout_notification_message))
796                     .setContentIntent(keyboardLayoutIntent)
797                     .setSmallIcon(R.drawable.ic_settings_language)
798                     .setPriority(Notification.PRIORITY_LOW)
799                     .setColor(mContext.getColor(
800                             com.android.internal.R.color.system_notification_accent_color))
801                     .build();
802             mNotificationManager.notifyAsUser(null,
803                     R.string.select_keyboard_layout_notification_title,
804                     notification, UserHandle.ALL);
805             mKeyboardLayoutNotificationShown = true;
806         }
807     }
808 
809     // Must be called on handler.
hideMissingKeyboardLayoutNotification()810     private void hideMissingKeyboardLayoutNotification() {
811         if (mKeyboardLayoutNotificationShown) {
812             mKeyboardLayoutNotificationShown = false;
813             mNotificationManager.cancelAsUser(null,
814                     R.string.select_keyboard_layout_notification_title,
815                     UserHandle.ALL);
816         }
817     }
818 
819     // Must be called on handler.
updateKeyboardLayouts()820     private void updateKeyboardLayouts() {
821         // Scan all input devices state for keyboard layouts that have been uninstalled.
822         final HashSet<String> availableKeyboardLayouts = new HashSet<String>();
823         visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
824             @Override
825             public void visitKeyboardLayout(Resources resources, String descriptor, String label,
826                     String collection, int keyboardLayoutResId, int priority) {
827                 availableKeyboardLayouts.add(descriptor);
828             }
829         });
830         synchronized (mDataStore) {
831             try {
832                 mDataStore.removeUninstalledKeyboardLayouts(availableKeyboardLayouts);
833             } finally {
834                 mDataStore.saveIfNeeded();
835             }
836         }
837 
838         // Reload keyboard layouts.
839         reloadKeyboardLayouts();
840     }
841 
containsInputDeviceWithDescriptor(InputDevice[] inputDevices, String descriptor)842     private static boolean containsInputDeviceWithDescriptor(InputDevice[] inputDevices,
843             String descriptor) {
844         final int numDevices = inputDevices.length;
845         for (int i = 0; i < numDevices; i++) {
846             final InputDevice inputDevice = inputDevices[i];
847             if (inputDevice.getDescriptor().equals(descriptor)) {
848                 return true;
849             }
850         }
851         return false;
852     }
853 
854     @Override // Binder call
getKeyboardLayouts()855     public KeyboardLayout[] getKeyboardLayouts() {
856         final ArrayList<KeyboardLayout> list = new ArrayList<KeyboardLayout>();
857         visitAllKeyboardLayouts(new KeyboardLayoutVisitor() {
858             @Override
859             public void visitKeyboardLayout(Resources resources, String descriptor, String label,
860                     String collection, int keyboardLayoutResId, int priority) {
861                 list.add(new KeyboardLayout(descriptor, label, collection, priority));
862             }
863         });
864         return list.toArray(new KeyboardLayout[list.size()]);
865     }
866 
867     @Override // Binder call
getKeyboardLayout(String keyboardLayoutDescriptor)868     public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
869         if (keyboardLayoutDescriptor == null) {
870             throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
871         }
872 
873         final KeyboardLayout[] result = new KeyboardLayout[1];
874         visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
875             @Override
876             public void visitKeyboardLayout(Resources resources, String descriptor,
877                     String label, String collection, int keyboardLayoutResId, int priority) {
878                 result[0] = new KeyboardLayout(descriptor, label, collection, priority);
879             }
880         });
881         if (result[0] == null) {
882             Log.w(TAG, "Could not get keyboard layout with descriptor '"
883                     + keyboardLayoutDescriptor + "'.");
884         }
885         return result[0];
886     }
887 
visitAllKeyboardLayouts(KeyboardLayoutVisitor visitor)888     private void visitAllKeyboardLayouts(KeyboardLayoutVisitor visitor) {
889         final PackageManager pm = mContext.getPackageManager();
890         Intent intent = new Intent(InputManager.ACTION_QUERY_KEYBOARD_LAYOUTS);
891         for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent,
892                 PackageManager.GET_META_DATA)) {
893             final ActivityInfo activityInfo = resolveInfo.activityInfo;
894             final int priority = resolveInfo.priority;
895             visitKeyboardLayoutsInPackage(pm, activityInfo, null, priority, visitor);
896         }
897     }
898 
visitKeyboardLayout(String keyboardLayoutDescriptor, KeyboardLayoutVisitor visitor)899     private void visitKeyboardLayout(String keyboardLayoutDescriptor,
900             KeyboardLayoutVisitor visitor) {
901         KeyboardLayoutDescriptor d = KeyboardLayoutDescriptor.parse(keyboardLayoutDescriptor);
902         if (d != null) {
903             final PackageManager pm = mContext.getPackageManager();
904             try {
905                 ActivityInfo receiver = pm.getReceiverInfo(
906                         new ComponentName(d.packageName, d.receiverName),
907                         PackageManager.GET_META_DATA);
908                 visitKeyboardLayoutsInPackage(pm, receiver, d.keyboardLayoutName, 0, visitor);
909             } catch (NameNotFoundException ex) {
910             }
911         }
912     }
913 
visitKeyboardLayoutsInPackage(PackageManager pm, ActivityInfo receiver, String keyboardName, int requestedPriority, KeyboardLayoutVisitor visitor)914     private void visitKeyboardLayoutsInPackage(PackageManager pm, ActivityInfo receiver,
915             String keyboardName, int requestedPriority, KeyboardLayoutVisitor visitor) {
916         Bundle metaData = receiver.metaData;
917         if (metaData == null) {
918             return;
919         }
920 
921         int configResId = metaData.getInt(InputManager.META_DATA_KEYBOARD_LAYOUTS);
922         if (configResId == 0) {
923             Log.w(TAG, "Missing meta-data '" + InputManager.META_DATA_KEYBOARD_LAYOUTS
924                     + "' on receiver " + receiver.packageName + "/" + receiver.name);
925             return;
926         }
927 
928         CharSequence receiverLabel = receiver.loadLabel(pm);
929         String collection = receiverLabel != null ? receiverLabel.toString() : "";
930         int priority;
931         if ((receiver.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
932             priority = requestedPriority;
933         } else {
934             priority = 0;
935         }
936 
937         try {
938             Resources resources = pm.getResourcesForApplication(receiver.applicationInfo);
939             XmlResourceParser parser = resources.getXml(configResId);
940             try {
941                 XmlUtils.beginDocument(parser, "keyboard-layouts");
942 
943                 for (;;) {
944                     XmlUtils.nextElement(parser);
945                     String element = parser.getName();
946                     if (element == null) {
947                         break;
948                     }
949                     if (element.equals("keyboard-layout")) {
950                         TypedArray a = resources.obtainAttributes(
951                                 parser, com.android.internal.R.styleable.KeyboardLayout);
952                         try {
953                             String name = a.getString(
954                                     com.android.internal.R.styleable.KeyboardLayout_name);
955                             String label = a.getString(
956                                     com.android.internal.R.styleable.KeyboardLayout_label);
957                             int keyboardLayoutResId = a.getResourceId(
958                                     com.android.internal.R.styleable.KeyboardLayout_keyboardLayout,
959                                     0);
960                             if (name == null || label == null || keyboardLayoutResId == 0) {
961                                 Log.w(TAG, "Missing required 'name', 'label' or 'keyboardLayout' "
962                                         + "attributes in keyboard layout "
963                                         + "resource from receiver "
964                                         + receiver.packageName + "/" + receiver.name);
965                             } else {
966                                 String descriptor = KeyboardLayoutDescriptor.format(
967                                         receiver.packageName, receiver.name, name);
968                                 if (keyboardName == null || name.equals(keyboardName)) {
969                                     visitor.visitKeyboardLayout(resources, descriptor,
970                                             label, collection, keyboardLayoutResId, priority);
971                                 }
972                             }
973                         } finally {
974                             a.recycle();
975                         }
976                     } else {
977                         Log.w(TAG, "Skipping unrecognized element '" + element
978                                 + "' in keyboard layout resource from receiver "
979                                 + receiver.packageName + "/" + receiver.name);
980                     }
981                 }
982             } finally {
983                 parser.close();
984             }
985         } catch (Exception ex) {
986             Log.w(TAG, "Could not parse keyboard layout resource from receiver "
987                     + receiver.packageName + "/" + receiver.name, ex);
988         }
989     }
990 
991     /**
992      * Builds a layout descriptor for the vendor/product. This returns the
993      * descriptor for ids that aren't useful (such as the default 0, 0).
994      */
getLayoutDescriptor(InputDeviceIdentifier identifier)995     private String getLayoutDescriptor(InputDeviceIdentifier identifier) {
996         if (identifier == null || identifier.getDescriptor() == null) {
997             throw new IllegalArgumentException("identifier and descriptor must not be null");
998         }
999 
1000         if (identifier.getVendorId() == 0 && identifier.getProductId() == 0) {
1001             return identifier.getDescriptor();
1002         }
1003         StringBuilder bob = new StringBuilder();
1004         bob.append("vendor:").append(identifier.getVendorId());
1005         bob.append(",product:").append(identifier.getProductId());
1006         return bob.toString();
1007     }
1008 
1009     @Override // Binder call
getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier)1010     public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
1011 
1012         String key = getLayoutDescriptor(identifier);
1013         synchronized (mDataStore) {
1014             String layout = null;
1015             // try loading it using the layout descriptor if we have it
1016             layout = mDataStore.getCurrentKeyboardLayout(key);
1017             if (layout == null && !key.equals(identifier.getDescriptor())) {
1018                 // if it doesn't exist fall back to the device descriptor
1019                 layout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1020             }
1021             if (DEBUG) {
1022                 Slog.d(TAG, "Loaded keyboard layout id for " + key + " and got "
1023                         + layout);
1024             }
1025             return layout;
1026         }
1027     }
1028 
1029     @Override // Binder call
setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier, String keyboardLayoutDescriptor)1030     public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
1031             String keyboardLayoutDescriptor) {
1032         if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1033                 "setCurrentKeyboardLayoutForInputDevice()")) {
1034             throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1035         }
1036         if (keyboardLayoutDescriptor == null) {
1037             throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1038         }
1039 
1040         String key = getLayoutDescriptor(identifier);
1041         synchronized (mDataStore) {
1042             try {
1043                 if (mDataStore.setCurrentKeyboardLayout(key, keyboardLayoutDescriptor)) {
1044                     if (DEBUG) {
1045                         Slog.d(TAG, "Saved keyboard layout using " + key);
1046                     }
1047                     mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1048                 }
1049             } finally {
1050                 mDataStore.saveIfNeeded();
1051             }
1052         }
1053     }
1054 
1055     @Override // Binder call
getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier)1056     public String[] getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
1057         String key = getLayoutDescriptor(identifier);
1058         synchronized (mDataStore) {
1059             String[] layouts = mDataStore.getKeyboardLayouts(key);
1060             if ((layouts == null || layouts.length == 0)
1061                     && !key.equals(identifier.getDescriptor())) {
1062                 layouts = mDataStore.getKeyboardLayouts(identifier.getDescriptor());
1063             }
1064             return layouts;
1065         }
1066     }
1067 
1068     @Override // Binder call
addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier, String keyboardLayoutDescriptor)1069     public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
1070             String keyboardLayoutDescriptor) {
1071         if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1072                 "addKeyboardLayoutForInputDevice()")) {
1073             throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1074         }
1075         if (keyboardLayoutDescriptor == null) {
1076             throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1077         }
1078 
1079         String key = getLayoutDescriptor(identifier);
1080         synchronized (mDataStore) {
1081             try {
1082                 String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
1083                 if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
1084                     oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1085                 }
1086                 if (mDataStore.addKeyboardLayout(key, keyboardLayoutDescriptor)
1087                         && !Objects.equal(oldLayout,
1088                                 mDataStore.getCurrentKeyboardLayout(key))) {
1089                     mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1090                 }
1091             } finally {
1092                 mDataStore.saveIfNeeded();
1093             }
1094         }
1095     }
1096 
1097     @Override // Binder call
removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier, String keyboardLayoutDescriptor)1098     public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
1099             String keyboardLayoutDescriptor) {
1100         if (!checkCallingPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT,
1101                 "removeKeyboardLayoutForInputDevice()")) {
1102             throw new SecurityException("Requires SET_KEYBOARD_LAYOUT permission");
1103         }
1104         if (keyboardLayoutDescriptor == null) {
1105             throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
1106         }
1107 
1108         String key = getLayoutDescriptor(identifier);
1109         synchronized (mDataStore) {
1110             try {
1111                 String oldLayout = mDataStore.getCurrentKeyboardLayout(key);
1112                 if (oldLayout == null && !key.equals(identifier.getDescriptor())) {
1113                     oldLayout = mDataStore.getCurrentKeyboardLayout(identifier.getDescriptor());
1114                 }
1115                 boolean removed = mDataStore.removeKeyboardLayout(key, keyboardLayoutDescriptor);
1116                 if (!key.equals(identifier.getDescriptor())) {
1117                     // We need to remove from both places to ensure it is gone
1118                     removed |= mDataStore.removeKeyboardLayout(identifier.getDescriptor(),
1119                             keyboardLayoutDescriptor);
1120                 }
1121                 if (removed && !Objects.equal(oldLayout,
1122                                 mDataStore.getCurrentKeyboardLayout(key))) {
1123                     mHandler.sendEmptyMessage(MSG_RELOAD_KEYBOARD_LAYOUTS);
1124                 }
1125             } finally {
1126                 mDataStore.saveIfNeeded();
1127             }
1128         }
1129     }
1130 
switchKeyboardLayout(int deviceId, int direction)1131     public void switchKeyboardLayout(int deviceId, int direction) {
1132         mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, deviceId, direction).sendToTarget();
1133     }
1134 
1135     // Must be called on handler.
handleSwitchKeyboardLayout(int deviceId, int direction)1136     private void handleSwitchKeyboardLayout(int deviceId, int direction) {
1137         final InputDevice device = getInputDevice(deviceId);
1138         if (device != null) {
1139             final boolean changed;
1140             final String keyboardLayoutDescriptor;
1141 
1142             String key = getLayoutDescriptor(device.getIdentifier());
1143             synchronized (mDataStore) {
1144                 try {
1145                     changed = mDataStore.switchKeyboardLayout(key, direction);
1146                     keyboardLayoutDescriptor = mDataStore.getCurrentKeyboardLayout(
1147                             key);
1148                 } finally {
1149                     mDataStore.saveIfNeeded();
1150                 }
1151             }
1152 
1153             if (changed) {
1154                 if (mSwitchedKeyboardLayoutToast != null) {
1155                     mSwitchedKeyboardLayoutToast.cancel();
1156                     mSwitchedKeyboardLayoutToast = null;
1157                 }
1158                 if (keyboardLayoutDescriptor != null) {
1159                     KeyboardLayout keyboardLayout = getKeyboardLayout(keyboardLayoutDescriptor);
1160                     if (keyboardLayout != null) {
1161                         mSwitchedKeyboardLayoutToast = Toast.makeText(
1162                                 mContext, keyboardLayout.getLabel(), Toast.LENGTH_SHORT);
1163                         mSwitchedKeyboardLayoutToast.show();
1164                     }
1165                 }
1166 
1167                 reloadKeyboardLayouts();
1168             }
1169         }
1170     }
1171 
setInputWindows(InputWindowHandle[] windowHandles)1172     public void setInputWindows(InputWindowHandle[] windowHandles) {
1173         nativeSetInputWindows(mPtr, windowHandles);
1174     }
1175 
setFocusedApplication(InputApplicationHandle application)1176     public void setFocusedApplication(InputApplicationHandle application) {
1177         nativeSetFocusedApplication(mPtr, application);
1178     }
1179 
setInputDispatchMode(boolean enabled, boolean frozen)1180     public void setInputDispatchMode(boolean enabled, boolean frozen) {
1181         nativeSetInputDispatchMode(mPtr, enabled, frozen);
1182     }
1183 
setSystemUiVisibility(int visibility)1184     public void setSystemUiVisibility(int visibility) {
1185         nativeSetSystemUiVisibility(mPtr, visibility);
1186     }
1187 
1188     /**
1189      * Atomically transfers touch focus from one window to another as identified by
1190      * their input channels.  It is possible for multiple windows to have
1191      * touch focus if they support split touch dispatch
1192      * {@link android.view.WindowManager.LayoutParams#FLAG_SPLIT_TOUCH} but this
1193      * method only transfers touch focus of the specified window without affecting
1194      * other windows that may also have touch focus at the same time.
1195      * @param fromChannel The channel of a window that currently has touch focus.
1196      * @param toChannel The channel of the window that should receive touch focus in
1197      * place of the first.
1198      * @return True if the transfer was successful.  False if the window with the
1199      * specified channel did not actually have touch focus at the time of the request.
1200      */
transferTouchFocus(InputChannel fromChannel, InputChannel toChannel)1201     public boolean transferTouchFocus(InputChannel fromChannel, InputChannel toChannel) {
1202         if (fromChannel == null) {
1203             throw new IllegalArgumentException("fromChannel must not be null.");
1204         }
1205         if (toChannel == null) {
1206             throw new IllegalArgumentException("toChannel must not be null.");
1207         }
1208         return nativeTransferTouchFocus(mPtr, fromChannel, toChannel);
1209     }
1210 
1211     @Override // Binder call
tryPointerSpeed(int speed)1212     public void tryPointerSpeed(int speed) {
1213         if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED,
1214                 "tryPointerSpeed()")) {
1215             throw new SecurityException("Requires SET_POINTER_SPEED permission");
1216         }
1217 
1218         if (speed < InputManager.MIN_POINTER_SPEED || speed > InputManager.MAX_POINTER_SPEED) {
1219             throw new IllegalArgumentException("speed out of range");
1220         }
1221 
1222         setPointerSpeedUnchecked(speed);
1223     }
1224 
updatePointerSpeedFromSettings()1225     public void updatePointerSpeedFromSettings() {
1226         int speed = getPointerSpeedSetting();
1227         setPointerSpeedUnchecked(speed);
1228     }
1229 
setPointerSpeedUnchecked(int speed)1230     private void setPointerSpeedUnchecked(int speed) {
1231         speed = Math.min(Math.max(speed, InputManager.MIN_POINTER_SPEED),
1232                 InputManager.MAX_POINTER_SPEED);
1233         nativeSetPointerSpeed(mPtr, speed);
1234     }
1235 
registerPointerSpeedSettingObserver()1236     private void registerPointerSpeedSettingObserver() {
1237         mContext.getContentResolver().registerContentObserver(
1238                 Settings.System.getUriFor(Settings.System.POINTER_SPEED), true,
1239                 new ContentObserver(mHandler) {
1240                     @Override
1241                     public void onChange(boolean selfChange) {
1242                         updatePointerSpeedFromSettings();
1243                     }
1244                 }, UserHandle.USER_ALL);
1245     }
1246 
getPointerSpeedSetting()1247     private int getPointerSpeedSetting() {
1248         int speed = InputManager.DEFAULT_POINTER_SPEED;
1249         try {
1250             speed = Settings.System.getIntForUser(mContext.getContentResolver(),
1251                     Settings.System.POINTER_SPEED, UserHandle.USER_CURRENT);
1252         } catch (SettingNotFoundException snfe) {
1253         }
1254         return speed;
1255     }
1256 
updateShowTouchesFromSettings()1257     public void updateShowTouchesFromSettings() {
1258         int setting = getShowTouchesSetting(0);
1259         nativeSetShowTouches(mPtr, setting != 0);
1260     }
1261 
registerShowTouchesSettingObserver()1262     private void registerShowTouchesSettingObserver() {
1263         mContext.getContentResolver().registerContentObserver(
1264                 Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), true,
1265                 new ContentObserver(mHandler) {
1266                     @Override
1267                     public void onChange(boolean selfChange) {
1268                         updateShowTouchesFromSettings();
1269                     }
1270                 }, UserHandle.USER_ALL);
1271     }
1272 
getShowTouchesSetting(int defaultValue)1273     private int getShowTouchesSetting(int defaultValue) {
1274         int result = defaultValue;
1275         try {
1276             result = Settings.System.getIntForUser(mContext.getContentResolver(),
1277                     Settings.System.SHOW_TOUCHES, UserHandle.USER_CURRENT);
1278         } catch (SettingNotFoundException snfe) {
1279         }
1280         return result;
1281     }
1282 
1283     // Binder call
1284     @Override
vibrate(int deviceId, long[] pattern, int repeat, IBinder token)1285     public void vibrate(int deviceId, long[] pattern, int repeat, IBinder token) {
1286         if (repeat >= pattern.length) {
1287             throw new ArrayIndexOutOfBoundsException();
1288         }
1289 
1290         VibratorToken v;
1291         synchronized (mVibratorLock) {
1292             v = mVibratorTokens.get(token);
1293             if (v == null) {
1294                 v = new VibratorToken(deviceId, token, mNextVibratorTokenValue++);
1295                 try {
1296                     token.linkToDeath(v, 0);
1297                 } catch (RemoteException ex) {
1298                     // give up
1299                     throw new RuntimeException(ex);
1300                 }
1301                 mVibratorTokens.put(token, v);
1302             }
1303         }
1304 
1305         synchronized (v) {
1306             v.mVibrating = true;
1307             nativeVibrate(mPtr, deviceId, pattern, repeat, v.mTokenValue);
1308         }
1309     }
1310 
1311     // Binder call
1312     @Override
cancelVibrate(int deviceId, IBinder token)1313     public void cancelVibrate(int deviceId, IBinder token) {
1314         VibratorToken v;
1315         synchronized (mVibratorLock) {
1316             v = mVibratorTokens.get(token);
1317             if (v == null || v.mDeviceId != deviceId) {
1318                 return; // nothing to cancel
1319             }
1320         }
1321 
1322         cancelVibrateIfNeeded(v);
1323     }
1324 
onVibratorTokenDied(VibratorToken v)1325     void onVibratorTokenDied(VibratorToken v) {
1326         synchronized (mVibratorLock) {
1327             mVibratorTokens.remove(v.mToken);
1328         }
1329 
1330         cancelVibrateIfNeeded(v);
1331     }
1332 
cancelVibrateIfNeeded(VibratorToken v)1333     private void cancelVibrateIfNeeded(VibratorToken v) {
1334         synchronized (v) {
1335             if (v.mVibrating) {
1336                 nativeCancelVibrate(mPtr, v.mDeviceId, v.mTokenValue);
1337                 v.mVibrating = false;
1338             }
1339         }
1340     }
1341 
1342     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)1343     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1344         if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
1345                 != PackageManager.PERMISSION_GRANTED) {
1346             pw.println("Permission Denial: can't dump InputManager from from pid="
1347                     + Binder.getCallingPid()
1348                     + ", uid=" + Binder.getCallingUid());
1349             return;
1350         }
1351 
1352         pw.println("INPUT MANAGER (dumpsys input)\n");
1353         String dumpStr = nativeDump(mPtr);
1354         if (dumpStr != null) {
1355             pw.println(dumpStr);
1356         }
1357     }
1358 
checkCallingPermission(String permission, String func)1359     private boolean checkCallingPermission(String permission, String func) {
1360         // Quick check: if the calling permission is me, it's all okay.
1361         if (Binder.getCallingPid() == Process.myPid()) {
1362             return true;
1363         }
1364 
1365         if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
1366             return true;
1367         }
1368         String msg = "Permission Denial: " + func + " from pid="
1369                 + Binder.getCallingPid()
1370                 + ", uid=" + Binder.getCallingUid()
1371                 + " requires " + permission;
1372         Slog.w(TAG, msg);
1373         return false;
1374     }
1375 
1376     // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection).
1377     @Override
monitor()1378     public void monitor() {
1379         synchronized (mInputFilterLock) { }
1380         nativeMonitor(mPtr);
1381     }
1382 
1383     // Native callback.
notifyConfigurationChanged(long whenNanos)1384     private void notifyConfigurationChanged(long whenNanos) {
1385         mWindowManagerCallbacks.notifyConfigurationChanged();
1386     }
1387 
1388     // Native callback.
notifyInputDevicesChanged(InputDevice[] inputDevices)1389     private void notifyInputDevicesChanged(InputDevice[] inputDevices) {
1390         synchronized (mInputDevicesLock) {
1391             if (!mInputDevicesChangedPending) {
1392                 mInputDevicesChangedPending = true;
1393                 mHandler.obtainMessage(MSG_DELIVER_INPUT_DEVICES_CHANGED,
1394                         mInputDevices).sendToTarget();
1395             }
1396 
1397             mInputDevices = inputDevices;
1398         }
1399     }
1400 
1401     // Native callback.
notifySwitch(long whenNanos, int switchValues, int switchMask)1402     private void notifySwitch(long whenNanos, int switchValues, int switchMask) {
1403         if (DEBUG) {
1404             Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues)
1405                     + ", mask=" + Integer.toHexString(switchMask));
1406         }
1407 
1408         if ((switchMask & SW_LID_BIT) != 0) {
1409             final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
1410             mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
1411         }
1412 
1413         if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) {
1414             final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) != 0);
1415             mWindowManagerCallbacks.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
1416         }
1417 
1418         if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
1419             mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
1420                     switchMask);
1421         }
1422     }
1423 
1424     // Native callback.
notifyInputChannelBroken(InputWindowHandle inputWindowHandle)1425     private void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
1426         mWindowManagerCallbacks.notifyInputChannelBroken(inputWindowHandle);
1427     }
1428 
1429     // Native callback.
notifyANR(InputApplicationHandle inputApplicationHandle, InputWindowHandle inputWindowHandle, String reason)1430     private long notifyANR(InputApplicationHandle inputApplicationHandle,
1431             InputWindowHandle inputWindowHandle, String reason) {
1432         return mWindowManagerCallbacks.notifyANR(
1433                 inputApplicationHandle, inputWindowHandle, reason);
1434     }
1435 
1436     // Native callback.
filterInputEvent(InputEvent event, int policyFlags)1437     final boolean filterInputEvent(InputEvent event, int policyFlags) {
1438         synchronized (mInputFilterLock) {
1439             if (mInputFilter != null) {
1440                 try {
1441                     mInputFilter.filterInputEvent(event, policyFlags);
1442                 } catch (RemoteException e) {
1443                     /* ignore */
1444                 }
1445                 return false;
1446             }
1447         }
1448         event.recycle();
1449         return true;
1450     }
1451 
1452     // Native callback.
interceptKeyBeforeQueueing(KeyEvent event, int policyFlags)1453     private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
1454         return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
1455     }
1456 
1457     // Native callback.
interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags)1458     private int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
1459         return mWindowManagerCallbacks.interceptMotionBeforeQueueingNonInteractive(
1460                 whenNanos, policyFlags);
1461     }
1462 
1463     // Native callback.
interceptKeyBeforeDispatching(InputWindowHandle focus, KeyEvent event, int policyFlags)1464     private long interceptKeyBeforeDispatching(InputWindowHandle focus,
1465             KeyEvent event, int policyFlags) {
1466         return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
1467     }
1468 
1469     // Native callback.
dispatchUnhandledKey(InputWindowHandle focus, KeyEvent event, int policyFlags)1470     private KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
1471             KeyEvent event, int policyFlags) {
1472         return mWindowManagerCallbacks.dispatchUnhandledKey(focus, event, policyFlags);
1473     }
1474 
1475     // Native callback.
checkInjectEventsPermission(int injectorPid, int injectorUid)1476     private boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
1477         return mContext.checkPermission(android.Manifest.permission.INJECT_EVENTS,
1478                 injectorPid, injectorUid) == PackageManager.PERMISSION_GRANTED;
1479     }
1480 
1481     // Native callback.
getVirtualKeyQuietTimeMillis()1482     private int getVirtualKeyQuietTimeMillis() {
1483         return mContext.getResources().getInteger(
1484                 com.android.internal.R.integer.config_virtualKeyQuietTimeMillis);
1485     }
1486 
1487     // Native callback.
getExcludedDeviceNames()1488     private String[] getExcludedDeviceNames() {
1489         ArrayList<String> names = new ArrayList<String>();
1490 
1491         // Read partner-provided list of excluded input devices
1492         XmlPullParser parser = null;
1493         // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
1494         File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH);
1495         FileReader confreader = null;
1496         try {
1497             confreader = new FileReader(confFile);
1498             parser = Xml.newPullParser();
1499             parser.setInput(confreader);
1500             XmlUtils.beginDocument(parser, "devices");
1501 
1502             while (true) {
1503                 XmlUtils.nextElement(parser);
1504                 if (!"device".equals(parser.getName())) {
1505                     break;
1506                 }
1507                 String name = parser.getAttributeValue(null, "name");
1508                 if (name != null) {
1509                     names.add(name);
1510                 }
1511             }
1512         } catch (FileNotFoundException e) {
1513             // It's ok if the file does not exist.
1514         } catch (Exception e) {
1515             Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
1516         } finally {
1517             try { if (confreader != null) confreader.close(); } catch (IOException e) { }
1518         }
1519 
1520         return names.toArray(new String[names.size()]);
1521     }
1522 
1523     // Native callback.
getKeyRepeatTimeout()1524     private int getKeyRepeatTimeout() {
1525         return ViewConfiguration.getKeyRepeatTimeout();
1526     }
1527 
1528     // Native callback.
getKeyRepeatDelay()1529     private int getKeyRepeatDelay() {
1530         return ViewConfiguration.getKeyRepeatDelay();
1531     }
1532 
1533     // Native callback.
getHoverTapTimeout()1534     private int getHoverTapTimeout() {
1535         return ViewConfiguration.getHoverTapTimeout();
1536     }
1537 
1538     // Native callback.
getHoverTapSlop()1539     private int getHoverTapSlop() {
1540         return ViewConfiguration.getHoverTapSlop();
1541     }
1542 
1543     // Native callback.
getDoubleTapTimeout()1544     private int getDoubleTapTimeout() {
1545         return ViewConfiguration.getDoubleTapTimeout();
1546     }
1547 
1548     // Native callback.
getLongPressTimeout()1549     private int getLongPressTimeout() {
1550         return ViewConfiguration.getLongPressTimeout();
1551     }
1552 
1553     // Native callback.
getPointerLayer()1554     private int getPointerLayer() {
1555         return mWindowManagerCallbacks.getPointerLayer();
1556     }
1557 
1558     // Native callback.
getPointerIcon()1559     private PointerIcon getPointerIcon() {
1560         return PointerIcon.getDefaultIcon(mContext);
1561     }
1562 
1563     // Native callback.
getKeyboardLayoutOverlay(InputDeviceIdentifier identifier)1564     private String[] getKeyboardLayoutOverlay(InputDeviceIdentifier identifier) {
1565         if (!mSystemReady) {
1566             return null;
1567         }
1568 
1569         String keyboardLayoutDescriptor = getCurrentKeyboardLayoutForInputDevice(identifier);
1570         if (keyboardLayoutDescriptor == null) {
1571             return null;
1572         }
1573 
1574         final String[] result = new String[2];
1575         visitKeyboardLayout(keyboardLayoutDescriptor, new KeyboardLayoutVisitor() {
1576             @Override
1577             public void visitKeyboardLayout(Resources resources, String descriptor, String label,
1578                     String collection, int keyboardLayoutResId, int priority) {
1579                 try {
1580                     result[0] = descriptor;
1581                     result[1] = Streams.readFully(new InputStreamReader(
1582                             resources.openRawResource(keyboardLayoutResId)));
1583                 } catch (IOException ex) {
1584                 } catch (NotFoundException ex) {
1585                 }
1586             }
1587         });
1588         if (result[0] == null) {
1589             Log.w(TAG, "Could not get keyboard layout with descriptor '"
1590                     + keyboardLayoutDescriptor + "'.");
1591             return null;
1592         }
1593         return result;
1594     }
1595 
1596     // Native callback.
getDeviceAlias(String uniqueId)1597     private String getDeviceAlias(String uniqueId) {
1598         if (BluetoothAdapter.checkBluetoothAddress(uniqueId)) {
1599             // TODO(BT) mBluetoothService.getRemoteAlias(uniqueId)
1600             return null;
1601         }
1602         return null;
1603     }
1604 
1605     /**
1606      * Callback interface implemented by the Window Manager.
1607      */
1608     public interface WindowManagerCallbacks {
notifyConfigurationChanged()1609         public void notifyConfigurationChanged();
1610 
notifyLidSwitchChanged(long whenNanos, boolean lidOpen)1611         public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
1612 
notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered)1613         public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered);
1614 
notifyInputChannelBroken(InputWindowHandle inputWindowHandle)1615         public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle);
1616 
notifyANR(InputApplicationHandle inputApplicationHandle, InputWindowHandle inputWindowHandle, String reason)1617         public long notifyANR(InputApplicationHandle inputApplicationHandle,
1618                 InputWindowHandle inputWindowHandle, String reason);
1619 
interceptKeyBeforeQueueing(KeyEvent event, int policyFlags)1620         public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
1621 
interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags)1622         public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
1623 
interceptKeyBeforeDispatching(InputWindowHandle focus, KeyEvent event, int policyFlags)1624         public long interceptKeyBeforeDispatching(InputWindowHandle focus,
1625                 KeyEvent event, int policyFlags);
1626 
dispatchUnhandledKey(InputWindowHandle focus, KeyEvent event, int policyFlags)1627         public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
1628                 KeyEvent event, int policyFlags);
1629 
getPointerLayer()1630         public int getPointerLayer();
1631     }
1632 
1633     /**
1634      * Callback interface implemented by WiredAccessoryObserver.
1635      */
1636     public interface WiredAccessoryCallbacks {
notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask)1637         public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask);
systemReady()1638         public void systemReady();
1639     }
1640 
1641     /**
1642      * Private handler for the input manager.
1643      */
1644     private final class InputManagerHandler extends Handler {
InputManagerHandler(Looper looper)1645         public InputManagerHandler(Looper looper) {
1646             super(looper, null, true /*async*/);
1647         }
1648 
1649         @Override
handleMessage(Message msg)1650         public void handleMessage(Message msg) {
1651             switch (msg.what) {
1652                 case MSG_DELIVER_INPUT_DEVICES_CHANGED:
1653                     deliverInputDevicesChanged((InputDevice[])msg.obj);
1654                     break;
1655                 case MSG_SWITCH_KEYBOARD_LAYOUT:
1656                     handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
1657                     break;
1658                 case MSG_RELOAD_KEYBOARD_LAYOUTS:
1659                     reloadKeyboardLayouts();
1660                     break;
1661                 case MSG_UPDATE_KEYBOARD_LAYOUTS:
1662                     updateKeyboardLayouts();
1663                     break;
1664                 case MSG_RELOAD_DEVICE_ALIASES:
1665                     reloadDeviceAliases();
1666                     break;
1667             }
1668         }
1669     }
1670 
1671     /**
1672      * Hosting interface for input filters to call back into the input manager.
1673      */
1674     private final class InputFilterHost extends IInputFilterHost.Stub {
1675         private boolean mDisconnected;
1676 
disconnectLocked()1677         public void disconnectLocked() {
1678             mDisconnected = true;
1679         }
1680 
1681         @Override
sendInputEvent(InputEvent event, int policyFlags)1682         public void sendInputEvent(InputEvent event, int policyFlags) {
1683             if (event == null) {
1684                 throw new IllegalArgumentException("event must not be null");
1685             }
1686 
1687             synchronized (mInputFilterLock) {
1688                 if (!mDisconnected) {
1689                     nativeInjectInputEvent(mPtr, event, Display.DEFAULT_DISPLAY, 0, 0,
1690                             InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0,
1691                             policyFlags | WindowManagerPolicy.FLAG_FILTERED);
1692                 }
1693             }
1694         }
1695     }
1696 
1697     private static final class KeyboardLayoutDescriptor {
1698         public String packageName;
1699         public String receiverName;
1700         public String keyboardLayoutName;
1701 
format(String packageName, String receiverName, String keyboardName)1702         public static String format(String packageName,
1703                 String receiverName, String keyboardName) {
1704             return packageName + "/" + receiverName + "/" + keyboardName;
1705         }
1706 
parse(String descriptor)1707         public static KeyboardLayoutDescriptor parse(String descriptor) {
1708             int pos = descriptor.indexOf('/');
1709             if (pos < 0 || pos + 1 == descriptor.length()) {
1710                 return null;
1711             }
1712             int pos2 = descriptor.indexOf('/', pos + 1);
1713             if (pos2 < pos + 2 || pos2 + 1 == descriptor.length()) {
1714                 return null;
1715             }
1716 
1717             KeyboardLayoutDescriptor result = new KeyboardLayoutDescriptor();
1718             result.packageName = descriptor.substring(0, pos);
1719             result.receiverName = descriptor.substring(pos + 1, pos2);
1720             result.keyboardLayoutName = descriptor.substring(pos2 + 1);
1721             return result;
1722         }
1723     }
1724 
1725     private interface KeyboardLayoutVisitor {
visitKeyboardLayout(Resources resources, String descriptor, String label, String collection, int keyboardLayoutResId, int priority)1726         void visitKeyboardLayout(Resources resources, String descriptor, String label,
1727                 String collection, int keyboardLayoutResId, int priority);
1728     }
1729 
1730     private final class InputDevicesChangedListenerRecord implements DeathRecipient {
1731         private final int mPid;
1732         private final IInputDevicesChangedListener mListener;
1733 
InputDevicesChangedListenerRecord(int pid, IInputDevicesChangedListener listener)1734         public InputDevicesChangedListenerRecord(int pid, IInputDevicesChangedListener listener) {
1735             mPid = pid;
1736             mListener = listener;
1737         }
1738 
1739         @Override
binderDied()1740         public void binderDied() {
1741             if (DEBUG) {
1742                 Slog.d(TAG, "Input devices changed listener for pid " + mPid + " died.");
1743             }
1744             onInputDevicesChangedListenerDied(mPid);
1745         }
1746 
notifyInputDevicesChanged(int[] info)1747         public void notifyInputDevicesChanged(int[] info) {
1748             try {
1749                 mListener.onInputDevicesChanged(info);
1750             } catch (RemoteException ex) {
1751                 Slog.w(TAG, "Failed to notify process "
1752                         + mPid + " that input devices changed, assuming it died.", ex);
1753                 binderDied();
1754             }
1755         }
1756     }
1757 
1758     private final class VibratorToken implements DeathRecipient {
1759         public final int mDeviceId;
1760         public final IBinder mToken;
1761         public final int mTokenValue;
1762 
1763         public boolean mVibrating;
1764 
VibratorToken(int deviceId, IBinder token, int tokenValue)1765         public VibratorToken(int deviceId, IBinder token, int tokenValue) {
1766             mDeviceId = deviceId;
1767             mToken = token;
1768             mTokenValue = tokenValue;
1769         }
1770 
1771         @Override
binderDied()1772         public void binderDied() {
1773             if (DEBUG) {
1774                 Slog.d(TAG, "Vibrator token died.");
1775             }
1776             onVibratorTokenDied(this);
1777         }
1778     }
1779 
1780     private final class LocalService extends InputManagerInternal {
1781         @Override
setDisplayViewports( DisplayViewport defaultViewport, DisplayViewport externalTouchViewport)1782         public void setDisplayViewports(
1783                 DisplayViewport defaultViewport, DisplayViewport externalTouchViewport) {
1784             setDisplayViewportsInternal(defaultViewport, externalTouchViewport);
1785         }
1786 
1787         @Override
injectInputEvent(InputEvent event, int displayId, int mode)1788         public boolean injectInputEvent(InputEvent event, int displayId, int mode) {
1789             return injectInputEventInternal(event, displayId, mode);
1790         }
1791 
1792         @Override
setInteractive(boolean interactive)1793         public void setInteractive(boolean interactive) {
1794             nativeSetInteractive(mPtr, interactive);
1795         }
1796     }
1797 }
1798