InputManager.java revision fb290df3c9a6f37ec050163029e25844de2f8590
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
19cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brownimport com.android.internal.util.ArrayUtils;
20cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
219df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.annotation.SdkConstant;
229df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.annotation.SdkConstant.SdkConstantType;
239df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.content.Context;
24a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brownimport android.os.Binder;
25af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.Handler;
26ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.IBinder;
27af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.Looper;
28af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.Message;
29fb290df3c9a6f37ec050163029e25844de2f8590RoboErikimport android.os.Parcel;
30fb290df3c9a6f37ec050163029e25844de2f8590RoboErikimport android.os.Parcelable;
31ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.RemoteException;
32ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.ServiceManager;
33a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brownimport android.os.Vibrator;
34ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.provider.Settings;
35ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.provider.Settings.SettingNotFoundException;
369df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.util.Log;
379f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.util.SparseArray;
38ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.view.InputDevice;
39ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.view.InputEvent;
409df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
41af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport java.util.ArrayList;
42af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
439df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown/**
449df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Provides information about input devices and available key layouts.
459df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * <p>
469df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Get an instance of this class by calling
479df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * {@link android.content.Context#getSystemService(java.lang.String)
489df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Context.getSystemService()} with the argument
499df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * {@link android.content.Context#INPUT_SERVICE}.
509df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * </p>
519df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown */
529df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownpublic final class InputManager {
539df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    private static final String TAG = "InputManager";
54af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final boolean DEBUG = false;
55af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
56af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final int MSG_DEVICE_ADDED = 1;
57af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final int MSG_DEVICE_REMOVED = 2;
58af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final int MSG_DEVICE_CHANGED = 3;
599df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
609f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    private static InputManager sInstance;
619df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
629f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    private final IInputManager mIm;
63af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
64af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    // Guarded by mInputDevicesLock
65af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final Object mInputDevicesLock = new Object();
66af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private SparseArray<InputDevice> mInputDevices;
67af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private InputDevicesChangedListener mInputDevicesChangedListener;
68af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners =
69af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            new ArrayList<InputDeviceListenerDelegate>();
709df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
719df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
729df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Broadcast Action: Query available keyboard layouts.
739df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
749df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The input manager service locates available keyboard layouts
759df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * by querying broadcast receivers that are registered for this action.
769df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * An application can offer additional keyboard layouts to the user
779df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * by declaring a suitable broadcast receiver in its manifest.
789df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p><p>
799df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Here is an example broadcast receiver declaration that an application
809df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * might include in its AndroidManifest.xml to advertise keyboard layouts.
819df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The meta-data specifies a resource that contains a description of each keyboard
829df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * layout that is provided by the application.
839df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <pre><code>
84d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown     * &lt;receiver android:name=".InputDeviceReceiver"
85d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown     *         android:label="@string/keyboard_layouts_label">
869df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;intent-filter>
879df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *         &lt;action android:name="android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS" />
889df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;/intent-filter>
899df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;meta-data android:name="android.hardware.input.metadata.KEYBOARD_LAYOUTS"
909df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *             android:resource="@xml/keyboard_layouts" />
919df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;/receiver>
929df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </code></pre>
939df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p><p>
949df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * In the above example, the <code>@xml/keyboard_layouts</code> resource refers to
959df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * an XML resource whose root element is <code>&lt;keyboard-layouts></code> that
969df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * contains zero or more <code>&lt;keyboard-layout></code> elements.
979df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Each <code>&lt;keyboard-layout></code> element specifies the name, label, and location
98d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown     * of a key character map for a particular keyboard layout.  The label on the receiver
99d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown     * is used to name the collection of keyboard layouts provided by this receiver in the
100d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown     * keyboard layout settings.
1019df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <pre></code>
1029df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;?xml version="1.0" encoding="utf-8"?>
1039df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;keyboard-layouts xmlns:android="http://schemas.android.com/apk/res/android">
1049df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;keyboard-layout android:name="keyboard_layout_english_us"
1059df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *             android:label="@string/keyboard_layout_english_us_label"
1062f0957607411b99810226ad38d59cf18718b86d0Jeff Brown     *             android:keyboardLayout="@raw/keyboard_layout_english_us" />
1079df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;/keyboard-layouts>
1089df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p><p>
1099df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The <code>android:name</code> attribute specifies an identifier by which
1109df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * the keyboard layout will be known in the package.
1119df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The <code>android:label</code> attributes specifies a human-readable descriptive
1129df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * label to describe the keyboard layout in the user interface, such as "English (US)".
1132f0957607411b99810226ad38d59cf18718b86d0Jeff Brown     * The <code>android:keyboardLayout</code> attribute refers to a
1149df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <a href="http://source.android.com/tech/input/key-character-map-files.html">
1159df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * key character map</a> resource that defines the keyboard layout.
1169df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
1179df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
1189df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
1199df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    public static final String ACTION_QUERY_KEYBOARD_LAYOUTS =
1209df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            "android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS";
1219df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
1229df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
1239df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Metadata Key: Keyboard layout metadata associated with
1249df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS}.
1259df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
1269df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Specifies the resource id of a XML resource that describes the keyboard
1279df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * layouts that are provided by the application.
1289df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
1299df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
1309df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    public static final String META_DATA_KEYBOARD_LAYOUTS =
1319df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            "android.hardware.input.metadata.KEYBOARD_LAYOUTS";
1329df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
133ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
134ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Pointer Speed: The minimum (slowest) pointer speed (-7).
135ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
136ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
137ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int MIN_POINTER_SPEED = -7;
138ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
139ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
140ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Pointer Speed: The maximum (fastest) pointer speed (7).
141ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
142ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
143ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int MAX_POINTER_SPEED = 7;
144ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
145ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
146ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Pointer Speed: The default pointer speed (0).
147ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
148ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
149ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int DEFAULT_POINTER_SPEED = 0;
150ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
151ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
152ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Input Event Injection Synchronization Mode: None.
153ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Never blocks.  Injection is asynchronous and is assumed always to be successful.
154ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
155ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
156ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int INJECT_INPUT_EVENT_MODE_ASYNC = 0; // see InputDispatcher.h
157ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
158ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
159ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Input Event Injection Synchronization Mode: Wait for result.
160ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Waits for previous events to be dispatched so that the input dispatcher can
161ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * determine whether input event injection will be permitted based on the current
162ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * input focus.  Does not wait for the input event to finish being handled
163ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * by the application.
164ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
165ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
166ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1;  // see InputDispatcher.h
167ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
168ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
169ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Input Event Injection Synchronization Mode: Wait for finish.
170ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Waits for the event to be delivered to the application and handled.
171ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
172ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
173ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2;  // see InputDispatcher.h
174ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
1759f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    private InputManager(IInputManager im) {
1769f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        mIm = im;
177ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
178ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
1799f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    /**
1809f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * Gets an instance of the input manager.
1819f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     *
1829f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @return The input manager instance.
1839f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     *
1849f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @hide
1859f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     */
1869f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public static InputManager getInstance() {
1879f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        synchronized (InputManager.class) {
1889f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            if (sInstance == null) {
1899f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                IBinder b = ServiceManager.getService(Context.INPUT_SERVICE);
1909f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                sInstance = new InputManager(IInputManager.Stub.asInterface(b));
1919f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            }
1929f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return sInstance;
1939f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
1949df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
1959df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
1969df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
197af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Gets information about the input device with the specified id.
198af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param id The device id.
199af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @return The input device or null if not found.
200af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
201af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public InputDevice getInputDevice(int id) {
202af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
203af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            populateInputDevicesLocked();
204af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
205af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int index = mInputDevices.indexOfKey(id);
206af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (index < 0) {
207af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                return null;
208af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
209af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
210af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            InputDevice inputDevice = mInputDevices.valueAt(index);
211af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (inputDevice == null) {
212af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                try {
213af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    inputDevice = mIm.getInputDevice(id);
214af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                } catch (RemoteException ex) {
215af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    throw new RuntimeException("Could not get input device information.", ex);
216af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                }
2178f124842dd16125062f048257889c85380879b68Jeff Brown                if (inputDevice != null) {
2188f124842dd16125062f048257889c85380879b68Jeff Brown                    mInputDevices.setValueAt(index, inputDevice);
2198f124842dd16125062f048257889c85380879b68Jeff Brown                }
220af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
221af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            return inputDevice;
222af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
223af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
224af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
225af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
226cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * Gets information about the input device with the specified descriptor.
227cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @param descriptor The input device descriptor.
228cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @return The input device or null if not found.
229cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @hide
230cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     */
231cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    public InputDevice getInputDeviceByDescriptor(String descriptor) {
232cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (descriptor == null) {
233cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("descriptor must not be null.");
234cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
235cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
236cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        synchronized (mInputDevicesLock) {
237cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            populateInputDevicesLocked();
238cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
239cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            int numDevices = mInputDevices.size();
240cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            for (int i = 0; i < numDevices; i++) {
241cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                InputDevice inputDevice = mInputDevices.valueAt(i);
242cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                if (inputDevice == null) {
243cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    int id = mInputDevices.keyAt(i);
244cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    try {
245cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        inputDevice = mIm.getInputDevice(id);
246cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    } catch (RemoteException ex) {
247cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        // Ignore the problem for the purposes of this method.
2488f124842dd16125062f048257889c85380879b68Jeff Brown                    }
2498f124842dd16125062f048257889c85380879b68Jeff Brown                    if (inputDevice == null) {
250cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        continue;
251cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    }
252cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    mInputDevices.setValueAt(i, inputDevice);
253cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
254cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                if (descriptor.equals(inputDevice.getDescriptor())) {
255cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    return inputDevice;
256cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
257cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
258cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            return null;
259cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
260cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
261cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
262cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    /**
263af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Gets the ids of all input devices in the system.
264af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @return The input device ids.
265af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
266af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public int[] getInputDeviceIds() {
267af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
268af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            populateInputDevicesLocked();
269af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
270af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int count = mInputDevices.size();
271af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int[] ids = new int[count];
272af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < count; i++) {
273af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                ids[i] = mInputDevices.keyAt(i);
274af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
275af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            return ids;
276af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
277af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
278af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
279af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
280af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Registers an input device listener to receive notifications about when
281af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * input devices are added, removed or changed.
282af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
283af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param listener The listener to register.
284af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param handler The handler on which the listener should be invoked, or null
285af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * if the listener should be invoked on the calling thread's looper.
286af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
287af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @see #unregisterInputDeviceListener
288af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
289af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
290af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (listener == null) {
291af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            throw new IllegalArgumentException("listener must not be null");
292af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
293af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
294af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
295af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int index = findInputDeviceListenerLocked(listener);
296af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (index < 0) {
297af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mInputDeviceListeners.add(new InputDeviceListenerDelegate(listener, handler));
298af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
299af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
300af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
301af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
302af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
303af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Unregisters an input device listener.
304af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
305af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param listener The listener to unregister.
306af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
307af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @see #registerInputDeviceListener
308af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
309af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public void unregisterInputDeviceListener(InputDeviceListener listener) {
310af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (listener == null) {
311af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            throw new IllegalArgumentException("listener must not be null");
312af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
313af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
314af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
315af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int index = findInputDeviceListenerLocked(listener);
316af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (index >= 0) {
3179e6d4b035d4f012d23264d3d2bc946b1ca02dba1Jeff Brown                InputDeviceListenerDelegate d = mInputDeviceListeners.get(index);
3189e6d4b035d4f012d23264d3d2bc946b1ca02dba1Jeff Brown                d.removeCallbacksAndMessages(null);
319af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mInputDeviceListeners.remove(index);
320af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
321af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
322af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
323af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
324af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private int findInputDeviceListenerLocked(InputDeviceListener listener) {
325af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        final int numListeners = mInputDeviceListeners.size();
326af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        for (int i = 0; i < numListeners; i++) {
327af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (mInputDeviceListeners.get(i).mListener == listener) {
328af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                return i;
329af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
330af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
331af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        return -1;
332af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
333af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
334af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
3359df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Gets information about all supported keyboard layouts.
3369df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
3379df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The input manager consults the built-in keyboard layouts as well
3389df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * as all keyboard layouts advertised by applications using a
3399df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver.
3409df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
3419df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
3429df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @return A list of all supported keyboard layouts.
3439f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     *
3449df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
3459df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
3469f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public KeyboardLayout[] getKeyboardLayouts() {
3479f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        try {
3489f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return mIm.getKeyboardLayouts();
3499f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
3509f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            Log.w(TAG, "Could not get list of keyboard layout informations.", ex);
3519f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return new KeyboardLayout[0];
3529df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
3539df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
3549df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
3559df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
3569df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Gets the keyboard layout with the specified descriptor.
3579df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
3589df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @param keyboardLayoutDescriptor The keyboard layout descriptor, as returned by
3599df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * {@link KeyboardLayout#getDescriptor()}.
3609df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @return The keyboard layout, or null if it could not be loaded.
3619df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
3629df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
3639df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
3649df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
3659df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        if (keyboardLayoutDescriptor == null) {
3669df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
3679df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
3689df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
3699df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        try {
3709f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return mIm.getKeyboardLayout(keyboardLayoutDescriptor);
3719f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
3729f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            Log.w(TAG, "Could not get keyboard layout information.", ex);
3739df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            return null;
3749df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
3759df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
3769df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
3779df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
378fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * Gets the current keyboard layout descriptor for the specified input
379fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * device.
3809df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
381fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param identifier Identifier for the input device
382fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @return The keyboard layout descriptor, or null if no keyboard layout has
383fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     *         been set.
3849df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
3859df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
386fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
3879f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        try {
388fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            return mIm.getCurrentKeyboardLayoutForInputDevice(identifier);
3899f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
390cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            Log.w(TAG, "Could not get current keyboard layout for input device.", ex);
3919f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return null;
3929f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
3939df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
3949df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
3959df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
396fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * Sets the current keyboard layout descriptor for the specified input
397fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * device.
3989df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
399fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * This method may have the side-effect of causing the input device in
400fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * question to be reconfigured.
4019df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
4029df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
403fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param identifier The identifier for the input device.
404fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param keyboardLayoutDescriptor The keyboard layout descriptor to use,
405fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     *            must not be null.
4069df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
4079df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
408fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
4099df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            String keyboardLayoutDescriptor) {
410fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier == null) {
411fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            throw new IllegalArgumentException("identifier must not be null");
4129df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
413cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (keyboardLayoutDescriptor == null) {
414cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
415cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
416cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
417cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        try {
418fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            mIm.setCurrentKeyboardLayoutForInputDevice(identifier,
419cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    keyboardLayoutDescriptor);
420cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        } catch (RemoteException ex) {
421cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            Log.w(TAG, "Could not set current keyboard layout for input device.", ex);
422cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
423cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
424cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
425cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    /**
426fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * Gets all keyboard layout descriptors that are enabled for the specified
427fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * input device.
428cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     *
429fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param identifier The identifier for the input device.
430cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @return The keyboard layout descriptors.
431cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @hide
432cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     */
433fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public String[] getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
434fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier == null) {
435cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
436cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
437cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
438cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        try {
439fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            return mIm.getKeyboardLayoutsForInputDevice(identifier);
440cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        } catch (RemoteException ex) {
441cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            Log.w(TAG, "Could not get keyboard layouts for input device.", ex);
442cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            return ArrayUtils.emptyArray(String.class);
443cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
444cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
445cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
446cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    /**
447cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * Adds the keyboard layout descriptor for the specified input device.
448cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * <p>
449fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * This method may have the side-effect of causing the input device in
450fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * question to be reconfigured.
451cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * </p>
452cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     *
453fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param identifier The identifier for the input device.
454fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param keyboardLayoutDescriptor The descriptor of the keyboard layout to
455fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     *            add.
456cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @hide
457cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     */
458fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
459cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            String keyboardLayoutDescriptor) {
460fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier == null) {
461cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
462cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
463cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (keyboardLayoutDescriptor == null) {
464cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
465cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
466cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
467cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        try {
468fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            mIm.addKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
469cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        } catch (RemoteException ex) {
470cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            Log.w(TAG, "Could not add keyboard layout for input device.", ex);
471cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
472cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
473cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
474cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    /**
475cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * Removes the keyboard layout descriptor for the specified input device.
476cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * <p>
477fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * This method may have the side-effect of causing the input device in
478fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * question to be reconfigured.
479cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * </p>
480cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     *
481fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param identifier The identifier for the input device.
482fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param keyboardLayoutDescriptor The descriptor of the keyboard layout to
483fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     *            remove.
484cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @hide
485cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     */
486fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
487cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            String keyboardLayoutDescriptor) {
488fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier == null) {
489cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
490cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
491cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (keyboardLayoutDescriptor == null) {
492cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
493cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
4949df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
4959df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        try {
496fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            mIm.removeKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
4979f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
498cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            Log.w(TAG, "Could not remove keyboard layout for input device.", ex);
4999df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
5009df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
5019df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
502ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
503ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Gets the mouse pointer speed.
504ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
505ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Only returns the permanent mouse pointer speed.  Ignores any temporary pointer
506ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * speed set by {@link #tryPointerSpeed}.
507ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
508ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
5099f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @param context The application context.
510ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @return The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
511ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
512ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
513ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
514ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
5159f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public int getPointerSpeed(Context context) {
516ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        int speed = DEFAULT_POINTER_SPEED;
517ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
5189f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            speed = Settings.System.getInt(context.getContentResolver(),
519ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                    Settings.System.POINTER_SPEED);
520ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (SettingNotFoundException snfe) {
521ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
522ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        return speed;
523ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
524ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
525ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
526ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Sets the mouse pointer speed.
527ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
528ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Requires {@link android.Manifest.permissions.WRITE_SETTINGS}.
529ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
530ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
5319f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @param context The application context.
532ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
533ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
534ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
535ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
536ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
5379f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public void setPointerSpeed(Context context, int speed) {
538ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
539ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("speed out of range");
540ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
541ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
5429f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        Settings.System.putInt(context.getContentResolver(),
543ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                Settings.System.POINTER_SPEED, speed);
544ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
545ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
546ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
547ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Changes the mouse pointer speed temporarily, but does not save the setting.
548ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
549ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Requires {@link android.Manifest.permission.SET_POINTER_SPEED}.
550ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
551ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
552ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
553ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
554ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
555ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
556ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
557ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public void tryPointerSpeed(int speed) {
558ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
559ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("speed out of range");
560ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
561ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
562ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
5639f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            mIm.tryPointerSpeed(speed);
564ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (RemoteException ex) {
565ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            Log.w(TAG, "Could not set temporary pointer speed.", ex);
566ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
567ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
568ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
569ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
570ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Queries the framework about whether any physical keys exist on the
571ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * any keyboard attached to the device that are capable of producing the given
572ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * array of key codes.
573ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
574ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param keyCodes The array of key codes to query.
575ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @return A new array of the same size as the key codes array whose elements
576ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * are set to true if at least one attached keyboard supports the corresponding key code
577ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * at the same index in the key codes array.
578ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
579ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
580ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
5819f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public boolean[] deviceHasKeys(int[] keyCodes) {
582b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright        return deviceHasKeys(-1, keyCodes);
583b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright    }
584b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright
585b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright    /**
586b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * Queries the framework about whether any physical keys exist on the
587b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * any keyboard attached to the device that are capable of producing the given
588b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * array of key codes.
589b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     *
590b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * @param id The id of the device to query.
591b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * @param keyCodes The array of key codes to query.
592b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * @return A new array of the same size as the key codes array whose elements are set to true
593b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * if the given device could produce the corresponding key code at the same index in the key
594b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * codes array.
595b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     *
596b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * @hide
597b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     */
598b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright    public boolean[] deviceHasKeys(int id, int[] keyCodes) {
599ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        boolean[] ret = new boolean[keyCodes.length];
600ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
601b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright            mIm.hasKeys(id, InputDevice.SOURCE_ANY, keyCodes, ret);
602ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (RemoteException e) {
603ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            // no fallback; just return the empty array
604ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
605ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        return ret;
606ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
607ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
608b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright
609ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
610ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Injects an input event into the event system on behalf of an application.
611ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * The synchronization mode determines whether the method blocks while waiting for
612ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * input injection to proceed.
613ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
614ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Requires {@link android.Manifest.permission.INJECT_EVENTS} to inject into
615ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * windows that are owned by other applications.
616ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p><p>
617ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Make sure you correctly set the event time and input source of the event
618ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * before calling this method.
619ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
620ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
621ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param event The event to inject.
622ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param mode The synchronization mode.  One of:
623ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #INJECT_INPUT_EVENT_MODE_ASYNC},
624ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT}, or
625ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH}.
626ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @return True if input event injection succeeded.
627ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
628ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
629ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
6309f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public boolean injectInputEvent(InputEvent event, int mode) {
631ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (event == null) {
632ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("event must not be null");
633ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
634ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (mode != INJECT_INPUT_EVENT_MODE_ASYNC
635ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                && mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
636ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                && mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
637ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("mode is invalid");
638ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
639ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
640ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
6419f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return mIm.injectInputEvent(event, mode);
642ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (RemoteException ex) {
643ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            return false;
644ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
645ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
646af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
647af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void populateInputDevicesLocked() {
648af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (mInputDevicesChangedListener == null) {
649af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final InputDevicesChangedListener listener = new InputDevicesChangedListener();
650af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            try {
651af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mIm.registerInputDevicesChangedListener(listener);
652af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            } catch (RemoteException ex) {
653af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                throw new RuntimeException(
654af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        "Could not get register input device changed listener", ex);
655af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
656af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mInputDevicesChangedListener = listener;
657af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
658af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
659af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (mInputDevices == null) {
660af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int[] ids;
661af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            try {
662af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                ids = mIm.getInputDeviceIds();
663af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            } catch (RemoteException ex) {
664af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                throw new RuntimeException("Could not get input device ids.", ex);
665af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
666af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
667af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mInputDevices = new SparseArray<InputDevice>();
668af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < ids.length; i++) {
669af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mInputDevices.put(ids[i], null);
670af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
671af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
672af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
673af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
674af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void onInputDevicesChanged(int[] deviceIdAndGeneration) {
675af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (DEBUG) {
676af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            Log.d(TAG, "Received input devices changed.");
677af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
678af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
679af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
680af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = mInputDevices.size(); --i > 0; ) {
681af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                final int deviceId = mInputDevices.keyAt(i);
682af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                if (!containsDeviceId(deviceIdAndGeneration, deviceId)) {
683af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    if (DEBUG) {
684af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        Log.d(TAG, "Device removed: " + deviceId);
685af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    }
686af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mInputDevices.removeAt(i);
687af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    sendMessageToInputDeviceListenersLocked(MSG_DEVICE_REMOVED, deviceId);
688af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                }
689af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
690af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
691af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
692af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                final int deviceId = deviceIdAndGeneration[i];
693af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                int index = mInputDevices.indexOfKey(deviceId);
694af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                if (index >= 0) {
695af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    final InputDevice device = mInputDevices.valueAt(index);
696af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    if (device != null) {
697af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        final int generation = deviceIdAndGeneration[i + 1];
698af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        if (device.getGeneration() != generation) {
699af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            if (DEBUG) {
700af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                                Log.d(TAG, "Device changed: " + deviceId);
701af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            }
702af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            mInputDevices.setValueAt(index, null);
703af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            sendMessageToInputDeviceListenersLocked(MSG_DEVICE_CHANGED, deviceId);
704af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        }
705af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    }
706af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                } else {
707af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    if (DEBUG) {
708af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        Log.d(TAG, "Device added: " + deviceId);
709af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    }
710af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mInputDevices.put(deviceId, null);
711af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    sendMessageToInputDeviceListenersLocked(MSG_DEVICE_ADDED, deviceId);
712af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                }
713af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
714af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
715af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
716af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
717af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void sendMessageToInputDeviceListenersLocked(int what, int deviceId) {
718af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        final int numListeners = mInputDeviceListeners.size();
719af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        for (int i = 0; i < numListeners; i++) {
720af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            InputDeviceListenerDelegate listener = mInputDeviceListeners.get(i);
721af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            listener.sendMessage(listener.obtainMessage(what, deviceId, 0));
722af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
723af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
724af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
725af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static boolean containsDeviceId(int[] deviceIdAndGeneration, int deviceId) {
726af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
727af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (deviceIdAndGeneration[i] == deviceId) {
728af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                return true;
729af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
730af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
731af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        return false;
732af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
733af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
734af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
735a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     * Gets a vibrator service associated with an input device, assuming it has one.
736a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     * @return The vibrator, never null.
737a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     * @hide
738a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     */
739a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    public Vibrator getInputDeviceVibrator(int deviceId) {
740a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        return new InputDeviceVibrator(deviceId);
741a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
742a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
743a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    /**
744af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Listens for changes in input devices.
745af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
746af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public interface InputDeviceListener {
747af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        /**
748af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Called whenever an input device has been added to the system.
749af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Use {@link InputManager#getInputDevice} to get more information about the device.
750af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         *
751af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * @param deviceId The id of the input device that was added.
752af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         */
753af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        void onInputDeviceAdded(int deviceId);
754af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
755af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        /**
756af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Called whenever an input device has been removed from the system.
757af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         *
758af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * @param deviceId The id of the input device that was removed.
759af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         */
760af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        void onInputDeviceRemoved(int deviceId);
761af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
762af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        /**
763af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Called whenever the properties of an input device have changed since they
764af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * were last queried.  Use {@link InputManager#getInputDevice} to get
765af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * a fresh {@link InputDevice} object with the new properties.
766af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         *
767af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * @param deviceId The id of the input device that changed.
768af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         */
769af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        void onInputDeviceChanged(int deviceId);
770af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
771af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
772af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final class InputDevicesChangedListener extends IInputDevicesChangedListener.Stub {
773af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        @Override
774af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public void onInputDevicesChanged(int[] deviceIdAndGeneration) throws RemoteException {
775af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            InputManager.this.onInputDevicesChanged(deviceIdAndGeneration);
776af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
777af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
778af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
779af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final class InputDeviceListenerDelegate extends Handler {
780af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public final InputDeviceListener mListener;
781af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
782af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public InputDeviceListenerDelegate(InputDeviceListener listener, Handler handler) {
783af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            super(handler != null ? handler.getLooper() : Looper.myLooper());
784af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mListener = listener;
785af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
786af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
787af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        @Override
788af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public void handleMessage(Message msg) {
789af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            switch (msg.what) {
790af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                case MSG_DEVICE_ADDED:
791af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mListener.onInputDeviceAdded(msg.arg1);
792af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    break;
793af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                case MSG_DEVICE_REMOVED:
794af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mListener.onInputDeviceRemoved(msg.arg1);
795af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    break;
796af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                case MSG_DEVICE_CHANGED:
797af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mListener.onInputDeviceChanged(msg.arg1);
798af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    break;
799af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
800af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
801af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
802a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
803a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    private final class InputDeviceVibrator extends Vibrator {
804a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        private final int mDeviceId;
805a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        private final Binder mToken;
806a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
807a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public InputDeviceVibrator(int deviceId) {
808a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mDeviceId = deviceId;
809a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mToken = new Binder();
810a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
811a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
812a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
813a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public boolean hasVibrator() {
814a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            return true;
815a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
816a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
817a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
818a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public void vibrate(long milliseconds) {
819a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            vibrate(new long[] { 0, milliseconds}, -1);
820a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
821a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
822a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
823a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public void vibrate(long[] pattern, int repeat) {
824a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            if (repeat >= pattern.length) {
825a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                throw new ArrayIndexOutOfBoundsException();
826a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
827a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            try {
828a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                mIm.vibrate(mDeviceId, pattern, repeat, mToken);
829a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            } catch (RemoteException ex) {
830a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                Log.w(TAG, "Failed to vibrate.", ex);
831a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
832a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
833a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
834f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        /**
835f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn         * @hide
836f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn         */
837f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        @Override
838f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        public void vibrate(int owningUid, String owningPackage, long milliseconds) {
839f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            vibrate(milliseconds);
840f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        }
841f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn
842f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        /**
843f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn         * @hide
844f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn         */
845f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        @Override
846f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        public void vibrate(int owningUid, String owningPackage, long[] pattern, int repeat) {
847f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            vibrate(pattern, repeat);
848f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        }
849f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn
850a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
851a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public void cancel() {
852a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            try {
853a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                mIm.cancelVibrate(mDeviceId, mToken);
854a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            } catch (RemoteException ex) {
855a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                Log.w(TAG, "Failed to cancel vibration.", ex);
856a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
857a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
858a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
8599df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown}
860