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
1939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wrightimport com.android.internal.os.SomeArgs;
20cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
219209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wrightimport android.annotation.IntDef;
2246ac35d09b0a1ba7af7eb4c14293a7978edcd2abYohei Yukawaimport android.annotation.Nullable;
239df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.annotation.SdkConstant;
249df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.annotation.SdkConstant.SdkConstantType;
259df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.content.Context;
267b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlockimport android.media.AudioAttributes;
27a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brownimport android.os.Binder;
28af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.Handler;
29ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.IBinder;
30af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.Looper;
31af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport android.os.Message;
32ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.RemoteException;
33ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.os.ServiceManager;
3439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wrightimport android.os.SystemClock;
35a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brownimport android.os.Vibrator;
36ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.provider.Settings;
37ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.provider.Settings.SettingNotFoundException;
389df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownimport android.util.Log;
399f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brownimport android.util.SparseArray;
40ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.view.InputDevice;
41ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brownimport android.view.InputEvent;
42d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wrightimport android.view.PointerIcon;
43d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wrightimport android.view.inputmethod.InputMethodInfo;
44d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wrightimport android.view.inputmethod.InputMethodSubtype;
459df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
469209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wrightimport java.lang.annotation.Retention;
479209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wrightimport java.lang.annotation.RetentionPolicy;
48af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brownimport java.util.ArrayList;
4939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wrightimport java.util.List;
50af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
519df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown/**
529df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Provides information about input devices and available key layouts.
539df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * <p>
549df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Get an instance of this class by calling
559df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * {@link android.content.Context#getSystemService(java.lang.String)
569df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * Context.getSystemService()} with the argument
579df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * {@link android.content.Context#INPUT_SERVICE}.
589df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown * </p>
599df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown */
609df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brownpublic final class InputManager {
619df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    private static final String TAG = "InputManager";
62af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final boolean DEBUG = false;
63af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
64af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final int MSG_DEVICE_ADDED = 1;
65af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final int MSG_DEVICE_REMOVED = 2;
66af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final int MSG_DEVICE_CHANGED = 3;
679df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
689f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    private static InputManager sInstance;
699df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
709f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    private final IInputManager mIm;
71af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
72af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    // Guarded by mInputDevicesLock
73af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final Object mInputDevicesLock = new Object();
74af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private SparseArray<InputDevice> mInputDevices;
75af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private InputDevicesChangedListener mInputDevicesChangedListener;
76af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners =
77af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            new ArrayList<InputDeviceListenerDelegate>();
789df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
7939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    // Guarded by mTabletModeLock
8039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private final Object mTabletModeLock = new Object();
8139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private TabletModeChangedListener mTabletModeChangedListener;
8239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private List<OnTabletModeChangedListenerDelegate> mOnTabletModeChangedListeners;
8339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
849df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
859df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Broadcast Action: Query available keyboard layouts.
869df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
879df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The input manager service locates available keyboard layouts
889df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * by querying broadcast receivers that are registered for this action.
899df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * An application can offer additional keyboard layouts to the user
909df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * by declaring a suitable broadcast receiver in its manifest.
919df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p><p>
929df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Here is an example broadcast receiver declaration that an application
939df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * might include in its AndroidManifest.xml to advertise keyboard layouts.
949df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The meta-data specifies a resource that contains a description of each keyboard
959df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * layout that is provided by the application.
969df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <pre><code>
97d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown     * &lt;receiver android:name=".InputDeviceReceiver"
98d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown     *         android:label="@string/keyboard_layouts_label">
999df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;intent-filter>
1009df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *         &lt;action android:name="android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS" />
1019df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;/intent-filter>
1029df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;meta-data android:name="android.hardware.input.metadata.KEYBOARD_LAYOUTS"
1039df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *             android:resource="@xml/keyboard_layouts" />
1049df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;/receiver>
1059df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </code></pre>
1069df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p><p>
1079df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * In the above example, the <code>@xml/keyboard_layouts</code> resource refers to
1089df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * an XML resource whose root element is <code>&lt;keyboard-layouts></code> that
1099df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * contains zero or more <code>&lt;keyboard-layout></code> elements.
1109df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Each <code>&lt;keyboard-layout></code> element specifies the name, label, and location
111d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown     * of a key character map for a particular keyboard layout.  The label on the receiver
112d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown     * is used to name the collection of keyboard layouts provided by this receiver in the
113d9fec5d317c09da6bcc7a54df4e0190a76d21eaeJeff Brown     * keyboard layout settings.
114112449ca2983898b14e5e4dfe5d9d50b66f803a5Michael Wright     * <pre><code>
1159df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;?xml version="1.0" encoding="utf-8"?>
1169df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;keyboard-layouts xmlns:android="http://schemas.android.com/apk/res/android">
1179df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *     &lt;keyboard-layout android:name="keyboard_layout_english_us"
1189df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *             android:label="@string/keyboard_layout_english_us_label"
1192f0957607411b99810226ad38d59cf18718b86d0Jeff Brown     *             android:keyboardLayout="@raw/keyboard_layout_english_us" />
1209df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * &lt;/keyboard-layouts>
121112449ca2983898b14e5e4dfe5d9d50b66f803a5Michael Wright     * </pre></code>
1229df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p><p>
1239df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The <code>android:name</code> attribute specifies an identifier by which
1249df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * the keyboard layout will be known in the package.
125682c24e22811d4ee17ae1cd61bf255c3f7e722b7Trevor Johns     * The <code>android:label</code> attribute specifies a human-readable descriptive
1269df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * label to describe the keyboard layout in the user interface, such as "English (US)".
1272f0957607411b99810226ad38d59cf18718b86d0Jeff Brown     * The <code>android:keyboardLayout</code> attribute refers to a
1289df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <a href="http://source.android.com/tech/input/key-character-map-files.html">
1299df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * key character map</a> resource that defines the keyboard layout.
1309df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
1319df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
1329df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
1339df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    public static final String ACTION_QUERY_KEYBOARD_LAYOUTS =
1349df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            "android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS";
1359df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
1369df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
1379df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Metadata Key: Keyboard layout metadata associated with
1389df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS}.
1399df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
1409df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Specifies the resource id of a XML resource that describes the keyboard
1419df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * layouts that are provided by the application.
1429df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
1439df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
1449df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    public static final String META_DATA_KEYBOARD_LAYOUTS =
1459df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            "android.hardware.input.metadata.KEYBOARD_LAYOUTS";
1469df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
147ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
148ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Pointer Speed: The minimum (slowest) pointer speed (-7).
149ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
150ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
151ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int MIN_POINTER_SPEED = -7;
152ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
153ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
154ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Pointer Speed: The maximum (fastest) pointer speed (7).
155ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
156ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
157ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int MAX_POINTER_SPEED = 7;
158ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
159ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
160ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Pointer Speed: The default pointer speed (0).
161ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
162ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
163ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int DEFAULT_POINTER_SPEED = 0;
164ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
165ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
166ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Input Event Injection Synchronization Mode: None.
167ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Never blocks.  Injection is asynchronous and is assumed always to be successful.
168ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
169ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
170ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int INJECT_INPUT_EVENT_MODE_ASYNC = 0; // see InputDispatcher.h
171ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
172ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
173ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Input Event Injection Synchronization Mode: Wait for result.
174ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Waits for previous events to be dispatched so that the input dispatcher can
175ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * determine whether input event injection will be permitted based on the current
176ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * input focus.  Does not wait for the input event to finish being handled
177ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * by the application.
178ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
179ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
180ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1;  // see InputDispatcher.h
181ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
182ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
183ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Input Event Injection Synchronization Mode: Wait for finish.
184ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Waits for the event to be delivered to the application and handled.
185ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
186ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
187ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2;  // see InputDispatcher.h
188ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
1899209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    /** @hide */
1909209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    @Retention(RetentionPolicy.SOURCE)
1919209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    @IntDef({SWITCH_STATE_UNKNOWN, SWITCH_STATE_OFF, SWITCH_STATE_ON})
1929209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    public @interface SwitchState {}
1939209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright
1949209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    /**
1959209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * Switch State: Unknown.
1969209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     *
1979209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * The system has yet to report a valid value for the switch.
1989209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * @hide
1999209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     */
2009209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    public static final int SWITCH_STATE_UNKNOWN = -1;
2019209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright
2029209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    /**
2039209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * Switch State: Off.
2049209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * @hide
2059209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     */
2069209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    public static final int SWITCH_STATE_OFF = 0;
2079209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright
2089209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    /**
2099209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * Switch State: On.
2109209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * @hide
2119209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     */
2129209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    public static final int SWITCH_STATE_ON = 1;
2139209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright
2149f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    private InputManager(IInputManager im) {
2159f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        mIm = im;
216ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
217ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
2189f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    /**
2199f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * Gets an instance of the input manager.
2209f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     *
2219f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @return The input manager instance.
2229f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     *
2239f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @hide
2249f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     */
2259f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public static InputManager getInstance() {
2269f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        synchronized (InputManager.class) {
2279f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            if (sInstance == null) {
2289f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                IBinder b = ServiceManager.getService(Context.INPUT_SERVICE);
2299f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown                sInstance = new InputManager(IInputManager.Stub.asInterface(b));
2309f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            }
2319f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return sInstance;
2329f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
2339df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
2349df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
2359df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
236af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Gets information about the input device with the specified id.
237af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param id The device id.
238af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @return The input device or null if not found.
239af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
240af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public InputDevice getInputDevice(int id) {
241af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
242af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            populateInputDevicesLocked();
243af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
244af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int index = mInputDevices.indexOfKey(id);
245af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (index < 0) {
246af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                return null;
247af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
248af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
249af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            InputDevice inputDevice = mInputDevices.valueAt(index);
250af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (inputDevice == null) {
251af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                try {
252af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    inputDevice = mIm.getInputDevice(id);
253af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                } catch (RemoteException ex) {
254c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                    throw ex.rethrowFromSystemServer();
255af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                }
2568f124842dd16125062f048257889c85380879b68Jeff Brown                if (inputDevice != null) {
2578f124842dd16125062f048257889c85380879b68Jeff Brown                    mInputDevices.setValueAt(index, inputDevice);
2588f124842dd16125062f048257889c85380879b68Jeff Brown                }
259af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
260af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            return inputDevice;
261af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
262af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
263af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
264af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
265cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * Gets information about the input device with the specified descriptor.
266cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @param descriptor The input device descriptor.
267cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @return The input device or null if not found.
268cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @hide
269cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     */
270cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    public InputDevice getInputDeviceByDescriptor(String descriptor) {
271cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (descriptor == null) {
272cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("descriptor must not be null.");
273cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
274cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
275cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        synchronized (mInputDevicesLock) {
276cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            populateInputDevicesLocked();
277cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
278cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            int numDevices = mInputDevices.size();
279cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            for (int i = 0; i < numDevices; i++) {
280cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                InputDevice inputDevice = mInputDevices.valueAt(i);
281cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                if (inputDevice == null) {
282cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    int id = mInputDevices.keyAt(i);
283cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    try {
284cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        inputDevice = mIm.getInputDevice(id);
285cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    } catch (RemoteException ex) {
286c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                        throw ex.rethrowFromSystemServer();
2878f124842dd16125062f048257889c85380879b68Jeff Brown                    }
2888f124842dd16125062f048257889c85380879b68Jeff Brown                    if (inputDevice == null) {
289cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                        continue;
290cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    }
291cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    mInputDevices.setValueAt(i, inputDevice);
292cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
293cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                if (descriptor.equals(inputDevice.getDescriptor())) {
294cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    return inputDevice;
295cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                }
296cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            }
297cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            return null;
298cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
299cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
300cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
301cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    /**
302af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Gets the ids of all input devices in the system.
303af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @return The input device ids.
304af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
305af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public int[] getInputDeviceIds() {
306af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
307af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            populateInputDevicesLocked();
308af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
309af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int count = mInputDevices.size();
310af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int[] ids = new int[count];
311af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < count; i++) {
312af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                ids[i] = mInputDevices.keyAt(i);
313af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
314af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            return ids;
315af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
316af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
317af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
318af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
319af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Registers an input device listener to receive notifications about when
320af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * input devices are added, removed or changed.
321af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
322af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param listener The listener to register.
323af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param handler The handler on which the listener should be invoked, or null
324af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * if the listener should be invoked on the calling thread's looper.
325af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
326af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @see #unregisterInputDeviceListener
327af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
328af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public void registerInputDeviceListener(InputDeviceListener listener, Handler handler) {
329af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (listener == null) {
330af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            throw new IllegalArgumentException("listener must not be null");
331af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
332af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
333af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
3349ddb864babab156428d5a001e9b14b1541d964edTim Kilbourn            populateInputDevicesLocked();
335af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int index = findInputDeviceListenerLocked(listener);
336af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (index < 0) {
337af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mInputDeviceListeners.add(new InputDeviceListenerDelegate(listener, handler));
338af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
339af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
340af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
341af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
342af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
343af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Unregisters an input device listener.
344af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
345af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @param listener The listener to unregister.
346af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     *
347af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * @see #registerInputDeviceListener
348af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
349af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public void unregisterInputDeviceListener(InputDeviceListener listener) {
350af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (listener == null) {
351af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            throw new IllegalArgumentException("listener must not be null");
352af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
353af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
354af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
355af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            int index = findInputDeviceListenerLocked(listener);
356af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (index >= 0) {
3579e6d4b035d4f012d23264d3d2bc946b1ca02dba1Jeff Brown                InputDeviceListenerDelegate d = mInputDeviceListeners.get(index);
3589e6d4b035d4f012d23264d3d2bc946b1ca02dba1Jeff Brown                d.removeCallbacksAndMessages(null);
359af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mInputDeviceListeners.remove(index);
360af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
361af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
362af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
363af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
364af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private int findInputDeviceListenerLocked(InputDeviceListener listener) {
365af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        final int numListeners = mInputDeviceListeners.size();
366af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        for (int i = 0; i < numListeners; i++) {
367af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (mInputDeviceListeners.get(i).mListener == listener) {
368af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                return i;
369af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
370af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
371af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        return -1;
372af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
373af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
374af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
3759209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * Queries whether the device is in tablet mode.
3769209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     *
3779209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * @return The tablet switch state which is one of {@link #SWITCH_STATE_UNKNOWN},
3789209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * {@link #SWITCH_STATE_OFF} or {@link #SWITCH_STATE_ON}.
3799209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     * @hide
3809209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright     */
3819209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    @SwitchState
3829209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    public int isInTabletMode() {
3839209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright        try {
3849209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright            return mIm.isInTabletMode();
3859209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright        } catch (RemoteException ex) {
386c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
3879209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright        }
3889209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    }
3899209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright
3909209c9cd9a6f779d0d9d86f9b2e368df564fa6bbMichael Wright    /**
39139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * Register a tablet mode changed listener.
39239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     *
39339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * @param listener The listener to register.
39439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * @param handler The handler on which the listener should be invoked, or null
39539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * if the listener should be invoked on the calling thread's looper.
39639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * @hide
39739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     */
39839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    public void registerOnTabletModeChangedListener(
39939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            OnTabletModeChangedListener listener, Handler handler) {
40039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        if (listener == null) {
40139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            throw new IllegalArgumentException("listener must not be null");
40239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
40339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        synchronized (mTabletModeLock) {
40439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            if (mOnTabletModeChangedListeners == null) {
40539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                initializeTabletModeListenerLocked();
40639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
40739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            int idx = findOnTabletModeChangedListenerLocked(listener);
40839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            if (idx < 0) {
40939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                OnTabletModeChangedListenerDelegate d =
41039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    new OnTabletModeChangedListenerDelegate(listener, handler);
41139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                mOnTabletModeChangedListeners.add(d);
41239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
41339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
41439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
41539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
41639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    /**
41739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * Unregister a tablet mode changed listener.
41839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     *
41939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * @param listener The listener to unregister.
42039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     * @hide
42139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright     */
42239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    public void unregisterOnTabletModeChangedListener(OnTabletModeChangedListener listener) {
42339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        if (listener == null) {
42439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            throw new IllegalArgumentException("listener must not be null");
42539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
42639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        synchronized (mTabletModeLock) {
42739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            int idx = findOnTabletModeChangedListenerLocked(listener);
42839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            if (idx >= 0) {
42939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                OnTabletModeChangedListenerDelegate d = mOnTabletModeChangedListeners.remove(idx);
43039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                d.removeCallbacksAndMessages(null);
43139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
43239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
43339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
43439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
43539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private void initializeTabletModeListenerLocked() {
43639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        final TabletModeChangedListener listener = new TabletModeChangedListener();
43739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        try {
43839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            mIm.registerTabletModeChangedListener(listener);
43939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        } catch (RemoteException ex) {
440c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
44139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
44239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        mTabletModeChangedListener = listener;
44339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        mOnTabletModeChangedListeners = new ArrayList<>();
44439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
44539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
44639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private int findOnTabletModeChangedListenerLocked(OnTabletModeChangedListener listener) {
44739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        final int N = mOnTabletModeChangedListeners.size();
44839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        for (int i = 0; i < N; i++) {
44939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            if (mOnTabletModeChangedListeners.get(i).mListener == listener) {
45039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                return i;
45139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
45239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
45339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        return -1;
45439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
45539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
45639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    /**
4579df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Gets information about all supported keyboard layouts.
4589df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
4599df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * The input manager consults the built-in keyboard layouts as well
4609df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * as all keyboard layouts advertised by applications using a
4619df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver.
4629df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
4639df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
4649df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @return A list of all supported keyboard layouts.
4659f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     *
4669df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
4679df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
4689f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public KeyboardLayout[] getKeyboardLayouts() {
4699f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        try {
4709f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return mIm.getKeyboardLayouts();
4719f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
472c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
4739df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
4749df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
4759df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
4769df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
4770748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * Gets information about all supported keyboard layouts appropriate
4780748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * for a specific input device.
4790748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * <p>
4800748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * The input manager consults the built-in keyboard layouts as well
4810748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * as all keyboard layouts advertised by applications using a
4820748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver.
4830748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * </p>
4840748342d2ed264c01384fbaa4446a702a8824813Michael Wright     *
4850748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * @return A list of all supported keyboard layouts for a specific
4860748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * input device.
4870748342d2ed264c01384fbaa4446a702a8824813Michael Wright     *
4880748342d2ed264c01384fbaa4446a702a8824813Michael Wright     * @hide
4890748342d2ed264c01384fbaa4446a702a8824813Michael Wright     */
4900748342d2ed264c01384fbaa4446a702a8824813Michael Wright    public KeyboardLayout[] getKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
4910748342d2ed264c01384fbaa4446a702a8824813Michael Wright        try {
4920748342d2ed264c01384fbaa4446a702a8824813Michael Wright            return mIm.getKeyboardLayoutsForInputDevice(identifier);
4930748342d2ed264c01384fbaa4446a702a8824813Michael Wright        } catch (RemoteException ex) {
494c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
4950748342d2ed264c01384fbaa4446a702a8824813Michael Wright        }
4960748342d2ed264c01384fbaa4446a702a8824813Michael Wright    }
4970748342d2ed264c01384fbaa4446a702a8824813Michael Wright
4980748342d2ed264c01384fbaa4446a702a8824813Michael Wright    /**
4999df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * Gets the keyboard layout with the specified descriptor.
5009df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
5019df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @param keyboardLayoutDescriptor The keyboard layout descriptor, as returned by
5029df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * {@link KeyboardLayout#getDescriptor()}.
5039df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @return The keyboard layout, or null if it could not be loaded.
5049df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
5059df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
5069df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
5079df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
5089df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        if (keyboardLayoutDescriptor == null) {
5099df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
5109df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
5119df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
5129df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        try {
5139f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return mIm.getKeyboardLayout(keyboardLayoutDescriptor);
5149f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
515c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
5169df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
5179df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
5189df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
5199df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
520fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * Gets the current keyboard layout descriptor for the specified input
521fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * device.
5229df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
523fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param identifier Identifier for the input device
524fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @return The keyboard layout descriptor, or null if no keyboard layout has
525fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     *         been set.
5269df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
5279df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
528fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public String getCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier) {
5299f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        try {
530fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            return mIm.getCurrentKeyboardLayoutForInputDevice(identifier);
5319f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
532c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
5339f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        }
5349df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
5359df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
5369df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    /**
537fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * Sets the current keyboard layout descriptor for the specified input
538fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * device.
5399df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * <p>
540fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * This method may have the side-effect of causing the input device in
541fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * question to be reconfigured.
5429df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * </p>
5439df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     *
544fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param identifier The identifier for the input device.
545fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param keyboardLayoutDescriptor The keyboard layout descriptor to use,
546fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     *            must not be null.
5479df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     * @hide
5489df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown     */
549fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public void setCurrentKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
5509df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown            String keyboardLayoutDescriptor) {
551fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier == null) {
552fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            throw new IllegalArgumentException("identifier must not be null");
5539df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
554cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (keyboardLayoutDescriptor == null) {
555cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
556cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
557cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
558cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        try {
559fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            mIm.setCurrentKeyboardLayoutForInputDevice(identifier,
560cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown                    keyboardLayoutDescriptor);
561cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        } catch (RemoteException ex) {
562c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
563cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
564cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
565cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
566cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    /**
567fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * Gets all keyboard layout descriptors that are enabled for the specified
568fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * input device.
569cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     *
570fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param identifier The identifier for the input device.
571cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @return The keyboard layout descriptors.
572cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @hide
573cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     */
5740748342d2ed264c01384fbaa4446a702a8824813Michael Wright    public String[] getEnabledKeyboardLayoutsForInputDevice(InputDeviceIdentifier identifier) {
575fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier == null) {
576cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
577cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
578cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
579cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        try {
5800748342d2ed264c01384fbaa4446a702a8824813Michael Wright            return mIm.getEnabledKeyboardLayoutsForInputDevice(identifier);
581cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        } catch (RemoteException ex) {
582c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
583cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
584cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
585cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
586cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    /**
587cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * Adds the keyboard layout descriptor for the specified input device.
588cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * <p>
589fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * This method may have the side-effect of causing the input device in
590fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * question to be reconfigured.
591cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * </p>
592cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     *
593fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param identifier The identifier for the input device.
594fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param keyboardLayoutDescriptor The descriptor of the keyboard layout to
595fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     *            add.
596cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @hide
597cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     */
598fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public void addKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
599cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            String keyboardLayoutDescriptor) {
600fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier == null) {
601cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
602cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
603cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (keyboardLayoutDescriptor == null) {
604cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
605cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
606cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
607cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        try {
608fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            mIm.addKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
609cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        } catch (RemoteException ex) {
610c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
611cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
612cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    }
613cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown
614cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown    /**
615cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * Removes the keyboard layout descriptor for the specified input device.
616cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * <p>
617fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * This method may have the side-effect of causing the input device in
618fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * question to be reconfigured.
619cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * </p>
620cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     *
621fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param identifier The identifier for the input device.
622fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     * @param keyboardLayoutDescriptor The descriptor of the keyboard layout to
623fb290df3c9a6f37ec050163029e25844de2f8590RoboErik     *            remove.
624cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     * @hide
625cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown     */
626fb290df3c9a6f37ec050163029e25844de2f8590RoboErik    public void removeKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
627cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            String keyboardLayoutDescriptor) {
628fb290df3c9a6f37ec050163029e25844de2f8590RoboErik        if (identifier == null) {
629cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
630cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
631cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        if (keyboardLayoutDescriptor == null) {
632cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
633cf39bdf3dff5e29447f6ce734b76dc3490385e58Jeff Brown        }
6349df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
6359df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        try {
636fb290df3c9a6f37ec050163029e25844de2f8590RoboErik            mIm.removeKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
6379f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        } catch (RemoteException ex) {
638c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
6399df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown        }
6409df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown    }
6419df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown
642d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
643d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    /**
644d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * Gets the keyboard layout for the specified input device and IME subtype.
645d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     *
646d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @param identifier The identifier for the input device.
647d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @param inputMethodInfo The input method.
64846ac35d09b0a1ba7af7eb4c14293a7978edcd2abYohei Yukawa     * @param inputMethodSubtype The input method subtype. {@code null} if this input method does
64946ac35d09b0a1ba7af7eb4c14293a7978edcd2abYohei Yukawa     * not support any 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     */
65546ac35d09b0a1ba7af7eb4c14293a7978edcd2abYohei Yukawa    @Nullable
656d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    public KeyboardLayout getKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
65746ac35d09b0a1ba7af7eb4c14293a7978edcd2abYohei Yukawa            InputMethodInfo inputMethodInfo, @Nullable InputMethodSubtype inputMethodSubtype) {
658d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        try {
659d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            return mIm.getKeyboardLayoutForInputDevice(
660d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    identifier, inputMethodInfo, inputMethodSubtype);
661d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        } catch (RemoteException ex) {
662c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
663d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
664d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    }
665d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
666d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    /**
667d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * Sets the keyboard layout for the specified input device and IME subtype pair.
668d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     *
669d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @param identifier The identifier for the input device.
670d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @param inputMethodInfo The input method with which to associate the keyboard layout.
671d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @param inputMethodSubtype The input method subtype which which to associate the keyboard
67246ac35d09b0a1ba7af7eb4c14293a7978edcd2abYohei Yukawa     * layout. {@code null} if this input method does not support any subtype.
673d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @param keyboardLayoutDescriptor The descriptor of the keyboard layout to set
674d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     *
675d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     * @hide
676d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright     */
677d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    public void setKeyboardLayoutForInputDevice(InputDeviceIdentifier identifier,
67846ac35d09b0a1ba7af7eb4c14293a7978edcd2abYohei Yukawa            InputMethodInfo inputMethodInfo, @Nullable InputMethodSubtype inputMethodSubtype,
679d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            String keyboardLayoutDescriptor) {
680d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        try {
681d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright            mIm.setKeyboardLayoutForInputDevice(identifier, inputMethodInfo,
682d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright                    inputMethodSubtype, keyboardLayoutDescriptor);
683d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        } catch (RemoteException ex) {
684c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
685d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright        }
686d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright    }
687d5f7ed9fe9dc3590f6ef9cb7470e29e836a95907Michael Wright
688ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
689d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * Gets the TouchCalibration applied to the specified input device's coordinates.
690d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     *
691d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * @param inputDeviceDescriptor The input device descriptor.
692d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * @return The TouchCalibration currently assigned for use with the given
693d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * input device. If none is set, an identity TouchCalibration is returned.
694d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     *
695d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * @hide
696d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     */
697d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke    public TouchCalibration getTouchCalibration(String inputDeviceDescriptor, int surfaceRotation) {
698d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        try {
699d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke            return mIm.getTouchCalibrationForInputDevice(inputDeviceDescriptor, surfaceRotation);
700d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        } catch (RemoteException ex) {
701c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
702d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
703d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke    }
704d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke
705d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke    /**
706d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * Sets the TouchCalibration to apply to the specified input device's coordinates.
707d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * <p>
708d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * This method may have the side-effect of causing the input device in question
709d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * to be reconfigured. Requires {@link android.Manifest.permissions.SET_INPUT_CALIBRATION}.
710d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * </p>
711d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     *
712d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * @param inputDeviceDescriptor The input device descriptor.
713d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * @param calibration The calibration to be applied
714d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     *
715d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     * @hide
716d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke     */
717d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke    public void setTouchCalibration(String inputDeviceDescriptor, int surfaceRotation,
718d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke            TouchCalibration calibration) {
719d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        try {
720d52207423225bcd99e94276e9d0fc2cb5f905602Jason Gerecke            mIm.setTouchCalibrationForInputDevice(inputDeviceDescriptor, surfaceRotation, calibration);
721d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        } catch (RemoteException ex) {
722c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
723d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke        }
724d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke    }
725d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke
726d6396d67201fb2b64d13070324bb115c9c23b08aJason Gerecke    /**
727ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Gets the mouse pointer speed.
728ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
729ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Only returns the permanent mouse pointer speed.  Ignores any temporary pointer
730ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * speed set by {@link #tryPointerSpeed}.
731ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
732ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
7339f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @param context The application context.
734ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @return The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
735ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
736ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
737ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
738ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
7399f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public int getPointerSpeed(Context context) {
740ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        int speed = DEFAULT_POINTER_SPEED;
741ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
7429f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            speed = Settings.System.getInt(context.getContentResolver(),
743ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                    Settings.System.POINTER_SPEED);
744ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (SettingNotFoundException snfe) {
745ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
746ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        return speed;
747ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
748ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
749ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
750ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Sets the mouse pointer speed.
751ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
752ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Requires {@link android.Manifest.permissions.WRITE_SETTINGS}.
753ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
754ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
7559f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown     * @param context The application context.
756ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
757ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
758ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
759ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
760ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
7619f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public void setPointerSpeed(Context context, int speed) {
762ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
763ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("speed out of range");
764ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
765ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
7669f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown        Settings.System.putInt(context.getContentResolver(),
767ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                Settings.System.POINTER_SPEED, speed);
768ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
769ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
770ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
771ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Changes the mouse pointer speed temporarily, but does not save the setting.
772ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
773ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Requires {@link android.Manifest.permission.SET_POINTER_SPEED}.
774ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
775ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
776ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
777ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
778ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
779ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
780ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
781ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    public void tryPointerSpeed(int speed) {
782ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
783ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("speed out of range");
784ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
785ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
786ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
7879f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            mIm.tryPointerSpeed(speed);
788ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (RemoteException ex) {
789c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
790ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
791ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
792ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
793ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
794ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Queries the framework about whether any physical keys exist on the
795ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * any keyboard attached to the device that are capable of producing the given
796ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * array of key codes.
797ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
798ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param keyCodes The array of key codes to query.
799ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @return A new array of the same size as the key codes array whose elements
800ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * are set to true if at least one attached keyboard supports the corresponding key code
801ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * at the same index in the key codes array.
802ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
803ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
804ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
8059f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public boolean[] deviceHasKeys(int[] keyCodes) {
806b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright        return deviceHasKeys(-1, keyCodes);
807b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright    }
808b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright
809b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright    /**
810b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * Queries the framework about whether any physical keys exist on the
811b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * any keyboard attached to the device that are capable of producing the given
812b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * array of key codes.
813b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     *
814b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * @param id The id of the device to query.
815b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * @param keyCodes The array of key codes to query.
816b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * @return A new array of the same size as the key codes array whose elements are set to true
817b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * if the given device could produce the corresponding key code at the same index in the key
818b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * codes array.
819b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     *
820b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     * @hide
821b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright     */
822b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright    public boolean[] deviceHasKeys(int id, int[] keyCodes) {
823ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        boolean[] ret = new boolean[keyCodes.length];
824ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
825b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright            mIm.hasKeys(id, InputDevice.SOURCE_ANY, keyCodes, ret);
826ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (RemoteException e) {
827c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
828ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
829ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        return ret;
830ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
831ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
832b7b2d4b490f5dd672e0b00ced579dc052e3637e9Michael Wright
833ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    /**
834ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Injects an input event into the event system on behalf of an application.
835ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * The synchronization mode determines whether the method blocks while waiting for
836ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * input injection to proceed.
837ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * <p>
838ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Requires {@link android.Manifest.permission.INJECT_EVENTS} to inject into
839ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * windows that are owned by other applications.
840ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p><p>
841ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * Make sure you correctly set the event time and input source of the event
842ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * before calling this method.
843ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * </p>
844ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
845ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param event The event to inject.
846ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @param mode The synchronization mode.  One of:
847ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #INJECT_INPUT_EVENT_MODE_ASYNC},
848ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT}, or
849ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * {@link #INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH}.
850ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @return True if input event injection succeeded.
851ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     *
852ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     * @hide
853ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown     */
8549f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown    public boolean injectInputEvent(InputEvent event, int mode) {
855ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (event == null) {
856ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("event must not be null");
857ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
858ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        if (mode != INJECT_INPUT_EVENT_MODE_ASYNC
859ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                && mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
860ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown                && mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
861ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown            throw new IllegalArgumentException("mode is invalid");
862ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
863ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown
864ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        try {
8659f25b7fdf216c9ef0bd2322cd223eeaf0d60f77fJeff Brown            return mIm.injectInputEvent(event, mode);
866ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        } catch (RemoteException ex) {
867c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
868ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown        }
869ac14351e16e1258f1cb54e2bf772b8be004eb2b8Jeff Brown    }
870af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
8711db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai    /**
8721db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai     * Changes the mouse pointer's icon shape into the specified id.
8731db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai     *
8741db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai     * @param iconId The id of the pointer graphic, as a value between
875f9d9ce7705475874c82af04eb9b208a7fb556792Michael Wright     * {@link PointerIcon.TYPE_ARROW} and {@link PointerIcon.TYPE_GRABBING}.
8761db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai     *
8771db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai     * @hide
8781db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai     */
879f9d9ce7705475874c82af04eb9b208a7fb556792Michael Wright    public void setPointerIconType(int iconId) {
8801db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai        try {
881f9d9ce7705475874c82af04eb9b208a7fb556792Michael Wright            mIm.setPointerIconType(iconId);
8821db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai        } catch (RemoteException ex) {
883c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
8841db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai        }
8851db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai    }
8861db5397d88e722b1ab82ccb2b429ceec1179ccd8Jun Mukai
887d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    /** @hide */
888d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    public void setCustomPointerIcon(PointerIcon icon) {
889d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai        try {
890d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai            mIm.setCustomPointerIcon(icon);
891d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai        } catch (RemoteException ex) {
892c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw ex.rethrowFromSystemServer();
893d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai        }
894d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai    }
895d4eaef7f4c5a5d281de4fff272cd33e892e26264Jun Mukai
896af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void populateInputDevicesLocked() {
897af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (mInputDevicesChangedListener == null) {
898af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final InputDevicesChangedListener listener = new InputDevicesChangedListener();
899af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            try {
900af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mIm.registerInputDevicesChangedListener(listener);
901af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            } catch (RemoteException ex) {
902c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw ex.rethrowFromSystemServer();
903af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
904af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mInputDevicesChangedListener = listener;
905af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
906af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
907af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (mInputDevices == null) {
908af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            final int[] ids;
909af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            try {
910af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                ids = mIm.getInputDeviceIds();
911af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            } catch (RemoteException ex) {
912c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw ex.rethrowFromSystemServer();
913af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
914af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
915af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mInputDevices = new SparseArray<InputDevice>();
916af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < ids.length; i++) {
917af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                mInputDevices.put(ids[i], null);
918af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
919af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
920af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
921af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
922af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void onInputDevicesChanged(int[] deviceIdAndGeneration) {
923af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        if (DEBUG) {
924af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            Log.d(TAG, "Received input devices changed.");
925af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
926af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
927af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        synchronized (mInputDevicesLock) {
928af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = mInputDevices.size(); --i > 0; ) {
929af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                final int deviceId = mInputDevices.keyAt(i);
930af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                if (!containsDeviceId(deviceIdAndGeneration, deviceId)) {
931af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    if (DEBUG) {
932af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        Log.d(TAG, "Device removed: " + deviceId);
933af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    }
934af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mInputDevices.removeAt(i);
935af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    sendMessageToInputDeviceListenersLocked(MSG_DEVICE_REMOVED, deviceId);
936af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                }
937af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
938af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
939af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
940af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                final int deviceId = deviceIdAndGeneration[i];
941af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                int index = mInputDevices.indexOfKey(deviceId);
942af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                if (index >= 0) {
943af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    final InputDevice device = mInputDevices.valueAt(index);
944af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    if (device != null) {
945af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        final int generation = deviceIdAndGeneration[i + 1];
946af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        if (device.getGeneration() != generation) {
947af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            if (DEBUG) {
948af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                                Log.d(TAG, "Device changed: " + deviceId);
949af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            }
950af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            mInputDevices.setValueAt(index, null);
951af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                            sendMessageToInputDeviceListenersLocked(MSG_DEVICE_CHANGED, deviceId);
952af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        }
953af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    }
954af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                } else {
955af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    if (DEBUG) {
956af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                        Log.d(TAG, "Device added: " + deviceId);
957af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    }
958af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mInputDevices.put(deviceId, null);
959af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    sendMessageToInputDeviceListenersLocked(MSG_DEVICE_ADDED, deviceId);
960af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                }
961af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
962af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
963af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
964af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
965af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private void sendMessageToInputDeviceListenersLocked(int what, int deviceId) {
966af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        final int numListeners = mInputDeviceListeners.size();
967af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        for (int i = 0; i < numListeners; i++) {
968af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            InputDeviceListenerDelegate listener = mInputDeviceListeners.get(i);
969af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            listener.sendMessage(listener.obtainMessage(what, deviceId, 0));
970af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
971af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
972af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
973af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static boolean containsDeviceId(int[] deviceIdAndGeneration, int deviceId) {
974af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        for (int i = 0; i < deviceIdAndGeneration.length; i += 2) {
975af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            if (deviceIdAndGeneration[i] == deviceId) {
976af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                return true;
977af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
978af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
979af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        return false;
980af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
981af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
98239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
98339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private void onTabletModeChanged(long whenNanos, boolean inTabletMode) {
98439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        if (DEBUG) {
98539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            Log.d(TAG, "Received tablet mode changed: "
98639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    + "whenNanos=" + whenNanos + ", inTabletMode=" + inTabletMode);
98739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
98839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        synchronized (mTabletModeLock) {
98939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            final int N = mOnTabletModeChangedListeners.size();
99039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            for (int i = 0; i < N; i++) {
99139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                OnTabletModeChangedListenerDelegate listener =
99239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                        mOnTabletModeChangedListeners.get(i);
99339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                listener.sendTabletModeChanged(whenNanos, inTabletMode);
99439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
99539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
99639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
99739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
998af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    /**
999a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     * Gets a vibrator service associated with an input device, assuming it has one.
1000a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     * @return The vibrator, never null.
1001a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     * @hide
1002a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown     */
1003a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    public Vibrator getInputDeviceVibrator(int deviceId) {
1004a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        return new InputDeviceVibrator(deviceId);
1005a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
1006a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1007a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    /**
1008af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     * Listens for changes in input devices.
1009af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown     */
1010af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    public interface InputDeviceListener {
1011af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        /**
1012af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Called whenever an input device has been added to the system.
1013af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Use {@link InputManager#getInputDevice} to get more information about the device.
1014af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         *
1015af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * @param deviceId The id of the input device that was added.
1016af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         */
1017af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        void onInputDeviceAdded(int deviceId);
1018af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1019af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        /**
1020af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Called whenever an input device has been removed from the system.
1021af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         *
1022af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * @param deviceId The id of the input device that was removed.
1023af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         */
1024af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        void onInputDeviceRemoved(int deviceId);
1025af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1026af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        /**
1027af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * Called whenever the properties of an input device have changed since they
1028af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * were last queried.  Use {@link InputManager#getInputDevice} to get
1029af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * a fresh {@link InputDevice} object with the new properties.
1030af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         *
1031af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         * @param deviceId The id of the input device that changed.
1032af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown         */
1033af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        void onInputDeviceChanged(int deviceId);
1034af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
1035af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1036af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private final class InputDevicesChangedListener extends IInputDevicesChangedListener.Stub {
1037af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        @Override
1038af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public void onInputDevicesChanged(int[] deviceIdAndGeneration) throws RemoteException {
1039af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            InputManager.this.onInputDevicesChanged(deviceIdAndGeneration);
1040af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
1041af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
1042af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1043af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    private static final class InputDeviceListenerDelegate extends Handler {
1044af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public final InputDeviceListener mListener;
1045af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1046af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public InputDeviceListenerDelegate(InputDeviceListener listener, Handler handler) {
1047af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            super(handler != null ? handler.getLooper() : Looper.myLooper());
1048af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            mListener = listener;
1049af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
1050af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown
1051af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        @Override
1052af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        public void handleMessage(Message msg) {
1053af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            switch (msg.what) {
1054af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                case MSG_DEVICE_ADDED:
1055af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mListener.onInputDeviceAdded(msg.arg1);
1056af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    break;
1057af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                case MSG_DEVICE_REMOVED:
1058af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mListener.onInputDeviceRemoved(msg.arg1);
1059af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    break;
1060af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                case MSG_DEVICE_CHANGED:
1061af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    mListener.onInputDeviceChanged(msg.arg1);
1062af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown                    break;
1063af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown            }
1064af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown        }
1065af9e8d38184c6ba4d2d3eb5bde7014a66dd8a78bJeff Brown    }
1066a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
106739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    /** @hide */
106839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    public interface OnTabletModeChangedListener {
106939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        /**
107039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright         * Called whenever the device goes into or comes out of tablet mode.
107139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright         *
107239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright         * @param whenNanos The time at which the device transitioned into or
107339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright         * out of tablet mode. This is given in nanoseconds in the
107439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright         * {@link SystemClock#uptimeMillis} time base.
107539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright         */
107639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        void onTabletModeChanged(long whenNanos, boolean inTabletMode);
107739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
107839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
107939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private final class TabletModeChangedListener extends ITabletModeChangedListener.Stub {
108039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        @Override
108139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        public void onTabletModeChanged(long whenNanos, boolean inTabletMode) {
108239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            InputManager.this.onTabletModeChanged(whenNanos, inTabletMode);
108339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
108439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
108539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
108639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    private static final class OnTabletModeChangedListenerDelegate extends Handler {
108739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        private static final int MSG_TABLET_MODE_CHANGED = 0;
108839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
108939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        public final OnTabletModeChangedListener mListener;
109039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
109139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        public OnTabletModeChangedListenerDelegate(
109239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                OnTabletModeChangedListener listener, Handler handler) {
109339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            super(handler != null ? handler.getLooper() : Looper.myLooper());
109439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            mListener = listener;
109539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
109639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
109739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        public void sendTabletModeChanged(long whenNanos, boolean inTabletMode) {
109839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            SomeArgs args = SomeArgs.obtain();
109939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            args.argi1 = (int) (whenNanos & 0xFFFFFFFF);
110039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            args.argi2 = (int) (whenNanos >> 32);
110139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            args.arg1 = (Boolean) inTabletMode;
110239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            obtainMessage(MSG_TABLET_MODE_CHANGED, args).sendToTarget();
110339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
110439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
110539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        @Override
110639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        public void handleMessage(Message msg) {
110739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            switch (msg.what) {
110839e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                case MSG_TABLET_MODE_CHANGED:
110939e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    SomeArgs args = (SomeArgs) msg.obj;
111039e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    long whenNanos = (args.argi1 & 0xFFFFFFFFl) | ((long) args.argi2 << 32);
111139e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    boolean inTabletMode = (boolean) args.arg1;
111239e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    mListener.onTabletModeChanged(whenNanos, inTabletMode);
111339e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright                    break;
111439e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright            }
111539e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright        }
111639e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright    }
111739e5e947447bc611205404ae6a4690656f1aa0f9Michael Wright
1118a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    private final class InputDeviceVibrator extends Vibrator {
1119a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        private final int mDeviceId;
1120a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        private final Binder mToken;
1121a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1122a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public InputDeviceVibrator(int deviceId) {
1123a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mDeviceId = deviceId;
1124a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            mToken = new Binder();
1125a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1126a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1127a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
1128a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public boolean hasVibrator() {
1129a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            return true;
1130a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1131a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
11321af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        /**
11331af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock         * @hide
11341af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock         */
1135a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
11367b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock        public void vibrate(int uid, String opPkg, long milliseconds, AudioAttributes attributes) {
1137a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            vibrate(new long[] { 0, milliseconds}, -1);
1138a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1139a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
11401af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock        /**
11411af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock         * @hide
11421af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock         */
1143a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
11448fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer        public void vibrate(int uid, String opPkg, long[] pattern, int repeat,
11457b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                AudioAttributes attributes) {
1146a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            if (repeat >= pattern.length) {
1147a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                throw new ArrayIndexOutOfBoundsException();
1148a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
1149a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            try {
1150a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                mIm.vibrate(mDeviceId, pattern, repeat, mToken);
1151a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            } catch (RemoteException ex) {
1152c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw ex.rethrowFromSystemServer();
1153a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
1154a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1155a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown
1156a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        @Override
1157a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        public void cancel() {
1158a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            try {
1159a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown                mIm.cancelVibrate(mDeviceId, mToken);
1160a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            } catch (RemoteException ex) {
1161c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw ex.rethrowFromSystemServer();
1162a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown            }
1163a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown        }
1164a47425a13c19f95057df78b8bb65bb25657e8753Jeff Brown    }
11659df6e7a926ce480baf70e97ee1b9ea387193f6adJeff Brown}
1166