| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.hardware.input; |
| |
| import android.annotation.SdkConstant; |
| import android.annotation.SdkConstant.SdkConstantType; |
| import android.content.Context; |
| import android.os.IBinder; |
| import android.os.RemoteException; |
| import android.os.ServiceManager; |
| import android.provider.Settings; |
| import android.provider.Settings.SettingNotFoundException; |
| import android.util.Log; |
| import android.util.SparseArray; |
| import android.view.InputDevice; |
| import android.view.InputEvent; |
| |
| /** |
| * Provides information about input devices and available key layouts. |
| * <p> |
| * Get an instance of this class by calling |
| * {@link android.content.Context#getSystemService(java.lang.String) |
| * Context.getSystemService()} with the argument |
| * {@link android.content.Context#INPUT_SERVICE}. |
| * </p> |
| */ |
| public final class InputManager { |
| private static final String TAG = "InputManager"; |
| |
| private static InputManager sInstance; |
| |
| private final IInputManager mIm; |
| private final SparseArray<InputDevice> mInputDevices = new SparseArray<InputDevice>(); |
| |
| /** |
| * Broadcast Action: Query available keyboard layouts. |
| * <p> |
| * The input manager service locates available keyboard layouts |
| * by querying broadcast receivers that are registered for this action. |
| * An application can offer additional keyboard layouts to the user |
| * by declaring a suitable broadcast receiver in its manifest. |
| * </p><p> |
| * Here is an example broadcast receiver declaration that an application |
| * might include in its AndroidManifest.xml to advertise keyboard layouts. |
| * The meta-data specifies a resource that contains a description of each keyboard |
| * layout that is provided by the application. |
| * <pre><code> |
| * <receiver android:name=".InputDeviceReceiver"> |
| * <intent-filter> |
| * <action android:name="android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS" /> |
| * </intent-filter> |
| * <meta-data android:name="android.hardware.input.metadata.KEYBOARD_LAYOUTS" |
| * android:resource="@xml/keyboard_layouts" /> |
| * </receiver> |
| * </code></pre> |
| * </p><p> |
| * In the above example, the <code>@xml/keyboard_layouts</code> resource refers to |
| * an XML resource whose root element is <code><keyboard-layouts></code> that |
| * contains zero or more <code><keyboard-layout></code> elements. |
| * Each <code><keyboard-layout></code> element specifies the name, label, and location |
| * of a key character map for a particular keyboard layout. |
| * <pre></code> |
| * <?xml version="1.0" encoding="utf-8"?> |
| * <keyboard-layouts xmlns:android="http://schemas.android.com/apk/res/android"> |
| * <keyboard-layout android:name="keyboard_layout_english_us" |
| * android:label="@string/keyboard_layout_english_us_label" |
| * android:kcm="@raw/keyboard_layout_english_us" /> |
| * </keyboard-layouts> |
| * </p><p> |
| * The <code>android:name</code> attribute specifies an identifier by which |
| * the keyboard layout will be known in the package. |
| * The <code>android:label</code> attributes specifies a human-readable descriptive |
| * label to describe the keyboard layout in the user interface, such as "English (US)". |
| * The <code>android:kcm</code> attribute refers to a |
| * <a href="http://source.android.com/tech/input/key-character-map-files.html"> |
| * key character map</a> resource that defines the keyboard layout. |
| * </p> |
| */ |
| @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) |
| public static final String ACTION_QUERY_KEYBOARD_LAYOUTS = |
| "android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS"; |
| |
| /** |
| * Metadata Key: Keyboard layout metadata associated with |
| * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS}. |
| * <p> |
| * Specifies the resource id of a XML resource that describes the keyboard |
| * layouts that are provided by the application. |
| * </p> |
| */ |
| public static final String META_DATA_KEYBOARD_LAYOUTS = |
| "android.hardware.input.metadata.KEYBOARD_LAYOUTS"; |
| |
| /** |
| * Pointer Speed: The minimum (slowest) pointer speed (-7). |
| * @hide |
| */ |
| public static final int MIN_POINTER_SPEED = -7; |
| |
| /** |
| * Pointer Speed: The maximum (fastest) pointer speed (7). |
| * @hide |
| */ |
| public static final int MAX_POINTER_SPEED = 7; |
| |
| /** |
| * Pointer Speed: The default pointer speed (0). |
| * @hide |
| */ |
| public static final int DEFAULT_POINTER_SPEED = 0; |
| |
| /** |
| * Input Event Injection Synchronization Mode: None. |
| * Never blocks. Injection is asynchronous and is assumed always to be successful. |
| * @hide |
| */ |
| public static final int INJECT_INPUT_EVENT_MODE_ASYNC = 0; // see InputDispatcher.h |
| |
| /** |
| * Input Event Injection Synchronization Mode: Wait for result. |
| * Waits for previous events to be dispatched so that the input dispatcher can |
| * determine whether input event injection will be permitted based on the current |
| * input focus. Does not wait for the input event to finish being handled |
| * by the application. |
| * @hide |
| */ |
| public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1; // see InputDispatcher.h |
| |
| /** |
| * Input Event Injection Synchronization Mode: Wait for finish. |
| * Waits for the event to be delivered to the application and handled. |
| * @hide |
| */ |
| public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2; // see InputDispatcher.h |
| |
| private InputManager(IInputManager im) { |
| mIm = im; |
| } |
| |
| /** |
| * Gets an instance of the input manager. |
| * |
| * @return The input manager instance. |
| * |
| * @hide |
| */ |
| public static InputManager getInstance() { |
| synchronized (InputManager.class) { |
| if (sInstance == null) { |
| IBinder b = ServiceManager.getService(Context.INPUT_SERVICE); |
| sInstance = new InputManager(IInputManager.Stub.asInterface(b)); |
| } |
| return sInstance; |
| } |
| } |
| |
| /** |
| * Gets information about all supported keyboard layouts. |
| * <p> |
| * The input manager consults the built-in keyboard layouts as well |
| * as all keyboard layouts advertised by applications using a |
| * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver. |
| * </p> |
| * |
| * @return A list of all supported keyboard layouts. |
| * |
| * @hide |
| */ |
| public KeyboardLayout[] getKeyboardLayouts() { |
| try { |
| return mIm.getKeyboardLayouts(); |
| } catch (RemoteException ex) { |
| Log.w(TAG, "Could not get list of keyboard layout informations.", ex); |
| return new KeyboardLayout[0]; |
| } |
| } |
| |
| /** |
| * Gets the keyboard layout with the specified descriptor. |
| * |
| * @param keyboardLayoutDescriptor The keyboard layout descriptor, as returned by |
| * {@link KeyboardLayout#getDescriptor()}. |
| * @return The keyboard layout, or null if it could not be loaded. |
| * |
| * @hide |
| */ |
| public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) { |
| if (keyboardLayoutDescriptor == null) { |
| throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null"); |
| } |
| |
| try { |
| return mIm.getKeyboardLayout(keyboardLayoutDescriptor); |
| } catch (RemoteException ex) { |
| Log.w(TAG, "Could not get keyboard layout information.", ex); |
| return null; |
| } |
| } |
| |
| /** |
| * Gets the keyboard layout descriptor for the specified input device. |
| * |
| * @param inputDeviceDescriptor The input device descriptor. |
| * @return The keyboard layout descriptor, or null if unknown or if the default |
| * keyboard layout will be used. |
| * |
| * @hide |
| */ |
| public String getKeyboardLayoutForInputDevice(String inputDeviceDescriptor) { |
| if (inputDeviceDescriptor == null) { |
| throw new IllegalArgumentException("inputDeviceDescriptor must not be null"); |
| } |
| |
| try { |
| return mIm.getKeyboardLayoutForInputDevice(inputDeviceDescriptor); |
| } catch (RemoteException ex) { |
| Log.w(TAG, "Could not get keyboard layout for input device.", ex); |
| return null; |
| } |
| } |
| |
| /** |
| * Sets the keyboard layout descriptor for the specified input device. |
| * <p> |
| * This method may have the side-effect of causing the input device in question |
| * to be reconfigured. |
| * </p> |
| * |
| * @param inputDeviceDescriptor The input device descriptor. |
| * @param keyboardLayoutDescriptor The keyboard layout descriptor, or null to remove |
| * the mapping so that the default keyboard layout will be used for the input device. |
| * |
| * @hide |
| */ |
| public void setKeyboardLayoutForInputDevice(String inputDeviceDescriptor, |
| String keyboardLayoutDescriptor) { |
| if (inputDeviceDescriptor == null) { |
| throw new IllegalArgumentException("inputDeviceDescriptor must not be null"); |
| } |
| |
| try { |
| mIm.setKeyboardLayoutForInputDevice(inputDeviceDescriptor, keyboardLayoutDescriptor); |
| } catch (RemoteException ex) { |
| Log.w(TAG, "Could not set keyboard layout for input device.", ex); |
| } |
| } |
| |
| /** |
| * Gets the mouse pointer speed. |
| * <p> |
| * Only returns the permanent mouse pointer speed. Ignores any temporary pointer |
| * speed set by {@link #tryPointerSpeed}. |
| * </p> |
| * |
| * @param context The application context. |
| * @return The pointer speed as a value between {@link #MIN_POINTER_SPEED} and |
| * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}. |
| * |
| * @hide |
| */ |
| public int getPointerSpeed(Context context) { |
| int speed = DEFAULT_POINTER_SPEED; |
| try { |
| speed = Settings.System.getInt(context.getContentResolver(), |
| Settings.System.POINTER_SPEED); |
| } catch (SettingNotFoundException snfe) { |
| } |
| return speed; |
| } |
| |
| /** |
| * Sets the mouse pointer speed. |
| * <p> |
| * Requires {@link android.Manifest.permissions.WRITE_SETTINGS}. |
| * </p> |
| * |
| * @param context The application context. |
| * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and |
| * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}. |
| * |
| * @hide |
| */ |
| public void setPointerSpeed(Context context, int speed) { |
| if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) { |
| throw new IllegalArgumentException("speed out of range"); |
| } |
| |
| Settings.System.putInt(context.getContentResolver(), |
| Settings.System.POINTER_SPEED, speed); |
| } |
| |
| /** |
| * Changes the mouse pointer speed temporarily, but does not save the setting. |
| * <p> |
| * Requires {@link android.Manifest.permission.SET_POINTER_SPEED}. |
| * </p> |
| * |
| * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and |
| * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}. |
| * |
| * @hide |
| */ |
| public void tryPointerSpeed(int speed) { |
| if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) { |
| throw new IllegalArgumentException("speed out of range"); |
| } |
| |
| try { |
| mIm.tryPointerSpeed(speed); |
| } catch (RemoteException ex) { |
| Log.w(TAG, "Could not set temporary pointer speed.", ex); |
| } |
| } |
| |
| /** |
| * Gets information about the input device with the specified id. |
| * @param id The device id. |
| * @return The input device or null if not found. |
| * |
| * @hide |
| */ |
| public InputDevice getInputDevice(int id) { |
| synchronized (mInputDevices) { |
| InputDevice inputDevice = mInputDevices.get(id); |
| if (inputDevice != null) { |
| return inputDevice; |
| } |
| } |
| final InputDevice newInputDevice; |
| try { |
| newInputDevice = mIm.getInputDevice(id); |
| } catch (RemoteException ex) { |
| throw new RuntimeException("Could not get input device information.", ex); |
| } |
| synchronized (mInputDevices) { |
| InputDevice inputDevice = mInputDevices.get(id); |
| if (inputDevice != null) { |
| return inputDevice; |
| } |
| mInputDevices.put(id, newInputDevice); |
| return newInputDevice; |
| } |
| } |
| |
| /** |
| * Gets the ids of all input devices in the system. |
| * @return The input device ids. |
| * |
| * @hide |
| */ |
| public int[] getInputDeviceIds() { |
| try { |
| return mIm.getInputDeviceIds(); |
| } catch (RemoteException ex) { |
| throw new RuntimeException("Could not get input device ids.", ex); |
| } |
| } |
| |
| /** |
| * Queries the framework about whether any physical keys exist on the |
| * any keyboard attached to the device that are capable of producing the given |
| * array of key codes. |
| * |
| * @param keyCodes The array of key codes to query. |
| * @return A new array of the same size as the key codes array whose elements |
| * are set to true if at least one attached keyboard supports the corresponding key code |
| * at the same index in the key codes array. |
| * |
| * @hide |
| */ |
| public boolean[] deviceHasKeys(int[] keyCodes) { |
| boolean[] ret = new boolean[keyCodes.length]; |
| try { |
| mIm.hasKeys(-1, InputDevice.SOURCE_ANY, keyCodes, ret); |
| } catch (RemoteException e) { |
| // no fallback; just return the empty array |
| } |
| return ret; |
| } |
| |
| /** |
| * Injects an input event into the event system on behalf of an application. |
| * The synchronization mode determines whether the method blocks while waiting for |
| * input injection to proceed. |
| * <p> |
| * Requires {@link android.Manifest.permission.INJECT_EVENTS} to inject into |
| * windows that are owned by other applications. |
| * </p><p> |
| * Make sure you correctly set the event time and input source of the event |
| * before calling this method. |
| * </p> |
| * |
| * @param event The event to inject. |
| * @param mode The synchronization mode. One of: |
| * {@link #INJECT_INPUT_EVENT_MODE_ASYNC}, |
| * {@link #INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT}, or |
| * {@link #INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH}. |
| * @return True if input event injection succeeded. |
| * |
| * @hide |
| */ |
| public boolean injectInputEvent(InputEvent event, int mode) { |
| if (event == null) { |
| throw new IllegalArgumentException("event must not be null"); |
| } |
| if (mode != INJECT_INPUT_EVENT_MODE_ASYNC |
| && mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH |
| && mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) { |
| throw new IllegalArgumentException("mode is invalid"); |
| } |
| |
| try { |
| return mIm.injectInputEvent(event, mode); |
| } catch (RemoteException ex) { |
| return false; |
| } |
| } |
| } |