InputManager.java revision c53962d4ede82a03b62f0c8bb86bd0da090a15eb
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
19d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wrightimport com.android.internal.inputmethod.InputMethodSubtypeHandle;
2039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wrightimport com.android.internal.os.SomeArgs;
21cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brownimport com.android.internal.util.ArrayUtils;
22cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
239209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wrightimport android.annotation.IntDef;
249df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.annotation.SdkConstant;
259df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.annotation.SdkConstant.SdkConstantType;
269df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.content.Context;
277b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlockimport android.media.AudioAttributes;
28a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brownimport android.os.Binder;
29af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.Handler;
30ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.IBinder;
31af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.Looper;
32af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.Message;
33ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.RemoteException;
34ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.ServiceManager;
3539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wrightimport android.os.SystemClock;
36a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brownimport android.os.Vibrator;
37ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.provider.Settings;
38ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.provider.Settings.SettingNotFoundException;
399df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.util.Log;
409f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.util.SparseArray;
41ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.view.InputDevice;
42ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.view.InputEvent;
43d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wrightimport android.view.PointerIcon;
44d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wrightimport android.view.inputmethod.InputMethodInfo;
45d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wrightimport android.view.inputmethod.InputMethodSubtype;
469df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
479209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wrightimport java.lang.annotation.Retention;
489209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wrightimport java.lang.annotation.RetentionPolicy;
49af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport java.util.ArrayList;
5039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wrightimport java.util.List;
51af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
529df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown/**
539df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Provides information about input devices and available key layouts.
549df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * <p>
559df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Get an instance of this class by calling
569df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * {@link android.content.Context#getSystemService(java.lang.String)
579df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Context.getSystemService()} with the argument
589df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * {@link android.content.Context#INPUT_SERVICE}.
599df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * </p>
609df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown */
619df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownpublic final class InputManager {
629df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    private static final String TAG = "InputManager";
63af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final boolean DEBUG = false;
64af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
65af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final int MSG_DEVICE_ADDED = 1;
66af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final int MSG_DEVICE_REMOVED = 2;
67af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final int MSG_DEVICE_CHANGED = 3;
689df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
699f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    private static InputManager sInstance;
709df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
719f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    private final IInputManager mIm;
72af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
73af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    // Guarded by mInputDevicesLock
74af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final Object mInputDevicesLock = new Object();
75af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private SparseArray<InputDevice> mInputDevices;
76af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private InputDevicesChangedListener mInputDevicesChangedListener;
77af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners =
78af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            new ArrayList<InputDeviceListenerDelegate>();
799df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
8039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    // Guarded by mTabletModeLock
8139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private final Object mTabletModeLock = new Object();
8239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private TabletModeChangedListener mTabletModeChangedListener;
8339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private List<OnTabletModeChangedListenerDelegate> mOnTabletModeChangedListeners;
8439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
859df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
869df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Broadcast Action: Query available keyboard layouts.
879df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
889df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The input manager service locates available keyboard layouts
899df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * by querying broadcast receivers that are registered for this action.
909df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * An application can offer additional keyboard layouts to the user
919df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * by declaring a suitable broadcast receiver in its manifest.
929df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p><p>
939df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Here is an example broadcast receiver declaration that an application
949df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * might include in its AndroidManifest.xml to advertise keyboard layouts.
959df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The meta-data specifies a resource that contains a description of each keyboard
969df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * layout that is provided by the application.
979df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <pre><code>
98d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown     * &lt;receiver android:name=".InputDeviceReceiver"
99d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown     *         android:label="@string/keyboard_layouts_label">
1009df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;intent-filter>
1019df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *         &lt;action android:name="android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS" />
1029df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;/intent-filter>
1039df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;meta-data android:name="android.hardware.input.metadata.KEYBOARD_LAYOUTS"
1049df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *             android:resource="@xml/keyboard_layouts" />
1059df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;/receiver>
1069df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </code></pre>
1079df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p><p>
1089df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * In the above example, the <code>@xml/keyboard_layouts</code> resource refers to
1099df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * an XML resource whose root element is <code>&lt;keyboard-layouts></code> that
1109df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * contains zero or more <code>&lt;keyboard-layout></code> elements.
1119df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Each <code>&lt;keyboard-layout></code> element specifies the name, label, and location
112d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown     * of a key character map for a particular keyboard layout.  The label on the receiver
113d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown     * is used to name the collection of keyboard layouts provided by this receiver in the
114d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown     * keyboard layout settings.
115112449ca2983898b14e5e4dfe5d9d50b66f803a5Michael Wright     * <pre><code>
1169df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;?xml version="1.0" encoding="utf-8"?>
1179df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;keyboard-layouts xmlns:android="http://schemas.android.com/apk/res/android">
1189df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;keyboard-layout android:name="keyboard_layout_english_us"
1199df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *             android:label="@string/keyboard_layout_english_us_label"
1202f0957607411b99810226ad38d59cf18718b86d0Jeff Brown     *             android:keyboardLayout="@raw/keyboard_layout_english_us" />
1219df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;/keyboard-layouts>
122112449ca2983898b14e5e4dfe5d9d50b66f803a5Michael Wright     * </pre></code>
1239df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p><p>
1249df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The <code>android:name</code> attribute specifies an identifier by which
1259df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * the keyboard layout will be known in the package.
1269df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The <code>android:label</code> attributes specifies a human-readable descriptive
1279df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * label to describe the keyboard layout in the user interface, such as "English (US)".
1282f0957607411b99810226ad38d59cf18718b86d0Jeff Brown     * The <code>android:keyboardLayout</code> attribute refers to a
1299df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <a href="http://source.android.com/tech/input/key-character-map-files.html">
1309df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * key character map</a> resource that defines the keyboard layout.
1319df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
1329df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
1339df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
1349df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    public static final String ACTION_QUERY_KEYBOARD_LAYOUTS =
1359df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            "android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS";
1369df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
1379df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
1389df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Metadata Key: Keyboard layout metadata associated with
1399df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS}.
1409df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
1419df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Specifies the resource id of a XML resource that describes the keyboard
1429df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * layouts that are provided by the application.
1439df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
1449df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
1459df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    public static final String META_DATA_KEYBOARD_LAYOUTS =
1469df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            "android.hardware.input.metadata.KEYBOARD_LAYOUTS";
1479df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
148ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
149ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Pointer Speed: The minimum (slowest) pointer speed (-7).
150ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
151ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
152ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int MIN_POINTER_SPEED = -7;
153ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
154ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
155ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Pointer Speed: The maximum (fastest) pointer speed (7).
156ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
157ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
158ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int MAX_POINTER_SPEED = 7;
159ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
160ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
161ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Pointer Speed: The default pointer speed (0).
162ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
163ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
164ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int DEFAULT_POINTER_SPEED = 0;
165ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
166ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
167ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Input Event Injection Synchronization Mode: None.
168ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Never blocks.  Injection is asynchronous and is assumed always to be successful.
169ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
170ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
171ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int INJECT_INPUT_EVENT_MODE_ASYNC = 0; // see InputDispatcher.h
172ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
173ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
174ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Input Event Injection Synchronization Mode: Wait for result.
175ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Waits for previous events to be dispatched so that the input dispatcher can
176ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * determine whether input event injection will be permitted based on the current
177ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * input focus.  Does not wait for the input event to finish being handled
178ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * by the application.
179ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
180ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
181ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1;  // see InputDispatcher.h
182ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
183ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
184ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Input Event Injection Synchronization Mode: Wait for finish.
185ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Waits for the event to be delivered to the application and handled.
186ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
187ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
188ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2;  // see InputDispatcher.h
189ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
1909209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    /** @hide */
1919209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    @Retention(RetentionPolicy.SOURCE)
1929209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    @IntDef({SWITCH_STATE_UNKNOWN, SWITCH_STATE_OFF, SWITCH_STATE_ON})
1939209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    public @interface SwitchState {}
1949209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright
1959209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    /**
1969209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * Switch State: Unknown.
1979209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     *
1989209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * The system has yet to report a valid value for the switch.
1999209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * @hide
2009209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     */
2019209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    public static final int SWITCH_STATE_UNKNOWN = -1;
2029209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright
2039209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    /**
2049209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * Switch State: Off.
2059209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * @hide
2069209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     */
2079209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    public static final int SWITCH_STATE_OFF = 0;
2089209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright
2099209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    /**
2109209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * Switch State: On.
2119209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * @hide
2129209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     */
2139209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    public static final int SWITCH_STATE_ON = 1;
2149209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright
2159f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    private InputManager(IInputManager im) {
2169f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        mIm = im;
217ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
218ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
2199f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    /**
2209f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * Gets an instance of the input manager.
2219f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     *
2229f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @return The input manager instance.
2239f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     *
2249f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @hide
2259f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     */
2269f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public static InputManager getInstance() {
2279f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        synchronized (InputManager.class) {
2289f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            if (sInstance == null) {
2299f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                IBinder b = ServiceManager.getService(Context.INPUT_SERVICE);
2309f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                sInstance = new InputManager(IInputManager.Stub.asInterface(b));
2319f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            }
2329f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return sInstance;
2339f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
2349df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
2359df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
2369df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
237af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Gets information about the input device with the specified id.
238af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param id The device id.
239af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @return The input device or null if not found.
240af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
241af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public InputDevice getInputDevice(int id) {
242af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
243af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            populateInputDevicesLocked();
244af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
245af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int index = mInputDevices.indexOfKey(id);
246af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (index < 0) {
247af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                return null;
248af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
249af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
250af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            InputDevice inputDevice = mInputDevices.valueAt(index);
251af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (inputDevice == null) {
252af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                try {
253af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    inputDevice = mIm.getInputDevice(id);
254af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                } catch (RemoteException ex) {
255c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                    throw ex.rethrowFromSystemServer();
256af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                }
2578f124842dd16125062f048257889c85380879b68Jeff Brown                if (inputDevice != null) {
2588f124842dd16125062f048257889c85380879b68Jeff Brown                    mInputDevices.setValueAt(index, inputDevice);
2598f124842dd16125062f048257889c85380879b68Jeff Brown                }
260af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
261af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            return inputDevice;
262af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
263af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
264af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
265af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
266cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * Gets information about the input device with the specified descriptor.
267cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @param descriptor The input device descriptor.
268cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @return The input device or null if not found.
269cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @hide
270cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     */
271cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    public InputDevice getInputDeviceByDescriptor(String descriptor) {
272cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (descriptor == null) {
273cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("descriptor must not be null.");
274cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
275cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
276cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        synchronized (mInputDevicesLock) {
277cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            populateInputDevicesLocked();
278cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
279cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            int numDevices = mInputDevices.size();
280cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            for (int i = 0; i < numDevices; i++) {
281cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                InputDevice inputDevice = mInputDevices.valueAt(i);
282cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                if (inputDevice == null) {
283cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    int id = mInputDevices.keyAt(i);
284cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    try {
285cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        inputDevice = mIm.getInputDevice(id);
286cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    } catch (RemoteException ex) {
287c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                        throw ex.rethrowFromSystemServer();
2888f124842dd16125062f048257889c85380879b68Jeff Brown                    }
2898f124842dd16125062f048257889c85380879b68Jeff Brown                    if (inputDevice == null) {
290cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        continue;
291cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    }
292cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    mInputDevices.setValueAt(i, inputDevice);
293cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
294cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                if (descriptor.equals(inputDevice.getDescriptor())) {
295cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    return inputDevice;
296cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
297cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
298cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            return null;
299cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
300cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
301cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
302cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    /**
303af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Gets the ids of all input devices in the system.
304af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @return The input device ids.
305af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
306af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public int[] getInputDeviceIds() {
307af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
308af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            populateInputDevicesLocked();
309af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
310af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int count = mInputDevices.size();
311af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int[] ids = new int[count];
312af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < count; i++) {
313af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                ids[i] = mInputDevices.keyAt(i);
314af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
315af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            return ids;
316af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
317af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
318af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
319af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
320af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Registers an input device listener to receive notifications about when
321af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * input devices are added, removed or changed.
322af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
323af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param listener The listener to register.
324af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param handler The handler on which the listener should be invoked, or null
325af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * if the listener should be invoked on the calling thread's looper.
326af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
327af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @see #unregisterInputDeviceListener
328af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
329af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
330af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (listener == null) {
331af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            throw new IllegalArgumentException("listener must not be null");
332af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
333af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
334af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
3359ddb864babab156428d5a001e9b14b1541d964edTim Kilbourn            populateInputDevicesLocked();
336af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int index = findInputDeviceListenerLocked(listener);
337af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (index < 0) {
338af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mInputDeviceListeners.add(new InputDeviceListenerDelegate(listener, handler));
339af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
340af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
341af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
342af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
343af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
344af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Unregisters an input device listener.
345af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
346af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param listener The listener to unregister.
347af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
348af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @see #registerInputDeviceListener
349af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
350af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public void unregisterInputDeviceListener(InputDeviceListener listener) {
351af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (listener == null) {
352af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            throw new IllegalArgumentException("listener must not be null");
353af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
354af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
355af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
356af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int index = findInputDeviceListenerLocked(listener);
357af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (index >= 0) {
3589e6d4b035d4f012d23264d3d2bc946b1ca02dba1Jeff Brown                InputDeviceListenerDelegate d = mInputDeviceListeners.get(index);
3599e6d4b035d4f012d23264d3d2bc946b1ca02dba1Jeff Brown                d.removeCallbacksAndMessages(null);
360af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mInputDeviceListeners.remove(index);
361af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
362af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
363af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
364af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
365af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private int findInputDeviceListenerLocked(InputDeviceListener listener) {
366af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        final int numListeners = mInputDeviceListeners.size();
367af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        for (int i = 0; i < numListeners; i++) {
368af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (mInputDeviceListeners.get(i).mListener == listener) {
369af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                return i;
370af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
371af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
372af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        return -1;
373af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
374af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
375af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
3769209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * Queries whether the device is in tablet mode.
3779209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     *
3789209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * @return The tablet switch state which is one of {@link #SWITCH_STATE_UNKNOWN},
3799209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * {@link #SWITCH_STATE_OFF} or {@link #SWITCH_STATE_ON}.
3809209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * @hide
3819209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     */
3829209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    @SwitchState
3839209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    public int isInTabletMode() {
3849209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright        try {
3859209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright            return mIm.isInTabletMode();
3869209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright        } catch (RemoteException ex) {
387c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
3889209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright        }
3899209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    }
3909209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright
3919209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    /**
39239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * Register a tablet mode changed listener.
39339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     *
39439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * @param listener The listener to register.
39539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * @param handler The handler on which the listener should be invoked, or null
39639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * if the listener should be invoked on the calling thread's looper.
39739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * @hide
39839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     */
39939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    public void registerOnTabletModeChangedListener(
40039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            OnTabletModeChangedListener listener, Handler handler) {
40139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        if (listener == null) {
40239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            throw new IllegalArgumentException("listener must not be null");
40339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
40439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        synchronized (mTabletModeLock) {
40539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            if (mOnTabletModeChangedListeners == null) {
40639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                initializeTabletModeListenerLocked();
40739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
40839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            int idx = findOnTabletModeChangedListenerLocked(listener);
40939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            if (idx < 0) {
41039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                OnTabletModeChangedListenerDelegate d =
41139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    new OnTabletModeChangedListenerDelegate(listener, handler);
41239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                mOnTabletModeChangedListeners.add(d);
41339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
41439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
41539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
41639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
41739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    /**
41839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * Unregister a tablet mode changed listener.
41939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     *
42039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * @param listener The listener to unregister.
42139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * @hide
42239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     */
42339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    public void unregisterOnTabletModeChangedListener(OnTabletModeChangedListener listener) {
42439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        if (listener == null) {
42539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            throw new IllegalArgumentException("listener must not be null");
42639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
42739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        synchronized (mTabletModeLock) {
42839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            int idx = findOnTabletModeChangedListenerLocked(listener);
42939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            if (idx >= 0) {
43039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                OnTabletModeChangedListenerDelegate d = mOnTabletModeChangedListeners.remove(idx);
43139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                d.removeCallbacksAndMessages(null);
43239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
43339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
43439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
43539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
43639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private void initializeTabletModeListenerLocked() {
43739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        final TabletModeChangedListener listener = new TabletModeChangedListener();
43839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        try {
43939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            mIm.registerTabletModeChangedListener(listener);
44039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        } catch (RemoteException ex) {
441c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
44239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
44339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        mTabletModeChangedListener = listener;
44439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        mOnTabletModeChangedListeners = new ArrayList<>();
44539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
44639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
44739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private int findOnTabletModeChangedListenerLocked(OnTabletModeChangedListener listener) {
44839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        final int N = mOnTabletModeChangedListeners.size();
44939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        for (int i = 0; i < N; i++) {
45039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            if (mOnTabletModeChangedListeners.get(i).mListener == listener) {
45139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                return i;
45239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
45339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
45439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        return -1;
45539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
45639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
45739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    /**
4589df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Gets information about all supported keyboard layouts.
4599df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
4609df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The input manager consults the built-in keyboard layouts as well
4619df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * as all keyboard layouts advertised by applications using a
4629df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver.
4639df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
4649df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
4659df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @return A list of all supported keyboard layouts.
4669f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     *
4679df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
4689df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
4699f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public KeyboardLayout[] getKeyboardLayouts() {
4709f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        try {
4719f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return mIm.getKeyboardLayouts();
4729f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
473c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
4749df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
4759df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
4769df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
4779df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
4780748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * Gets information about all supported keyboard layouts appropriate
4790748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * for a specific input device.
4800748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * <p>
4810748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * The input manager consults the built-in keyboard layouts as well
4820748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * as all keyboard layouts advertised by applications using a
4830748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver.
4840748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * </p>
4850748342d2ed264c01384fbaa4446a702a8824813Michael Wright     *
4860748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * @return A list of all supported keyboard layouts for a specific
4870748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * input device.
4880748342d2ed264c01384fbaa4446a702a8824813Michael Wright     *
4890748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * @hide
4900748342d2ed264c01384fbaa4446a702a8824813Michael Wright     */
4910748342d2ed264c01384fbaa4446a702a8824813Michael Wright    public KeyboardLayout[] getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
4920748342d2ed264c01384fbaa4446a702a8824813Michael Wright        try {
4930748342d2ed264c01384fbaa4446a702a8824813Michael Wright            return mIm.getKeyboardLayoutsForInputDevice(identifier);
4940748342d2ed264c01384fbaa4446a702a8824813Michael Wright        } catch (RemoteException ex) {
495c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
4960748342d2ed264c01384fbaa4446a702a8824813Michael Wright        }
4970748342d2ed264c01384fbaa4446a702a8824813Michael Wright    }
4980748342d2ed264c01384fbaa4446a702a8824813Michael Wright
4990748342d2ed264c01384fbaa4446a702a8824813Michael Wright    /**
5009df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Gets the keyboard layout with the specified descriptor.
5019df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
5029df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @param keyboardLayoutDescriptor The keyboard layout descriptor, as returned by
5039df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * {@link KeyboardLayout#getDescriptor()}.
5049df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @return The keyboard layout, or null if it could not be loaded.
5059df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
5069df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
5079df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
5089df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
5099df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        if (keyboardLayoutDescriptor == null) {
5109df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
5119df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
5129df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
5139df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        try {
5149f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return mIm.getKeyboardLayout(keyboardLayoutDescriptor);
5159f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
516c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
5179df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
5189df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
5199df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
5209df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
521fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * Gets the current keyboard layout descriptor for the specified input
522fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * device.
5239df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
524fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param identifier Identifier for the input device
525fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @return The keyboard layout descriptor, or null if no keyboard layout has
526fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     *         been set.
5279df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
5289df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
529fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
5309f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        try {
531fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            return mIm.getCurrentKeyboardLayoutForInputDevice(identifier);
5329f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
533c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
5349f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
5359df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
5369df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
5379df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
538fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * Sets the current keyboard layout descriptor for the specified input
539fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * device.
5409df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
541fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * This method may have the side-effect of causing the input device in
542fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * question to be reconfigured.
5439df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
5449df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
545fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param identifier The identifier for the input device.
546fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param keyboardLayoutDescriptor The keyboard layout descriptor to use,
547fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     *            must not be null.
5489df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
5499df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
550fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
5519df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            String keyboardLayoutDescriptor) {
552fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier == null) {
553fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            throw new IllegalArgumentException("identifier must not be null");
5549df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
555cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (keyboardLayoutDescriptor == null) {
556cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
557cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
558cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
559cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        try {
560fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            mIm.setCurrentKeyboardLayoutForInputDevice(identifier,
561cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    keyboardLayoutDescriptor);
562cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        } catch (RemoteException ex) {
563c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
564cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
565cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
566cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
567cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    /**
568fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * Gets all keyboard layout descriptors that are enabled for the specified
569fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * input device.
570cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     *
571fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param identifier The identifier for the input device.
572cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @return The keyboard layout descriptors.
573cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @hide
574cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     */
5750748342d2ed264c01384fbaa4446a702a8824813Michael Wright    public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
576fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier == null) {
577cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
578cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
579cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
580cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        try {
5810748342d2ed264c01384fbaa4446a702a8824813Michael Wright            return mIm.getEnabledKeyboardLayoutsForInputDevice(identifier);
582cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        } catch (RemoteException ex) {
583c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
584cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
585cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
586cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
587cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    /**
588cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * Adds the keyboard layout descriptor for the specified input device.
589cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * <p>
590fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * This method may have the side-effect of causing the input device in
591fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * question to be reconfigured.
592cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * </p>
593cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     *
594fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param identifier The identifier for the input device.
595fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param keyboardLayoutDescriptor The descriptor of the keyboard layout to
596fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     *            add.
597cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @hide
598cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     */
599fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
600cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            String keyboardLayoutDescriptor) {
601fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier == null) {
602cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
603cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
604cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (keyboardLayoutDescriptor == null) {
605cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
606cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
607cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
608cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        try {
609fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            mIm.addKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
610cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        } catch (RemoteException ex) {
611c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
612cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
613cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
614cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
615cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    /**
616cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * Removes the keyboard layout descriptor for the specified input device.
617cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * <p>
618fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * This method may have the side-effect of causing the input device in
619fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * question to be reconfigured.
620cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * </p>
621cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     *
622fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param identifier The identifier for the input device.
623fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param keyboardLayoutDescriptor The descriptor of the keyboard layout to
624fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     *            remove.
625cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @hide
626cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     */
627fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
628cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            String keyboardLayoutDescriptor) {
629fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier == null) {
630cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
631cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
632cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (keyboardLayoutDescriptor == null) {
633cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
634cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
6359df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
6369df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        try {
637fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            mIm.removeKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
6389f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
639c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
6409df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
6419df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
6429df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
643d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
644d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    /**
645d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * Gets the keyboard layout for the specified input device and IME subtype.
646d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     *
647d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @param identifier The identifier for the input device.
648d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @param inputMethodInfo The input method.
649d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @param inputMethodSubtype The input method subtype.
650d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     *
651d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @return The associated {@link KeyboardLayout}, or null if one has not been set.
652d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     *
653d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @hide
654d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     */
655d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    public KeyboardLayout getKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
656d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            InputMethodInfo inputMethodInfo, InputMethodSubtype inputMethodSubtype) {
657d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        try {
658d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            return mIm.getKeyboardLayoutForInputDevice(
659d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    identifier, inputMethodInfo, inputMethodSubtype);
660d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        } catch (RemoteException ex) {
661c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
662d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
663d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    }
664d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
665d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    /**
666d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * Sets the keyboard layout for the specified input device and IME subtype pair.
667d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     *
668d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @param identifier The identifier for the input device.
669d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @param inputMethodInfo The input method with which to associate the keyboard layout.
670d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @param inputMethodSubtype The input method subtype which which to associate the keyboard
671d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     *                           layout.
672d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @param keyboardLayoutDescriptor The descriptor of the keyboard layout to set
673d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     *
674d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @hide
675d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     */
676d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
677d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            InputMethodInfo inputMethodInfo, InputMethodSubtype inputMethodSubtype,
678d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            String keyboardLayoutDescriptor) {
679d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        try {
680d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            mIm.setKeyboardLayoutForInputDevice(identifier, inputMethodInfo,
681d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    inputMethodSubtype, keyboardLayoutDescriptor);
682d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        } catch (RemoteException ex) {
683c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
684d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
685d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    }
686d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
687ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
688d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * Gets the TouchCalibration applied to the specified input device's coordinates.
689d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     *
690d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * @param inputDeviceDescriptor The input device descriptor.
691d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * @return The TouchCalibration currently assigned for use with the given
692d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * input device. If none is set, an identity TouchCalibration is returned.
693d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     *
694d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * @hide
695d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     */
696d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke    public TouchCalibration getTouchCalibration(String inputDeviceDescriptor, int surfaceRotation) {
697d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        try {
698d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke            return mIm.getTouchCalibrationForInputDevice(inputDeviceDescriptor, surfaceRotation);
699d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        } catch (RemoteException ex) {
700c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
701d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
702d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke    }
703d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke
704d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke    /**
705d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * Sets the TouchCalibration to apply to the specified input device's coordinates.
706d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * <p>
707d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * This method may have the side-effect of causing the input device in question
708d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * to be reconfigured. Requires {@link android.Manifest.permissions.SET_INPUT_CALIBRATION}.
709d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * </p>
710d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     *
711d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * @param inputDeviceDescriptor The input device descriptor.
712d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * @param calibration The calibration to be applied
713d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     *
714d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * @hide
715d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     */
716d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke    public void setTouchCalibration(String inputDeviceDescriptor, int surfaceRotation,
717d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke            TouchCalibration calibration) {
718d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        try {
719d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke            mIm.setTouchCalibrationForInputDevice(inputDeviceDescriptor, surfaceRotation, calibration);
720d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        } catch (RemoteException ex) {
721c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
722d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
723d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke    }
724d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke
725d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke    /**
726ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Gets the mouse pointer speed.
727ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
728ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Only returns the permanent mouse pointer speed.  Ignores any temporary pointer
729ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * speed set by {@link #tryPointerSpeed}.
730ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
731ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
7329f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @param context The application context.
733ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @return The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
734ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
735ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
736ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
737ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
7389f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public int getPointerSpeed(Context context) {
739ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        int speed = DEFAULT_POINTER_SPEED;
740ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
7419f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            speed = Settings.System.getInt(context.getContentResolver(),
742ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                    Settings.System.POINTER_SPEED);
743ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (SettingNotFoundException snfe) {
744ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
745ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        return speed;
746ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
747ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
748ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
749ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Sets the mouse pointer speed.
750ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
751ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Requires {@link android.Manifest.permissions.WRITE_SETTINGS}.
752ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
753ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
7549f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @param context The application context.
755ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
756ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
757ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
758ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
759ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
7609f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public void setPointerSpeed(Context context, int speed) {
761ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
762ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("speed out of range");
763ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
764ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
7659f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        Settings.System.putInt(context.getContentResolver(),
766ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                Settings.System.POINTER_SPEED, speed);
767ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
768ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
769ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
770ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Changes the mouse pointer speed temporarily, but does not save the setting.
771ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
772ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Requires {@link android.Manifest.permission.SET_POINTER_SPEED}.
773ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
774ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
775ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
776ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
777ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
778ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
779ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
780ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public void tryPointerSpeed(int speed) {
781ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
782ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("speed out of range");
783ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
784ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
785ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
7869f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            mIm.tryPointerSpeed(speed);
787ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (RemoteException ex) {
788c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
789ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
790ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
791ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
792ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
793ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Queries the framework about whether any physical keys exist on the
794ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * any keyboard attached to the device that are capable of producing the given
795ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * array of key codes.
796ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
797ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param keyCodes The array of key codes to query.
798ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @return A new array of the same size as the key codes array whose elements
799ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * are set to true if at least one attached keyboard supports the corresponding key code
800ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * at the same index in the key codes array.
801ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
802ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
803ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
8049f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public boolean[] deviceHasKeys(int[] keyCodes) {
805b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright        return deviceHasKeys(-1, keyCodes);
806b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright    }
807b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright
808b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright    /**
809b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * Queries the framework about whether any physical keys exist on the
810b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * any keyboard attached to the device that are capable of producing the given
811b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * array of key codes.
812b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     *
813b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * @param id The id of the device to query.
814b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * @param keyCodes The array of key codes to query.
815b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * @return A new array of the same size as the key codes array whose elements are set to true
816b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * if the given device could produce the corresponding key code at the same index in the key
817b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * codes array.
818b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     *
819b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * @hide
820b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     */
821b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright    public boolean[] deviceHasKeys(int id, int[] keyCodes) {
822ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        boolean[] ret = new boolean[keyCodes.length];
823ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
824b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright            mIm.hasKeys(id, InputDevice.SOURCE_ANY, keyCodes, ret);
825ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (RemoteException e) {
826c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
827ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
828ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        return ret;
829ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
830ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
831b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright
832ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
833ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Injects an input event into the event system on behalf of an application.
834ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * The synchronization mode determines whether the method blocks while waiting for
835ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * input injection to proceed.
836ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
837ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Requires {@link android.Manifest.permission.INJECT_EVENTS} to inject into
838ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * windows that are owned by other applications.
839ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p><p>
840ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Make sure you correctly set the event time and input source of the event
841ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * before calling this method.
842ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
843ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
844ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param event The event to inject.
845ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param mode The synchronization mode.  One of:
846ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #INJECT_INPUT_EVENT_MODE_ASYNC},
847ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT}, or
848ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH}.
849ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @return True if input event injection succeeded.
850ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
851ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
852ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
8539f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public boolean injectInputEvent(InputEvent event, int mode) {
854ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (event == null) {
855ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("event must not be null");
856ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
857ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (mode != INJECT_INPUT_EVENT_MODE_ASYNC
858ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                && mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
859ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                && mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
860ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("mode is invalid");
861ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
862ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
863ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
8649f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return mIm.injectInputEvent(event, mode);
865ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (RemoteException ex) {
866c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
867ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
868ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
869af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
8701db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai    /**
8711db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai     * Changes the mouse pointer's icon shape into the specified id.
8721db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai     *
8731db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai     * @param iconId The id of the pointer graphic, as a value between
8741db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai     * {@link PointerIcon.STYLE_ARROW} and {@link PointerIcon.STYLE_GRABBING}.
8751db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai     *
8761db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai     * @hide
8771db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai     */
8781db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai    public void setPointerIconShape(int iconId) {
8791db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai        try {
8801db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai            mIm.setPointerIconShape(iconId);
8811db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai        } catch (RemoteException ex) {
882c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
8831db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai        }
8841db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai    }
8851db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai
886d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    /** @hide */
887d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    public void setCustomPointerIcon(PointerIcon icon) {
888d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai        try {
889d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai            mIm.setCustomPointerIcon(icon);
890d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai        } catch (RemoteException ex) {
891c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
892d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai        }
893d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    }
894d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai
895347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai    /**
896347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai     * Update the pointer icon status. When detached, the pointer icon disappears, and further
897347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai     * mouse location will be stuck at the current point. Mouse movement events will still arrive,
898347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai     * and movement should be handled through {@link MotionEvent.AXIS_RELATIVE_X} and
899347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai     * {@link MotionEvent.AXIS_RELATIVE_Y}.
900347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai     *
901347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai     * @param detached true if the icon will be detached from the actual mouse movement.
902347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai     *
903347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai     * @hide
904347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai     */
905347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai    public void setPointerIconDetached(boolean detached) {
906347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai        try {
907347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai            mIm.setPointerIconDetached(detached);
908347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai        } catch (RemoteException ex) {
909c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
910347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai        }
911347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai    }
912347e5d498f4c216d588e98776a386d8bdf93d05cJun Mukai
913af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void populateInputDevicesLocked() {
914af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (mInputDevicesChangedListener == null) {
915af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final InputDevicesChangedListener listener = new InputDevicesChangedListener();
916af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            try {
917af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mIm.registerInputDevicesChangedListener(listener);
918af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            } catch (RemoteException ex) {
919c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw ex.rethrowFromSystemServer();
920af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
921af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mInputDevicesChangedListener = listener;
922af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
923af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
924af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (mInputDevices == null) {
925af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int[] ids;
926af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            try {
927af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                ids = mIm.getInputDeviceIds();
928af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            } catch (RemoteException ex) {
929c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw ex.rethrowFromSystemServer();
930af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
931af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
932af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mInputDevices = new SparseArray<InputDevice>();
933af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < ids.length; i++) {
934af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mInputDevices.put(ids[i], null);
935af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
936af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
937af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
938af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
939af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void onInputDevicesChanged(int[] deviceIdAndGeneration) {
940af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (DEBUG) {
941af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            Log.d(TAG, "Received input devices changed.");
942af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
943af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
944af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
945af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = mInputDevices.size(); --i > 0; ) {
946af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                final int deviceId = mInputDevices.keyAt(i);
947af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                if (!containsDeviceId(deviceIdAndGeneration, deviceId)) {
948af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    if (DEBUG) {
949af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        Log.d(TAG, "Device removed: " + deviceId);
950af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    }
951af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mInputDevices.removeAt(i);
952af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    sendMessageToInputDeviceListenersLocked(MSG_DEVICE_REMOVED, deviceId);
953af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                }
954af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
955af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
956af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
957af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                final int deviceId = deviceIdAndGeneration[i];
958af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                int index = mInputDevices.indexOfKey(deviceId);
959af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                if (index >= 0) {
960af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    final InputDevice device = mInputDevices.valueAt(index);
961af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    if (device != null) {
962af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        final int generation = deviceIdAndGeneration[i + 1];
963af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        if (device.getGeneration() != generation) {
964af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            if (DEBUG) {
965af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                                Log.d(TAG, "Device changed: " + deviceId);
966af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            }
967af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            mInputDevices.setValueAt(index, null);
968af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            sendMessageToInputDeviceListenersLocked(MSG_DEVICE_CHANGED, deviceId);
969af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        }
970af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    }
971af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                } else {
972af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    if (DEBUG) {
973af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        Log.d(TAG, "Device added: " + deviceId);
974af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    }
975af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mInputDevices.put(deviceId, null);
976af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    sendMessageToInputDeviceListenersLocked(MSG_DEVICE_ADDED, deviceId);
977af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                }
978af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
979af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
980af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
981af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
982af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void sendMessageToInputDeviceListenersLocked(int what, int deviceId) {
983af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        final int numListeners = mInputDeviceListeners.size();
984af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        for (int i = 0; i < numListeners; i++) {
985af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            InputDeviceListenerDelegate listener = mInputDeviceListeners.get(i);
986af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            listener.sendMessage(listener.obtainMessage(what, deviceId, 0));
987af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
988af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
989af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
990af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static boolean containsDeviceId(int[] deviceIdAndGeneration, int deviceId) {
991af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
992af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (deviceIdAndGeneration[i] == deviceId) {
993af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                return true;
994af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
995af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
996af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        return false;
997af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
998af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
99939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
100039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private void onTabletModeChanged(long whenNanos, boolean inTabletMode) {
100139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        if (DEBUG) {
100239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            Log.d(TAG, "Received tablet mode changed: "
100339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    + "whenNanos=" + whenNanos + ", inTabletMode=" + inTabletMode);
100439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
100539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        synchronized (mTabletModeLock) {
100639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            final int N = mOnTabletModeChangedListeners.size();
100739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            for (int i = 0; i < N; i++) {
100839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                OnTabletModeChangedListenerDelegate listener =
100939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                        mOnTabletModeChangedListeners.get(i);
101039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                listener.sendTabletModeChanged(whenNanos, inTabletMode);
101139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
101239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
101339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
101439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
1015af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
1016a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     * Gets a vibrator service associated with an input device, assuming it has one.
1017a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     * @return The vibrator, never null.
1018a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     * @hide
1019a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     */
1020a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    public Vibrator getInputDeviceVibrator(int deviceId) {
1021a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        return new InputDeviceVibrator(deviceId);
1022a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
1023a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1024a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    /**
1025af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Listens for changes in input devices.
1026af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
1027af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public interface InputDeviceListener {
1028af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        /**
1029af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Called whenever an input device has been added to the system.
1030af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Use {@link InputManager#getInputDevice} to get more information about the device.
1031af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         *
1032af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * @param deviceId The id of the input device that was added.
1033af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         */
1034af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        void onInputDeviceAdded(int deviceId);
1035af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1036af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        /**
1037af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Called whenever an input device has been removed from the system.
1038af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         *
1039af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * @param deviceId The id of the input device that was removed.
1040af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         */
1041af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        void onInputDeviceRemoved(int deviceId);
1042af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1043af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        /**
1044af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Called whenever the properties of an input device have changed since they
1045af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * were last queried.  Use {@link InputManager#getInputDevice} to get
1046af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * a fresh {@link InputDevice} object with the new properties.
1047af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         *
1048af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * @param deviceId The id of the input device that changed.
1049af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         */
1050af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        void onInputDeviceChanged(int deviceId);
1051af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
1052af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1053af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final class InputDevicesChangedListener extends IInputDevicesChangedListener.Stub {
1054af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        @Override
1055af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public void onInputDevicesChanged(int[] deviceIdAndGeneration) throws RemoteException {
1056af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            InputManager.this.onInputDevicesChanged(deviceIdAndGeneration);
1057af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
1058af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
1059af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1060af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final class InputDeviceListenerDelegate extends Handler {
1061af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public final InputDeviceListener mListener;
1062af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1063af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public InputDeviceListenerDelegate(InputDeviceListener listener, Handler handler) {
1064af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            super(handler != null ? handler.getLooper() : Looper.myLooper());
1065af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mListener = listener;
1066af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
1067af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1068af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        @Override
1069af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public void handleMessage(Message msg) {
1070af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            switch (msg.what) {
1071af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                case MSG_DEVICE_ADDED:
1072af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mListener.onInputDeviceAdded(msg.arg1);
1073af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    break;
1074af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                case MSG_DEVICE_REMOVED:
1075af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mListener.onInputDeviceRemoved(msg.arg1);
1076af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    break;
1077af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                case MSG_DEVICE_CHANGED:
1078af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mListener.onInputDeviceChanged(msg.arg1);
1079af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    break;
1080af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
1081af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
1082af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
1083a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
108439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    /** @hide */
108539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    public interface OnTabletModeChangedListener {
108639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        /**
108739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright         * Called whenever the device goes into or comes out of tablet mode.
108839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright         *
108939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright         * @param whenNanos The time at which the device transitioned into or
109039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright         * out of tablet mode. This is given in nanoseconds in the
109139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright         * {@link SystemClock#uptimeMillis} time base.
109239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright         */
109339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        void onTabletModeChanged(long whenNanos, boolean inTabletMode);
109439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
109539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
109639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private final class TabletModeChangedListener extends ITabletModeChangedListener.Stub {
109739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        @Override
109839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        public void onTabletModeChanged(long whenNanos, boolean inTabletMode) {
109939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            InputManager.this.onTabletModeChanged(whenNanos, inTabletMode);
110039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
110139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
110239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
110339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private static final class OnTabletModeChangedListenerDelegate extends Handler {
110439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        private static final int MSG_TABLET_MODE_CHANGED = 0;
110539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
110639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        public final OnTabletModeChangedListener mListener;
110739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
110839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        public OnTabletModeChangedListenerDelegate(
110939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                OnTabletModeChangedListener listener, Handler handler) {
111039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            super(handler != null ? handler.getLooper() : Looper.myLooper());
111139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            mListener = listener;
111239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
111339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
111439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        public void sendTabletModeChanged(long whenNanos, boolean inTabletMode) {
111539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            SomeArgs args = SomeArgs.obtain();
111639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            args.argi1 = (int) (whenNanos & 0xFFFFFFFF);
111739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            args.argi2 = (int) (whenNanos >> 32);
111839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            args.arg1 = (Boolean) inTabletMode;
111939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            obtainMessage(MSG_TABLET_MODE_CHANGED, args).sendToTarget();
112039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
112139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
112239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        @Override
112339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        public void handleMessage(Message msg) {
112439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            switch (msg.what) {
112539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                case MSG_TABLET_MODE_CHANGED:
112639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    SomeArgs args = (SomeArgs) msg.obj;
112739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    long whenNanos = (args.argi1 & 0xFFFFFFFFl) | ((long) args.argi2 << 32);
112839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    boolean inTabletMode = (boolean) args.arg1;
112939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    mListener.onTabletModeChanged(whenNanos, inTabletMode);
113039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    break;
113139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
113239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
113339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
113439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
1135a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    private final class InputDeviceVibrator extends Vibrator {
1136a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        private final int mDeviceId;
1137a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        private final Binder mToken;
1138a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1139a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public InputDeviceVibrator(int deviceId) {
1140a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mDeviceId = deviceId;
1141a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mToken = new Binder();
1142a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1143a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1144a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
1145a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public boolean hasVibrator() {
1146a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            return true;
1147a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1148a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
11491af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        /**
11501af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock         * @hide
11511af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock         */
1152a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
11537b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock        public void vibrate(int uid, String opPkg, long milliseconds, AudioAttributes attributes) {
1154a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            vibrate(new long[] { 0, milliseconds}, -1);
1155a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1156a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
11571af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        /**
11581af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock         * @hide
11591af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock         */
1160a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
11618fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer        public void vibrate(int uid, String opPkg, long[] pattern, int repeat,
11627b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                AudioAttributes attributes) {
1163a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            if (repeat >= pattern.length) {
1164a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                throw new ArrayIndexOutOfBoundsException();
1165a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
1166a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            try {
1167a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                mIm.vibrate(mDeviceId, pattern, repeat, mToken);
1168a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            } catch (RemoteException ex) {
1169c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw ex.rethrowFromSystemServer();
1170a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
1171a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1172a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1173a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
1174a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public void cancel() {
1175a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            try {
1176a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                mIm.cancelVibrate(mDeviceId, mToken);
1177a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            } catch (RemoteException ex) {
1178c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw ex.rethrowFromSystemServer();
1179a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
1180a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1181a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
11829df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown}
1183