blob: 58e5b2dfaa375935c1f701862c43db6e0335093d [file] [log] [blame]
/*
* Copyright (C) 2010 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.view;
import android.annotation.IntDef;
import android.annotation.RequiresPermission;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.os.Build;
import android.os.NullVibrator;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Vibrator;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
/**
* Describes the capabilities of a particular input device.
* <p>
* Each input device may support multiple classes of input. For example, a multi-function
* keyboard may compose the capabilities of a standard keyboard together with a track pad mouse
* or other pointing device.
* </p><p>
* Some input devices present multiple distinguishable sources of input.
* Applications can query the framework about the characteristics of each distinct source.
* </p><p>
* As a further wrinkle, different kinds of input sources uses different coordinate systems
* to describe motion events. Refer to the comments on the input source constants for
* the appropriate interpretation.
* </p>
*/
public final class InputDevice implements Parcelable {
private final int mId;
private final int mGeneration;
private final int mControllerNumber;
private final String mName;
private final int mVendorId;
private final int mProductId;
private final String mDescriptor;
private final InputDeviceIdentifier mIdentifier;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private final boolean mIsExternal;
private final int mSources;
private final int mKeyboardType;
private final KeyCharacterMap mKeyCharacterMap;
private final boolean mHasVibrator;
private final boolean mHasMicrophone;
private final boolean mHasButtonUnderPad;
private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>();
private Vibrator mVibrator; // guarded by mMotionRanges during initialization
/**
* A mask for input source classes.
*
* Each distinct input source constant has one or more input source class bits set to
* specify the desired interpretation for its input events.
*/
public static final int SOURCE_CLASS_MASK = 0x000000ff;
/**
* The input source has no class.
*
* It is up to the application to determine how to handle the device based on the device type.
*/
public static final int SOURCE_CLASS_NONE = 0x00000000;
/**
* The input source has buttons or keys.
* Examples: {@link #SOURCE_KEYBOARD}, {@link #SOURCE_DPAD}.
*
* A {@link KeyEvent} should be interpreted as a button or key press.
*
* Use {@link #getKeyCharacterMap} to query the device's button and key mappings.
*/
public static final int SOURCE_CLASS_BUTTON = 0x00000001;
/**
* The input source is a pointing device associated with a display.
* Examples: {@link #SOURCE_TOUCHSCREEN}, {@link #SOURCE_MOUSE}.
*
* A {@link MotionEvent} should be interpreted as absolute coordinates in
* display units according to the {@link View} hierarchy. Pointer down/up indicated when
* the finger touches the display or when the selection button is pressed/released.
*
* Use {@link #getMotionRange} to query the range of the pointing device. Some devices permit
* touches outside the display area so the effective range may be somewhat smaller or larger
* than the actual display size.
*/
public static final int SOURCE_CLASS_POINTER = 0x00000002;
/**
* The input source is a trackball navigation device.
* Examples: {@link #SOURCE_TRACKBALL}.
*
* A {@link MotionEvent} should be interpreted as relative movements in device-specific
* units used for navigation purposes. Pointer down/up indicates when the selection button
* is pressed/released.
*
* Use {@link #getMotionRange} to query the range of motion.
*/
public static final int SOURCE_CLASS_TRACKBALL = 0x00000004;
/**
* The input source is an absolute positioning device not associated with a display
* (unlike {@link #SOURCE_CLASS_POINTER}).
*
* A {@link MotionEvent} should be interpreted as absolute coordinates in
* device-specific surface units.
*
* Use {@link #getMotionRange} to query the range of positions.
*/
public static final int SOURCE_CLASS_POSITION = 0x00000008;
/**
* The input source is a joystick.
*
* A {@link MotionEvent} should be interpreted as absolute joystick movements.
*
* Use {@link #getMotionRange} to query the range of positions.
*/
public static final int SOURCE_CLASS_JOYSTICK = 0x00000010;
/** @hide */
@IntDef(flag = true, prefix = { "SOURCE_CLASS_" }, value = {
SOURCE_CLASS_NONE,
SOURCE_CLASS_BUTTON,
SOURCE_CLASS_POINTER,
SOURCE_CLASS_POINTER,
SOURCE_CLASS_TRACKBALL,
SOURCE_CLASS_POSITION,
SOURCE_CLASS_JOYSTICK
})
@Retention(RetentionPolicy.SOURCE)
@interface InputSourceClass {}
/**
* The input source is unknown.
*/
public static final int SOURCE_UNKNOWN = 0x00000000;
/**
* The input source is a keyboard.
*
* This source indicates pretty much anything that has buttons. Use
* {@link #getKeyboardType()} to determine whether the keyboard has alphabetic keys
* and can be used to enter text.
*
* @see #SOURCE_CLASS_BUTTON
*/
public static final int SOURCE_KEYBOARD = 0x00000100 | SOURCE_CLASS_BUTTON;
/**
* The input source is a DPad.
*
* @see #SOURCE_CLASS_BUTTON
*/
public static final int SOURCE_DPAD = 0x00000200 | SOURCE_CLASS_BUTTON;
/**
* The input source is a game pad.
* (It may also be a {@link #SOURCE_JOYSTICK}).
*
* @see #SOURCE_CLASS_BUTTON
*/
public static final int SOURCE_GAMEPAD = 0x00000400 | SOURCE_CLASS_BUTTON;
/**
* The input source is a touch screen pointing device.
*
* @see #SOURCE_CLASS_POINTER
*/
public static final int SOURCE_TOUCHSCREEN = 0x00001000 | SOURCE_CLASS_POINTER;
/**
* The input source is a mouse pointing device.
* This code is also used for other mouse-like pointing devices such as trackpads
* and trackpoints.
*
* @see #SOURCE_CLASS_POINTER
*/
public static final int SOURCE_MOUSE = 0x00002000 | SOURCE_CLASS_POINTER;
/**
* The input source is a stylus pointing device.
* <p>
* Note that this bit merely indicates that an input device is capable of obtaining
* input from a stylus. To determine whether a given touch event was produced
* by a stylus, examine the tool type returned by {@link MotionEvent#getToolType(int)}
* for each individual pointer.
* </p><p>
* A single touch event may multiple pointers with different tool types,
* such as an event that has one pointer with tool type
* {@link MotionEvent#TOOL_TYPE_FINGER} and another pointer with tool type
* {@link MotionEvent#TOOL_TYPE_STYLUS}. So it is important to examine
* the tool type of each pointer, regardless of the source reported
* by {@link MotionEvent#getSource()}.
* </p>
*
* @see #SOURCE_CLASS_POINTER
*/
public static final int SOURCE_STYLUS = 0x00004000 | SOURCE_CLASS_POINTER;
/**
* The input device is a Bluetooth stylus.
* <p>
* Note that this bit merely indicates that an input device is capable of
* obtaining input from a Bluetooth stylus. To determine whether a given
* touch event was produced by a stylus, examine the tool type returned by
* {@link MotionEvent#getToolType(int)} for each individual pointer.
* </p><p>
* A single touch event may multiple pointers with different tool types,
* such as an event that has one pointer with tool type
* {@link MotionEvent#TOOL_TYPE_FINGER} and another pointer with tool type
* {@link MotionEvent#TOOL_TYPE_STYLUS}. So it is important to examine
* the tool type of each pointer, regardless of the source reported
* by {@link MotionEvent#getSource()}.
* </p><p>
* A bluetooth stylus generally receives its pressure and button state
* information from the stylus itself, and derives the rest from another
* source. For example, a Bluetooth stylus used in conjunction with a
* touchscreen would derive its contact position and pointer size from the
* touchscreen and may not be any more accurate than other tools such as
* fingers.
* </p>
*
* @see #SOURCE_STYLUS
* @see #SOURCE_CLASS_POINTER
*/
public static final int SOURCE_BLUETOOTH_STYLUS =
0x00008000 | SOURCE_STYLUS;
/**
* The input source is a trackball.
*
* @see #SOURCE_CLASS_TRACKBALL
*/
public static final int SOURCE_TRACKBALL = 0x00010000 | SOURCE_CLASS_TRACKBALL;
/**
* The input source is a mouse device whose relative motions should be interpreted as
* navigation events.
*
* @see #SOURCE_CLASS_TRACKBALL
*/
public static final int SOURCE_MOUSE_RELATIVE = 0x00020000 | SOURCE_CLASS_TRACKBALL;
/**
* The input source is a touch pad or digitizer tablet that is not
* associated with a display (unlike {@link #SOURCE_TOUCHSCREEN}).
*
* @see #SOURCE_CLASS_POSITION
*/
public static final int SOURCE_TOUCHPAD = 0x00100000 | SOURCE_CLASS_POSITION;
/**
* The input source is a touch device whose motions should be interpreted as navigation events.
*
* For example, an upward swipe should be as an upward focus traversal in the same manner as
* pressing up on a D-Pad would be. Swipes to the left, right and down should be treated in a
* similar manner.
*
* @see #SOURCE_CLASS_NONE
*/
public static final int SOURCE_TOUCH_NAVIGATION = 0x00200000 | SOURCE_CLASS_NONE;
/**
* The input source is a rotating encoder device whose motions should be interpreted as akin to
* those of a scroll wheel.
*
* @see #SOURCE_CLASS_NONE
*/
public static final int SOURCE_ROTARY_ENCODER = 0x00400000 | SOURCE_CLASS_NONE;
/**
* The input source is a joystick.
* (It may also be a {@link #SOURCE_GAMEPAD}).
*
* @see #SOURCE_CLASS_JOYSTICK
*/
public static final int SOURCE_JOYSTICK = 0x01000000 | SOURCE_CLASS_JOYSTICK;
/**
* The input source is a device connected through HDMI-based bus.
*
* The key comes in through HDMI-CEC or MHL signal line, and is treated as if it were
* generated by a locally connected DPAD or keyboard.
*/
public static final int SOURCE_HDMI = 0x02000000 | SOURCE_CLASS_BUTTON;
/**
* A special input source constant that is used when filtering input devices
* to match devices that provide any type of input source.
*/
public static final int SOURCE_ANY = 0xffffff00;
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_X}.
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_X} instead.
*/
@Deprecated
public static final int MOTION_RANGE_X = MotionEvent.AXIS_X;
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_Y}.
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_Y} instead.
*/
@Deprecated
public static final int MOTION_RANGE_Y = MotionEvent.AXIS_Y;
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_PRESSURE}.
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_PRESSURE} instead.
*/
@Deprecated
public static final int MOTION_RANGE_PRESSURE = MotionEvent.AXIS_PRESSURE;
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_SIZE}.
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_SIZE} instead.
*/
@Deprecated
public static final int MOTION_RANGE_SIZE = MotionEvent.AXIS_SIZE;
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MAJOR}.
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_TOUCH_MAJOR} instead.
*/
@Deprecated
public static final int MOTION_RANGE_TOUCH_MAJOR = MotionEvent.AXIS_TOUCH_MAJOR;
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MINOR}.
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_TOUCH_MINOR} instead.
*/
@Deprecated
public static final int MOTION_RANGE_TOUCH_MINOR = MotionEvent.AXIS_TOUCH_MINOR;
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MAJOR}.
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_TOOL_MAJOR} instead.
*/
@Deprecated
public static final int MOTION_RANGE_TOOL_MAJOR = MotionEvent.AXIS_TOOL_MAJOR;
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MINOR}.
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_TOOL_MINOR} instead.
*/
@Deprecated
public static final int MOTION_RANGE_TOOL_MINOR = MotionEvent.AXIS_TOOL_MINOR;
/**
* Constant for retrieving the range of values for {@link MotionEvent#AXIS_ORIENTATION}.
*
* @see #getMotionRange
* @deprecated Use {@link MotionEvent#AXIS_ORIENTATION} instead.
*/
@Deprecated
public static final int MOTION_RANGE_ORIENTATION = MotionEvent.AXIS_ORIENTATION;
/**
* There is no keyboard.
*/
public static final int KEYBOARD_TYPE_NONE = 0;
/**
* The keyboard is not fully alphabetic. It may be a numeric keypad or an assortment
* of buttons that are not mapped as alphabetic keys suitable for text input.
*/
public static final int KEYBOARD_TYPE_NON_ALPHABETIC = 1;
/**
* The keyboard supports a complement of alphabetic keys.
*/
public static final int KEYBOARD_TYPE_ALPHABETIC = 2;
private static final int MAX_RANGES = 1000;
public static final @android.annotation.NonNull Parcelable.Creator<InputDevice> CREATOR =
new Parcelable.Creator<InputDevice>() {
public InputDevice createFromParcel(Parcel in) {
return new InputDevice(in);
}
public InputDevice[] newArray(int size) {
return new InputDevice[size];
}
};
// Called by native code.
@UnsupportedAppUsage
private InputDevice(int id, int generation, int controllerNumber, String name, int vendorId,
int productId, String descriptor, boolean isExternal, int sources, int keyboardType,
KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasMicrophone,
boolean hasButtonUnderPad) {
mId = id;
mGeneration = generation;
mControllerNumber = controllerNumber;
mName = name;
mVendorId = vendorId;
mProductId = productId;
mDescriptor = descriptor;
mIsExternal = isExternal;
mSources = sources;
mKeyboardType = keyboardType;
mKeyCharacterMap = keyCharacterMap;
mHasVibrator = hasVibrator;
mHasMicrophone = hasMicrophone;
mHasButtonUnderPad = hasButtonUnderPad;
mIdentifier = new InputDeviceIdentifier(descriptor, vendorId, productId);
}
private InputDevice(Parcel in) {
mId = in.readInt();
mGeneration = in.readInt();
mControllerNumber = in.readInt();
mName = in.readString();
mVendorId = in.readInt();
mProductId = in.readInt();
mDescriptor = in.readString();
mIsExternal = in.readInt() != 0;
mSources = in.readInt();
mKeyboardType = in.readInt();
mKeyCharacterMap = KeyCharacterMap.CREATOR.createFromParcel(in);
mHasVibrator = in.readInt() != 0;
mHasMicrophone = in.readInt() != 0;
mHasButtonUnderPad = in.readInt() != 0;
mIdentifier = new InputDeviceIdentifier(mDescriptor, mVendorId, mProductId);
int numRanges = in.readInt();
if (numRanges > MAX_RANGES) {
numRanges = MAX_RANGES;
}
for (int i = 0; i < numRanges; i++) {
addMotionRange(in.readInt(), in.readInt(), in.readFloat(), in.readFloat(),
in.readFloat(), in.readFloat(), in.readFloat());
}
}
/**
* Gets information about the input device with the specified id.
* @param id The device id.
* @return The input device or null if not found.
*/
public static InputDevice getDevice(int id) {
return InputManager.getInstance().getInputDevice(id);
}
/**
* Gets the ids of all input devices in the system.
* @return The input device ids.
*/
public static int[] getDeviceIds() {
return InputManager.getInstance().getInputDeviceIds();
}
/**
* Gets the input device id.
* <p>
* Each input device receives a unique id when it is first configured
* by the system. The input device id may change when the system is restarted or if the
* input device is disconnected, reconnected or reconfigured at any time.
* If you require a stable identifier for a device that persists across
* boots and reconfigurations, use {@link #getDescriptor()}.
* </p>
*
* @return The input device id.
*/
public int getId() {
return mId;
}
/**
* The controller number for a given input device.
* <p>
* Each gamepad or joystick is given a unique, positive controller number when initially
* configured by the system. This number may change due to events such as device disconnects /
* reconnects or user initiated reassignment. Any change in number will trigger an event that
* can be observed by registering an {@link InputManager.InputDeviceListener}.
* </p>
* <p>
* All input devices which are not gamepads or joysticks will be assigned a controller number
* of 0.
* </p>
*
* @return The controller number of the device.
*/
public int getControllerNumber() {
return mControllerNumber;
}
/**
* The set of identifying information for type of input device. This
* information can be used by the system to configure appropriate settings
* for the device.
*
* @return The identifier object for this device
* @hide
*/
public InputDeviceIdentifier getIdentifier() {
return mIdentifier;
}
/**
* Gets a generation number for this input device.
* The generation number is incremented whenever the device is reconfigured and its
* properties may have changed.
*
* @return The generation number.
*
* @hide
*/
public int getGeneration() {
return mGeneration;
}
/**
* Gets the vendor id for the given device, if available.
* <p>
* A vendor id uniquely identifies the company who manufactured the device. A value of 0 will
* be assigned where a vendor id is not available.
* </p>
*
* @return The vendor id of a given device
*/
public int getVendorId() {
return mVendorId;
}
/**
* Gets the product id for the given device, if available.
* <p>
* A product id uniquely identifies which product within the address space of a given vendor,
* identified by the device's vendor id. A value of 0 will be assigned where a product id is
* not available.
* </p>
*
* @return The product id of a given device
*/
public int getProductId() {
return mProductId;
}
/**
* Gets the input device descriptor, which is a stable identifier for an input device.
* <p>
* An input device descriptor uniquely identifies an input device. Its value
* is intended to be persistent across system restarts, and should not change even
* if the input device is disconnected, reconnected or reconfigured at any time.
* </p><p>
* It is possible for there to be multiple {@link InputDevice} instances that have the
* same input device descriptor. This might happen in situations where a single
* human input device registers multiple {@link InputDevice} instances (HID collections)
* that describe separate features of the device, such as a keyboard that also
* has a trackpad. Alternately, it may be that the input devices are simply
* indistinguishable, such as two keyboards made by the same manufacturer.
* </p><p>
* The input device descriptor returned by {@link #getDescriptor} should only be
* used when an application needs to remember settings associated with a particular
* input device. For all other purposes when referring to a logical
* {@link InputDevice} instance at runtime use the id returned by {@link #getId()}.
* </p>
*
* @return The input device descriptor.
*/
public String getDescriptor() {
return mDescriptor;
}
/**
* Returns true if the device is a virtual input device rather than a real one,
* such as the virtual keyboard (see {@link KeyCharacterMap#VIRTUAL_KEYBOARD}).
* <p>
* Virtual input devices are provided to implement system-level functionality
* and should not be seen or configured by users.
* </p>
*
* @return True if the device is virtual.
*
* @see KeyCharacterMap#VIRTUAL_KEYBOARD
*/
public boolean isVirtual() {
return mId < 0;
}
/**
* Returns true if the device is external (connected to USB or Bluetooth or some other
* peripheral bus), otherwise it is built-in.
*
* @return True if the device is external.
*/
public boolean isExternal() {
return mIsExternal;
}
/**
* Returns true if the device is a full keyboard.
*
* @return True if the device is a full keyboard.
*
* @hide
*/
public boolean isFullKeyboard() {
return (mSources & SOURCE_KEYBOARD) == SOURCE_KEYBOARD
&& mKeyboardType == KEYBOARD_TYPE_ALPHABETIC;
}
/**
* Gets the name of this input device.
* @return The input device name.
*/
public String getName() {
return mName;
}
/**
* Gets the input sources supported by this input device as a combined bitfield.
* @return The supported input sources.
*/
public int getSources() {
return mSources;
}
/**
* Determines whether the input device supports the given source or sources.
*
* @param source The input source or sources to check against. This can be a generic device
* type such as {@link InputDevice#SOURCE_MOUSE}, a more generic device class, such as
* {@link InputDevice#SOURCE_CLASS_POINTER}, or a combination of sources bitwise ORed together.
* @return Whether the device can produce all of the given sources.
*/
public boolean supportsSource(int source) {
return (mSources & source) == source;
}
/**
* Gets the keyboard type.
* @return The keyboard type.
*/
public int getKeyboardType() {
return mKeyboardType;
}
/**
* Gets the key character map associated with this input device.
* @return The key character map.
*/
public KeyCharacterMap getKeyCharacterMap() {
return mKeyCharacterMap;
}
/**
* Gets whether the device is capable of producing the list of keycodes.
* @param keys The list of android keycodes to check for.
* @return An array of booleans where each member specifies whether the device is capable of
* generating the keycode given by the corresponding value at the same index in the keys array.
*/
public boolean[] hasKeys(int... keys) {
return InputManager.getInstance().deviceHasKeys(mId, keys);
}
/**
* Gets information about the range of values for a particular {@link MotionEvent} axis.
* If the device supports multiple sources, the same axis may have different meanings
* for each source. Returns information about the first axis found for any source.
* To obtain information about the axis for a specific source, use
* {@link #getMotionRange(int, int)}.
*
* @param axis The axis constant.
* @return The range of values, or null if the requested axis is not
* supported by the device.
*
* @see MotionEvent#AXIS_X
* @see MotionEvent#AXIS_Y
*/
public MotionRange getMotionRange(int axis) {
final int numRanges = mMotionRanges.size();
for (int i = 0; i < numRanges; i++) {
final MotionRange range = mMotionRanges.get(i);
if (range.mAxis == axis) {
return range;
}
}
return null;
}
/**
* Gets information about the range of values for a particular {@link MotionEvent} axis
* used by a particular source on the device.
* If the device supports multiple sources, the same axis may have different meanings
* for each source.
*
* @param axis The axis constant.
* @param source The source for which to return information.
* @return The range of values, or null if the requested axis is not
* supported by the device.
*
* @see MotionEvent#AXIS_X
* @see MotionEvent#AXIS_Y
*/
public MotionRange getMotionRange(int axis, int source) {
final int numRanges = mMotionRanges.size();
for (int i = 0; i < numRanges; i++) {
final MotionRange range = mMotionRanges.get(i);
if (range.mAxis == axis && range.mSource == source) {
return range;
}
}
return null;
}
/**
* Gets the ranges for all axes supported by the device.
* @return The motion ranges for the device.
*
* @see #getMotionRange(int, int)
*/
public List<MotionRange> getMotionRanges() {
return mMotionRanges;
}
// Called from native code.
@UnsupportedAppUsage
private void addMotionRange(int axis, int source,
float min, float max, float flat, float fuzz, float resolution) {
mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz, resolution));
}
/**
* Gets the vibrator service associated with the device, if there is one.
* Even if the device does not have a vibrator, the result is never null.
* Use {@link Vibrator#hasVibrator} to determine whether a vibrator is
* present.
*
* Note that the vibrator associated with the device may be different from
* the system vibrator. To obtain an instance of the system vibrator instead, call
* {@link Context#getSystemService} with {@link Context#VIBRATOR_SERVICE} as argument.
*
* @return The vibrator service associated with the device, never null.
*/
public Vibrator getVibrator() {
synchronized (mMotionRanges) {
if (mVibrator == null) {
if (mHasVibrator) {
mVibrator = InputManager.getInstance().getInputDeviceVibrator(mId);
} else {
mVibrator = NullVibrator.getInstance();
}
}
return mVibrator;
}
}
/**
* Returns true if input device is enabled.
* @return Whether the input device is enabled.
*/
public boolean isEnabled() {
return InputManager.getInstance().isInputDeviceEnabled(mId);
}
/**
* Enables the input device.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.DISABLE_INPUT_DEVICE)
@TestApi
public void enable() {
InputManager.getInstance().enableInputDevice(mId);
}
/**
* Disables the input device.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.DISABLE_INPUT_DEVICE)
@TestApi
public void disable() {
InputManager.getInstance().disableInputDevice(mId);
}
/**
* Reports whether the device has a built-in microphone.
* @return Whether the device has a built-in microphone.
*/
public boolean hasMicrophone() {
return mHasMicrophone;
}
/**
* Reports whether the device has a button under its touchpad
* @return Whether the device has a button under its touchpad
* @hide
*/
public boolean hasButtonUnderPad() {
return mHasButtonUnderPad;
}
/**
* Sets the current pointer type.
* @param pointerType the type of the pointer icon.
* @hide
*/
public void setPointerType(int pointerType) {
InputManager.getInstance().setPointerIconType(pointerType);
}
/**
* Specifies the current custom pointer.
* @param icon the icon data.
* @hide
*/
public void setCustomPointerIcon(PointerIcon icon) {
InputManager.getInstance().setCustomPointerIcon(icon);
}
/**
* Provides information about the range of values for a particular {@link MotionEvent} axis.
*
* @see InputDevice#getMotionRange(int)
*/
public static final class MotionRange {
private int mAxis;
private int mSource;
private float mMin;
private float mMax;
private float mFlat;
private float mFuzz;
private float mResolution;
private MotionRange(int axis, int source, float min, float max, float flat, float fuzz,
float resolution) {
mAxis = axis;
mSource = source;
mMin = min;
mMax = max;
mFlat = flat;
mFuzz = fuzz;
mResolution = resolution;
}
/**
* Gets the axis id.
* @return The axis id.
*/
public int getAxis() {
return mAxis;
}
/**
* Gets the source for which the axis is defined.
* @return The source.
*/
public int getSource() {
return mSource;
}
/**
* Determines whether the event is from the given source.
*
* @param source The input source to check against. This can be a specific device type,
* such as {@link InputDevice#SOURCE_TOUCH_NAVIGATION}, or a more generic device class,
* such as {@link InputDevice#SOURCE_CLASS_POINTER}.
* @return Whether the event is from the given source.
*/
public boolean isFromSource(int source) {
return (getSource() & source) == source;
}
/**
* Gets the inclusive minimum value for the axis.
* @return The inclusive minimum value.
*/
public float getMin() {
return mMin;
}
/**
* Gets the inclusive maximum value for the axis.
* @return The inclusive maximum value.
*/
public float getMax() {
return mMax;
}
/**
* Gets the range of the axis (difference between maximum and minimum).
* @return The range of values.
*/
public float getRange() {
return mMax - mMin;
}
/**
* Gets the extent of the center flat position with respect to this axis.
* <p>
* For example, a flat value of 8 means that the center position is between -8 and +8.
* This value is mainly useful for calibrating self-centering devices.
* </p>
* @return The extent of the center flat position.
*/
public float getFlat() {
return mFlat;
}
/**
* Gets the error tolerance for input device measurements with respect to this axis.
* <p>
* For example, a value of 2 indicates that the measured value may be up to +/- 2 units
* away from the actual value due to noise and device sensitivity limitations.
* </p>
* @return The error tolerance.
*/
public float getFuzz() {
return mFuzz;
}
/**
* Gets the resolution for input device measurements with respect to this axis.
* @return The resolution in units per millimeter, or units per radian for rotational axes.
*/
public float getResolution() {
return mResolution;
}
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mId);
out.writeInt(mGeneration);
out.writeInt(mControllerNumber);
out.writeString(mName);
out.writeInt(mVendorId);
out.writeInt(mProductId);
out.writeString(mDescriptor);
out.writeInt(mIsExternal ? 1 : 0);
out.writeInt(mSources);
out.writeInt(mKeyboardType);
mKeyCharacterMap.writeToParcel(out, flags);
out.writeInt(mHasVibrator ? 1 : 0);
out.writeInt(mHasMicrophone ? 1 : 0);
out.writeInt(mHasButtonUnderPad ? 1 : 0);
final int numRanges = mMotionRanges.size();
out.writeInt(numRanges);
for (int i = 0; i < numRanges; i++) {
MotionRange range = mMotionRanges.get(i);
out.writeInt(range.mAxis);
out.writeInt(range.mSource);
out.writeFloat(range.mMin);
out.writeFloat(range.mMax);
out.writeFloat(range.mFlat);
out.writeFloat(range.mFuzz);
out.writeFloat(range.mResolution);
}
}
@Override
public int describeContents() {
return 0;
}
@Override
public String toString() {
StringBuilder description = new StringBuilder();
description.append("Input Device ").append(mId).append(": ").append(mName).append("\n");
description.append(" Descriptor: ").append(mDescriptor).append("\n");
description.append(" Generation: ").append(mGeneration).append("\n");
description.append(" Location: ").append(mIsExternal ? "external" : "built-in").append("\n");
description.append(" Keyboard Type: ");
switch (mKeyboardType) {
case KEYBOARD_TYPE_NONE:
description.append("none");
break;
case KEYBOARD_TYPE_NON_ALPHABETIC:
description.append("non-alphabetic");
break;
case KEYBOARD_TYPE_ALPHABETIC:
description.append("alphabetic");
break;
}
description.append("\n");
description.append(" Has Vibrator: ").append(mHasVibrator).append("\n");
description.append(" Has mic: ").append(mHasMicrophone).append("\n");
description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" (");
appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard");
appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad");
appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen");
appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse");
appendSourceDescriptionIfApplicable(description, SOURCE_STYLUS, "stylus");
appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball");
appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE_RELATIVE, "mouse_relative");
appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad");
appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK, "joystick");
appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad");
description.append(" )\n");
final int numAxes = mMotionRanges.size();
for (int i = 0; i < numAxes; i++) {
MotionRange range = mMotionRanges.get(i);
description.append(" ").append(MotionEvent.axisToString(range.mAxis));
description.append(": source=0x").append(Integer.toHexString(range.mSource));
description.append(" min=").append(range.mMin);
description.append(" max=").append(range.mMax);
description.append(" flat=").append(range.mFlat);
description.append(" fuzz=").append(range.mFuzz);
description.append(" resolution=").append(range.mResolution);
description.append("\n");
}
return description.toString();
}
private void appendSourceDescriptionIfApplicable(StringBuilder description, int source,
String sourceName) {
if ((mSources & source) == source) {
description.append(" ");
description.append(sourceName);
}
}
}