InputManager.java revision a47425a13c19f95057df78b8bb65bb25657e8753
19df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown/*
29df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Copyright (C) 2012 The Android Open Source Project
39df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown *
49df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
59df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * you may not use this file except in compliance with the License.
69df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * You may obtain a copy of the License at
79df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown *
89df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
99df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown *
109df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Unless required by applicable law or agreed to in writing, software
119df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
129df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * See the License for the specific language governing permissions and
149df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * limitations under the License.
159df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown */
169df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
179df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownpackage android.hardware.input;
189df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
199df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.annotation.SdkConstant;
209df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.annotation.SdkConstant.SdkConstantType;
219df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.content.Context;
22a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brownimport android.os.Binder;
23af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.Handler;
24ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.IBinder;
25af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.Looper;
26af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.Message;
27ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.RemoteException;
28ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.ServiceManager;
29a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brownimport android.os.Vibrator;
30ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.provider.Settings;
31ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.provider.Settings.SettingNotFoundException;
329df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.util.Log;
339f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.util.SparseArray;
34ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.view.InputDevice;
35ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.view.InputEvent;
369df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
37af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport java.util.ArrayList;
38af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
399df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown/**
409df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Provides information about input devices and available key layouts.
419df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * <p>
429df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Get an instance of this class by calling
439df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * {@link android.content.Context#getSystemService(java.lang.String)
449df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Context.getSystemService()} with the argument
459df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * {@link android.content.Context#INPUT_SERVICE}.
469df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * </p>
479df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown */
489df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownpublic final class InputManager {
499df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    private static final String TAG = "InputManager";
50af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final boolean DEBUG = false;
51af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
52af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final int MSG_DEVICE_ADDED = 1;
53af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final int MSG_DEVICE_REMOVED = 2;
54af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final int MSG_DEVICE_CHANGED = 3;
559df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
569f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    private static InputManager sInstance;
579df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
589f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    private final IInputManager mIm;
59af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
60af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    // Guarded by mInputDevicesLock
61af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final Object mInputDevicesLock = new Object();
62af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private SparseArray<InputDevice> mInputDevices;
63af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private InputDevicesChangedListener mInputDevicesChangedListener;
64af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners =
65af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            new ArrayList<InputDeviceListenerDelegate>();
669df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
679df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
689df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Broadcast Action: Query available keyboard layouts.
699df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
709df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The input manager service locates available keyboard layouts
719df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * by querying broadcast receivers that are registered for this action.
729df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * An application can offer additional keyboard layouts to the user
739df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * by declaring a suitable broadcast receiver in its manifest.
749df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p><p>
759df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Here is an example broadcast receiver declaration that an application
769df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * might include in its AndroidManifest.xml to advertise keyboard layouts.
779df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The meta-data specifies a resource that contains a description of each keyboard
789df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * layout that is provided by the application.
799df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <pre><code>
809df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;receiver android:name=".InputDeviceReceiver">
819df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;intent-filter>
829df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *         &lt;action android:name="android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS" />
839df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;/intent-filter>
849df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;meta-data android:name="android.hardware.input.metadata.KEYBOARD_LAYOUTS"
859df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *             android:resource="@xml/keyboard_layouts" />
869df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;/receiver>
879df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </code></pre>
889df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p><p>
899df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * In the above example, the <code>@xml/keyboard_layouts</code> resource refers to
909df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * an XML resource whose root element is <code>&lt;keyboard-layouts></code> that
919df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * contains zero or more <code>&lt;keyboard-layout></code> elements.
929df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Each <code>&lt;keyboard-layout></code> element specifies the name, label, and location
939df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * of a key character map for a particular keyboard layout.
949df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <pre></code>
959df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;?xml version="1.0" encoding="utf-8"?>
969df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;keyboard-layouts xmlns:android="http://schemas.android.com/apk/res/android">
979df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;keyboard-layout android:name="keyboard_layout_english_us"
989df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *             android:label="@string/keyboard_layout_english_us_label"
999df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *             android:kcm="@raw/keyboard_layout_english_us" />
1009df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;/keyboard-layouts>
1019df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p><p>
1029df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The <code>android:name</code> attribute specifies an identifier by which
1039df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * the keyboard layout will be known in the package.
1049df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The <code>android:label</code> attributes specifies a human-readable descriptive
1059df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * label to describe the keyboard layout in the user interface, such as "English (US)".
1069df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The <code>android:kcm</code> attribute refers to a
1079df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <a href="http://source.android.com/tech/input/key-character-map-files.html">
1089df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * key character map</a> resource that defines the keyboard layout.
1099df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
1109df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
1119df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
1129df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    public static final String ACTION_QUERY_KEYBOARD_LAYOUTS =
1139df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            "android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS";
1149df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
1159df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
1169df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Metadata Key: Keyboard layout metadata associated with
1179df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS}.
1189df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
1199df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Specifies the resource id of a XML resource that describes the keyboard
1209df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * layouts that are provided by the application.
1219df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
1229df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
1239df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    public static final String META_DATA_KEYBOARD_LAYOUTS =
1249df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            "android.hardware.input.metadata.KEYBOARD_LAYOUTS";
1259df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
126ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
127ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Pointer Speed: The minimum (slowest) pointer speed (-7).
128ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
129ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
130ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int MIN_POINTER_SPEED = -7;
131ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
132ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
133ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Pointer Speed: The maximum (fastest) pointer speed (7).
134ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
135ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
136ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int MAX_POINTER_SPEED = 7;
137ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
138ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
139ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Pointer Speed: The default pointer speed (0).
140ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
141ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
142ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int DEFAULT_POINTER_SPEED = 0;
143ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
144ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
145ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Input Event Injection Synchronization Mode: None.
146ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Never blocks.  Injection is asynchronous and is assumed always to be successful.
147ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
148ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
149ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int INJECT_INPUT_EVENT_MODE_ASYNC = 0; // see InputDispatcher.h
150ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
151ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
152ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Input Event Injection Synchronization Mode: Wait for result.
153ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Waits for previous events to be dispatched so that the input dispatcher can
154ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * determine whether input event injection will be permitted based on the current
155ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * input focus.  Does not wait for the input event to finish being handled
156ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * by the application.
157ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
158ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
159ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1;  // see InputDispatcher.h
160ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
161ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
162ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Input Event Injection Synchronization Mode: Wait for finish.
163ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Waits for the event to be delivered to the application and handled.
164ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
165ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
166ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2;  // see InputDispatcher.h
167ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
1689f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    private InputManager(IInputManager im) {
1699f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        mIm = im;
170ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
171ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
1729f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    /**
1739f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * Gets an instance of the input manager.
1749f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     *
1759f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @return The input manager instance.
1769f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     *
1779f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @hide
1789f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     */
1799f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public static InputManager getInstance() {
1809f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        synchronized (InputManager.class) {
1819f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            if (sInstance == null) {
1829f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                IBinder b = ServiceManager.getService(Context.INPUT_SERVICE);
1839f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                sInstance = new InputManager(IInputManager.Stub.asInterface(b));
1849f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            }
1859f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return sInstance;
1869f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
1879df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
1889df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
1899df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
190af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Gets information about the input device with the specified id.
191af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param id The device id.
192af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @return The input device or null if not found.
193af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
194af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public InputDevice getInputDevice(int id) {
195af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
196af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            populateInputDevicesLocked();
197af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
198af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int index = mInputDevices.indexOfKey(id);
199af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (index < 0) {
200af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                return null;
201af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
202af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
203af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            InputDevice inputDevice = mInputDevices.valueAt(index);
204af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (inputDevice == null) {
205af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                try {
206af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    inputDevice = mIm.getInputDevice(id);
207af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                } catch (RemoteException ex) {
208af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    throw new RuntimeException("Could not get input device information.", ex);
209af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                }
210af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
211af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mInputDevices.setValueAt(index, inputDevice);
212af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            return inputDevice;
213af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
214af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
215af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
216af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
217af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Gets the ids of all input devices in the system.
218af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @return The input device ids.
219af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
220af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public int[] getInputDeviceIds() {
221af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
222af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            populateInputDevicesLocked();
223af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
224af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int count = mInputDevices.size();
225af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int[] ids = new int[count];
226af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < count; i++) {
227af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                ids[i] = mInputDevices.keyAt(i);
228af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
229af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            return ids;
230af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
231af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
232af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
233af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
234af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Registers an input device listener to receive notifications about when
235af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * input devices are added, removed or changed.
236af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
237af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param listener The listener to register.
238af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param handler The handler on which the listener should be invoked, or null
239af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * if the listener should be invoked on the calling thread's looper.
240af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
241af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @see #unregisterInputDeviceListener
242af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
243af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
244af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (listener == null) {
245af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            throw new IllegalArgumentException("listener must not be null");
246af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
247af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
248af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
249af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int index = findInputDeviceListenerLocked(listener);
250af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (index < 0) {
251af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mInputDeviceListeners.add(new InputDeviceListenerDelegate(listener, handler));
252af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
253af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
254af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
255af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
256af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
257af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Unregisters an input device listener.
258af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
259af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param listener The listener to unregister.
260af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
261af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @see #registerInputDeviceListener
262af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
263af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public void unregisterInputDeviceListener(InputDeviceListener listener) {
264af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (listener == null) {
265af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            throw new IllegalArgumentException("listener must not be null");
266af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
267af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
268af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
269af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int index = findInputDeviceListenerLocked(listener);
270af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (index >= 0) {
271af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mInputDeviceListeners.remove(index);
272af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
273af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
274af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
275af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
276af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private int findInputDeviceListenerLocked(InputDeviceListener listener) {
277af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        final int numListeners = mInputDeviceListeners.size();
278af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        for (int i = 0; i < numListeners; i++) {
279af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (mInputDeviceListeners.get(i).mListener == listener) {
280af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                return i;
281af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
282af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
283af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        return -1;
284af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
285af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
286af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
2879df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Gets information about all supported keyboard layouts.
2889df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
2899df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The input manager consults the built-in keyboard layouts as well
2909df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * as all keyboard layouts advertised by applications using a
2919df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver.
2929df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
2939df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
2949df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @return A list of all supported keyboard layouts.
2959f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     *
2969df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
2979df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
2989f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public KeyboardLayout[] getKeyboardLayouts() {
2999f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        try {
3009f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return mIm.getKeyboardLayouts();
3019f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
3029f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            Log.w(TAG, "Could not get list of keyboard layout informations.", ex);
3039f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return new KeyboardLayout[0];
3049df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
3059df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
3069df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
3079df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
3089df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Gets the keyboard layout with the specified descriptor.
3099df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
3109df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @param keyboardLayoutDescriptor The keyboard layout descriptor, as returned by
3119df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * {@link KeyboardLayout#getDescriptor()}.
3129df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @return The keyboard layout, or null if it could not be loaded.
3139df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
3149df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
3159df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
3169df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
3179df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        if (keyboardLayoutDescriptor == null) {
3189df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
3199df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
3209df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
3219df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        try {
3229f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return mIm.getKeyboardLayout(keyboardLayoutDescriptor);
3239f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
3249f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            Log.w(TAG, "Could not get keyboard layout information.", ex);
3259df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            return null;
3269df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
3279df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
3289df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
3299df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
3309df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Gets the keyboard layout descriptor for the specified input device.
3319df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
3329df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @param inputDeviceDescriptor The input device descriptor.
3339df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @return The keyboard layout descriptor, or null if unknown or if the default
3349df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * keyboard layout will be used.
3359df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
3369df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
3379df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
3389f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public String getKeyboardLayoutForInputDevice(String inputDeviceDescriptor) {
3399df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        if (inputDeviceDescriptor == null) {
3409df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
3419df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
3429df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
3439f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        try {
3449f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return mIm.getKeyboardLayoutForInputDevice(inputDeviceDescriptor);
3459f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
3469f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            Log.w(TAG, "Could not get keyboard layout for input device.", ex);
3479f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return null;
3489f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
3499df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
3509df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
3519df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
3529df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Sets the keyboard layout descriptor for the specified input device.
3539df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
3549df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * This method may have the side-effect of causing the input device in question
3559df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * to be reconfigured.
3569df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
3579df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
3589df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @param inputDeviceDescriptor The input device descriptor.
3599df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @param keyboardLayoutDescriptor The keyboard layout descriptor, or null to remove
3609df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * the mapping so that the default keyboard layout will be used for the input device.
3619df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
3629df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
3639df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
3649f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public void setKeyboardLayoutForInputDevice(String inputDeviceDescriptor,
3659df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            String keyboardLayoutDescriptor) {
3669df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        if (inputDeviceDescriptor == null) {
3679df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
3689df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
3699df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
3709df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        try {
3719f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            mIm.setKeyboardLayoutForInputDevice(inputDeviceDescriptor, keyboardLayoutDescriptor);
3729f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
3739f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            Log.w(TAG, "Could not set keyboard layout for input device.", ex);
3749df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
3759df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
3769df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
377ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
378ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Gets the mouse pointer speed.
379ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
380ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Only returns the permanent mouse pointer speed.  Ignores any temporary pointer
381ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * speed set by {@link #tryPointerSpeed}.
382ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
383ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
3849f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @param context The application context.
385ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @return The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
386ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
387ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
388ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
389ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
3909f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public int getPointerSpeed(Context context) {
391ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        int speed = DEFAULT_POINTER_SPEED;
392ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
3939f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            speed = Settings.System.getInt(context.getContentResolver(),
394ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                    Settings.System.POINTER_SPEED);
395ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (SettingNotFoundException snfe) {
396ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
397ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        return speed;
398ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
399ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
400ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
401ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Sets the mouse pointer speed.
402ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
403ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Requires {@link android.Manifest.permissions.WRITE_SETTINGS}.
404ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
405ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
4069f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @param context The application context.
407ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
408ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
409ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
410ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
411ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
4129f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public void setPointerSpeed(Context context, int speed) {
413ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
414ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("speed out of range");
415ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
416ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
4179f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        Settings.System.putInt(context.getContentResolver(),
418ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                Settings.System.POINTER_SPEED, speed);
419ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
420ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
421ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
422ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Changes the mouse pointer speed temporarily, but does not save the setting.
423ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
424ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Requires {@link android.Manifest.permission.SET_POINTER_SPEED}.
425ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
426ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
427ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
428ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
429ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
430ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
431ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
432ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public void tryPointerSpeed(int speed) {
433ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
434ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("speed out of range");
435ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
436ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
437ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
4389f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            mIm.tryPointerSpeed(speed);
439ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (RemoteException ex) {
440ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            Log.w(TAG, "Could not set temporary pointer speed.", ex);
441ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
442ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
443ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
444ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
445ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Queries the framework about whether any physical keys exist on the
446ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * any keyboard attached to the device that are capable of producing the given
447ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * array of key codes.
448ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
449ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param keyCodes The array of key codes to query.
450ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @return A new array of the same size as the key codes array whose elements
451ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * are set to true if at least one attached keyboard supports the corresponding key code
452ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * at the same index in the key codes array.
453ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
454ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
455ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
4569f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public boolean[] deviceHasKeys(int[] keyCodes) {
457ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        boolean[] ret = new boolean[keyCodes.length];
458ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
4599f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            mIm.hasKeys(-1, InputDevice.SOURCE_ANY, keyCodes, ret);
460ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (RemoteException e) {
461ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            // no fallback; just return the empty array
462ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
463ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        return ret;
464ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
465ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
466ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
467ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Injects an input event into the event system on behalf of an application.
468ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * The synchronization mode determines whether the method blocks while waiting for
469ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * input injection to proceed.
470ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
471ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Requires {@link android.Manifest.permission.INJECT_EVENTS} to inject into
472ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * windows that are owned by other applications.
473ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p><p>
474ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Make sure you correctly set the event time and input source of the event
475ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * before calling this method.
476ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
477ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
478ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param event The event to inject.
479ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param mode The synchronization mode.  One of:
480ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #INJECT_INPUT_EVENT_MODE_ASYNC},
481ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT}, or
482ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH}.
483ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @return True if input event injection succeeded.
484ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
485ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
486ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
4879f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public boolean injectInputEvent(InputEvent event, int mode) {
488ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (event == null) {
489ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("event must not be null");
490ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
491ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (mode != INJECT_INPUT_EVENT_MODE_ASYNC
492ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                && mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
493ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                && mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
494ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("mode is invalid");
495ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
496ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
497ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
4989f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return mIm.injectInputEvent(event, mode);
499ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (RemoteException ex) {
500ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            return false;
501ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
502ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
503af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
504af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void populateInputDevicesLocked() {
505af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (mInputDevicesChangedListener == null) {
506af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final InputDevicesChangedListener listener = new InputDevicesChangedListener();
507af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            try {
508af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mIm.registerInputDevicesChangedListener(listener);
509af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            } catch (RemoteException ex) {
510af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                throw new RuntimeException(
511af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        "Could not get register input device changed listener", ex);
512af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
513af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mInputDevicesChangedListener = listener;
514af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
515af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
516af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (mInputDevices == null) {
517af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int[] ids;
518af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            try {
519af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                ids = mIm.getInputDeviceIds();
520af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            } catch (RemoteException ex) {
521af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                throw new RuntimeException("Could not get input device ids.", ex);
522af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
523af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
524af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mInputDevices = new SparseArray<InputDevice>();
525af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < ids.length; i++) {
526af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mInputDevices.put(ids[i], null);
527af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
528af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
529af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
530af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
531af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void onInputDevicesChanged(int[] deviceIdAndGeneration) {
532af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (DEBUG) {
533af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            Log.d(TAG, "Received input devices changed.");
534af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
535af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
536af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
537af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = mInputDevices.size(); --i > 0; ) {
538af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                final int deviceId = mInputDevices.keyAt(i);
539af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                if (!containsDeviceId(deviceIdAndGeneration, deviceId)) {
540af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    if (DEBUG) {
541af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        Log.d(TAG, "Device removed: " + deviceId);
542af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    }
543af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mInputDevices.removeAt(i);
544af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    sendMessageToInputDeviceListenersLocked(MSG_DEVICE_REMOVED, deviceId);
545af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                }
546af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
547af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
548af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
549af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                final int deviceId = deviceIdAndGeneration[i];
550af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                int index = mInputDevices.indexOfKey(deviceId);
551af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                if (index >= 0) {
552af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    final InputDevice device = mInputDevices.valueAt(index);
553af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    if (device != null) {
554af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        final int generation = deviceIdAndGeneration[i + 1];
555af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        if (device.getGeneration() != generation) {
556af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            if (DEBUG) {
557af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                                Log.d(TAG, "Device changed: " + deviceId);
558af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            }
559af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            mInputDevices.setValueAt(index, null);
560af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            sendMessageToInputDeviceListenersLocked(MSG_DEVICE_CHANGED, deviceId);
561af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        }
562af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    }
563af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                } else {
564af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    if (DEBUG) {
565af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        Log.d(TAG, "Device added: " + deviceId);
566af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    }
567af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mInputDevices.put(deviceId, null);
568af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    sendMessageToInputDeviceListenersLocked(MSG_DEVICE_ADDED, deviceId);
569af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                }
570af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
571af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
572af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
573af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
574af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void sendMessageToInputDeviceListenersLocked(int what, int deviceId) {
575af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        final int numListeners = mInputDeviceListeners.size();
576af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        for (int i = 0; i < numListeners; i++) {
577af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            InputDeviceListenerDelegate listener = mInputDeviceListeners.get(i);
578af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            listener.sendMessage(listener.obtainMessage(what, deviceId, 0));
579af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
580af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
581af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
582af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static boolean containsDeviceId(int[] deviceIdAndGeneration, int deviceId) {
583af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
584af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (deviceIdAndGeneration[i] == deviceId) {
585af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                return true;
586af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
587af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
588af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        return false;
589af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
590af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
591af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
592a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     * Gets a vibrator service associated with an input device, assuming it has one.
593a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     * @return The vibrator, never null.
594a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     * @hide
595a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     */
596a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    public Vibrator getInputDeviceVibrator(int deviceId) {
597a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        return new InputDeviceVibrator(deviceId);
598a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
599a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
600a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    /**
601af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Listens for changes in input devices.
602af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
603af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public interface InputDeviceListener {
604af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        /**
605af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Called whenever an input device has been added to the system.
606af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Use {@link InputManager#getInputDevice} to get more information about the device.
607af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         *
608af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * @param deviceId The id of the input device that was added.
609af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         */
610af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        void onInputDeviceAdded(int deviceId);
611af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
612af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        /**
613af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Called whenever an input device has been removed from the system.
614af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         *
615af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * @param deviceId The id of the input device that was removed.
616af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         */
617af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        void onInputDeviceRemoved(int deviceId);
618af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
619af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        /**
620af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Called whenever the properties of an input device have changed since they
621af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * were last queried.  Use {@link InputManager#getInputDevice} to get
622af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * a fresh {@link InputDevice} object with the new properties.
623af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         *
624af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * @param deviceId The id of the input device that changed.
625af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         */
626af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        void onInputDeviceChanged(int deviceId);
627af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
628af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
629af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final class InputDevicesChangedListener extends IInputDevicesChangedListener.Stub {
630af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        @Override
631af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public void onInputDevicesChanged(int[] deviceIdAndGeneration) throws RemoteException {
632af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            InputManager.this.onInputDevicesChanged(deviceIdAndGeneration);
633af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
634af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
635af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
636af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final class InputDeviceListenerDelegate extends Handler {
637af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public final InputDeviceListener mListener;
638af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
639af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public InputDeviceListenerDelegate(InputDeviceListener listener, Handler handler) {
640af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            super(handler != null ? handler.getLooper() : Looper.myLooper());
641af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mListener = listener;
642af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
643af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
644af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        @Override
645af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public void handleMessage(Message msg) {
646af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            switch (msg.what) {
647af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                case MSG_DEVICE_ADDED:
648af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mListener.onInputDeviceAdded(msg.arg1);
649af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    break;
650af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                case MSG_DEVICE_REMOVED:
651af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mListener.onInputDeviceRemoved(msg.arg1);
652af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    break;
653af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                case MSG_DEVICE_CHANGED:
654af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mListener.onInputDeviceChanged(msg.arg1);
655af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    break;
656af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
657af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
658af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
659a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
660a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    private final class InputDeviceVibrator extends Vibrator {
661a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        private final int mDeviceId;
662a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        private final Binder mToken;
663a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
664a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public InputDeviceVibrator(int deviceId) {
665a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mDeviceId = deviceId;
666a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mToken = new Binder();
667a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
668a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
669a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
670a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public boolean hasVibrator() {
671a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            return true;
672a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
673a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
674a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
675a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public void vibrate(long milliseconds) {
676a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            vibrate(new long[] { 0, milliseconds}, -1);
677a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
678a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
679a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
680a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public void vibrate(long[] pattern, int repeat) {
681a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            if (repeat >= pattern.length) {
682a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                throw new ArrayIndexOutOfBoundsException();
683a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
684a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            try {
685a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                mIm.vibrate(mDeviceId, pattern, repeat, mToken);
686a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            } catch (RemoteException ex) {
687a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                Log.w(TAG, "Failed to vibrate.", ex);
688a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
689a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
690a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
691a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
692a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public void cancel() {
693a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            try {
694a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                mIm.cancelVibrate(mDeviceId, mToken);
695a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            } catch (RemoteException ex) {
696a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                Log.w(TAG, "Failed to cancel vibration.", ex);
697a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
698a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
699a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
7009df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown}
701