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