1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.content.Context;
20import android.hardware.input.InputDeviceIdentifier;
21import android.hardware.input.InputManager;
22import android.os.NullVibrator;
23import android.os.Parcel;
24import android.os.Parcelable;
25import android.os.Vibrator;
26
27import java.util.ArrayList;
28import java.util.List;
29
30/**
31 * Describes the capabilities of a particular input device.
32 * <p>
33 * Each input device may support multiple classes of input.  For example, a multi-function
34 * keyboard may compose the capabilities of a standard keyboard together with a track pad mouse
35 * or other pointing device.
36 * </p><p>
37 * Some input devices present multiple distinguishable sources of input.
38 * Applications can query the framework about the characteristics of each distinct source.
39 * </p><p>
40 * As a further wrinkle, different kinds of input sources uses different coordinate systems
41 * to describe motion events.  Refer to the comments on the input source constants for
42 * the appropriate interpretation.
43 * </p>
44 */
45public final class InputDevice implements Parcelable {
46    private final int mId;
47    private final int mGeneration;
48    private final int mControllerNumber;
49    private final String mName;
50    private final int mVendorId;
51    private final int mProductId;
52    private final String mDescriptor;
53    private final InputDeviceIdentifier mIdentifier;
54    private final boolean mIsExternal;
55    private final int mSources;
56    private final int mKeyboardType;
57    private final KeyCharacterMap mKeyCharacterMap;
58    private final boolean mHasVibrator;
59    private final boolean mHasMicrophone;
60    private final boolean mHasButtonUnderPad;
61    private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>();
62
63    private Vibrator mVibrator; // guarded by mMotionRanges during initialization
64
65    /**
66     * A mask for input source classes.
67     *
68     * Each distinct input source constant has one or more input source class bits set to
69     * specify the desired interpretation for its input events.
70     */
71    public static final int SOURCE_CLASS_MASK = 0x000000ff;
72
73    /**
74     * The input source has no class.
75     *
76     * It is up to the application to determine how to handle the device based on the device type.
77     */
78    public static final int SOURCE_CLASS_NONE = 0x00000000;
79
80    /**
81     * The input source has buttons or keys.
82     * Examples: {@link #SOURCE_KEYBOARD}, {@link #SOURCE_DPAD}.
83     *
84     * A {@link KeyEvent} should be interpreted as a button or key press.
85     *
86     * Use {@link #getKeyCharacterMap} to query the device's button and key mappings.
87     */
88    public static final int SOURCE_CLASS_BUTTON = 0x00000001;
89
90    /**
91     * The input source is a pointing device associated with a display.
92     * Examples: {@link #SOURCE_TOUCHSCREEN}, {@link #SOURCE_MOUSE}.
93     *
94     * A {@link MotionEvent} should be interpreted as absolute coordinates in
95     * display units according to the {@link View} hierarchy.  Pointer down/up indicated when
96     * the finger touches the display or when the selection button is pressed/released.
97     *
98     * Use {@link #getMotionRange} to query the range of the pointing device.  Some devices permit
99     * touches outside the display area so the effective range may be somewhat smaller or larger
100     * than the actual display size.
101     */
102    public static final int SOURCE_CLASS_POINTER = 0x00000002;
103
104    /**
105     * The input source is a trackball navigation device.
106     * Examples: {@link #SOURCE_TRACKBALL}.
107     *
108     * A {@link MotionEvent} should be interpreted as relative movements in device-specific
109     * units used for navigation purposes.  Pointer down/up indicates when the selection button
110     * is pressed/released.
111     *
112     * Use {@link #getMotionRange} to query the range of motion.
113     */
114    public static final int SOURCE_CLASS_TRACKBALL = 0x00000004;
115
116    /**
117     * The input source is an absolute positioning device not associated with a display
118     * (unlike {@link #SOURCE_CLASS_POINTER}).
119     *
120     * A {@link MotionEvent} should be interpreted as absolute coordinates in
121     * device-specific surface units.
122     *
123     * Use {@link #getMotionRange} to query the range of positions.
124     */
125    public static final int SOURCE_CLASS_POSITION = 0x00000008;
126
127    /**
128     * The input source is a joystick.
129     *
130     * A {@link MotionEvent} should be interpreted as absolute joystick movements.
131     *
132     * Use {@link #getMotionRange} to query the range of positions.
133     */
134    public static final int SOURCE_CLASS_JOYSTICK = 0x00000010;
135
136    /**
137     * The input source is unknown.
138     */
139    public static final int SOURCE_UNKNOWN = 0x00000000;
140
141    /**
142     * The input source is a keyboard.
143     *
144     * This source indicates pretty much anything that has buttons.  Use
145     * {@link #getKeyboardType()} to determine whether the keyboard has alphabetic keys
146     * and can be used to enter text.
147     *
148     * @see #SOURCE_CLASS_BUTTON
149     */
150    public static final int SOURCE_KEYBOARD = 0x00000100 | SOURCE_CLASS_BUTTON;
151
152    /**
153     * The input source is a DPad.
154     *
155     * @see #SOURCE_CLASS_BUTTON
156     */
157    public static final int SOURCE_DPAD = 0x00000200 | SOURCE_CLASS_BUTTON;
158
159    /**
160     * The input source is a game pad.
161     * (It may also be a {@link #SOURCE_JOYSTICK}).
162     *
163     * @see #SOURCE_CLASS_BUTTON
164     */
165    public static final int SOURCE_GAMEPAD = 0x00000400 | SOURCE_CLASS_BUTTON;
166
167    /**
168     * The input source is a touch screen pointing device.
169     *
170     * @see #SOURCE_CLASS_POINTER
171     */
172    public static final int SOURCE_TOUCHSCREEN = 0x00001000 | SOURCE_CLASS_POINTER;
173
174    /**
175     * The input source is a mouse pointing device.
176     * This code is also used for other mouse-like pointing devices such as trackpads
177     * and trackpoints.
178     *
179     * @see #SOURCE_CLASS_POINTER
180     */
181    public static final int SOURCE_MOUSE = 0x00002000 | SOURCE_CLASS_POINTER;
182
183    /**
184     * The input source is a stylus pointing device.
185     * <p>
186     * Note that this bit merely indicates that an input device is capable of obtaining
187     * input from a stylus.  To determine whether a given touch event was produced
188     * by a stylus, examine the tool type returned by {@link MotionEvent#getToolType(int)}
189     * for each individual pointer.
190     * </p><p>
191     * A single touch event may multiple pointers with different tool types,
192     * such as an event that has one pointer with tool type
193     * {@link MotionEvent#TOOL_TYPE_FINGER} and another pointer with tool type
194     * {@link MotionEvent#TOOL_TYPE_STYLUS}.  So it is important to examine
195     * the tool type of each pointer, regardless of the source reported
196     * by {@link MotionEvent#getSource()}.
197     * </p>
198     *
199     * @see #SOURCE_CLASS_POINTER
200     */
201    public static final int SOURCE_STYLUS = 0x00004000 | SOURCE_CLASS_POINTER;
202
203    /**
204     * The input device is a Bluetooth stylus.
205     * <p>
206     * Note that this bit merely indicates that an input device is capable of
207     * obtaining input from a Bluetooth stylus.  To determine whether a given
208     * touch event was produced by a stylus, examine the tool type returned by
209     * {@link MotionEvent#getToolType(int)} for each individual pointer.
210     * </p><p>
211     * A single touch event may multiple pointers with different tool types,
212     * such as an event that has one pointer with tool type
213     * {@link MotionEvent#TOOL_TYPE_FINGER} and another pointer with tool type
214     * {@link MotionEvent#TOOL_TYPE_STYLUS}.  So it is important to examine
215     * the tool type of each pointer, regardless of the source reported
216     * by {@link MotionEvent#getSource()}.
217     * </p><p>
218     * A bluetooth stylus generally receives its pressure and button state
219     * information from the stylus itself, and derives the rest from another
220     * source. For example, a Bluetooth stylus used in conjunction with a
221     * touchscreen would derive its contact position and pointer size from the
222     * touchscreen and may not be any more accurate than other tools such as
223     * fingers.
224     * </p>
225     *
226     * @see #SOURCE_STYLUS
227     * @see #SOURCE_CLASS_POINTER
228     */
229    public static final int SOURCE_BLUETOOTH_STYLUS =
230            0x00008000 | SOURCE_STYLUS;
231
232    /**
233     * The input source is a trackball.
234     *
235     * @see #SOURCE_CLASS_TRACKBALL
236     */
237    public static final int SOURCE_TRACKBALL = 0x00010000 | SOURCE_CLASS_TRACKBALL;
238
239    /**
240     * The input source is a mouse device whose relative motions should be interpreted as
241     * navigation events.
242     *
243     * @see #SOURCE_CLASS_TRACKBALL
244     */
245    public static final int SOURCE_MOUSE_RELATIVE = 0x00020000 | SOURCE_CLASS_TRACKBALL;
246
247    /**
248     * The input source is a touch pad or digitizer tablet that is not
249     * associated with a display (unlike {@link #SOURCE_TOUCHSCREEN}).
250     *
251     * @see #SOURCE_CLASS_POSITION
252     */
253    public static final int SOURCE_TOUCHPAD = 0x00100000 | SOURCE_CLASS_POSITION;
254
255    /**
256     * The input source is a touch device whose motions should be interpreted as navigation events.
257     *
258     * For example, an upward swipe should be as an upward focus traversal in the same manner as
259     * pressing up on a D-Pad would be. Swipes to the left, right and down should be treated in a
260     * similar manner.
261     *
262     * @see #SOURCE_CLASS_NONE
263     */
264    public static final int SOURCE_TOUCH_NAVIGATION = 0x00200000 | SOURCE_CLASS_NONE;
265
266    /**
267     * The input source is a rotating encoder device whose motions should be interpreted as akin to
268     * those of a scroll wheel.
269     *
270     * @see #SOURCE_CLASS_NONE
271     */
272    public static final int SOURCE_ROTARY_ENCODER = 0x00400000 | SOURCE_CLASS_NONE;
273
274    /**
275     * The input source is a joystick.
276     * (It may also be a {@link #SOURCE_GAMEPAD}).
277     *
278     * @see #SOURCE_CLASS_JOYSTICK
279     */
280    public static final int SOURCE_JOYSTICK = 0x01000000 | SOURCE_CLASS_JOYSTICK;
281
282    /**
283     * The input source is a device connected through HDMI-based bus.
284     *
285     * The key comes in through HDMI-CEC or MHL signal line, and is treated as if it were
286     * generated by a locally connected DPAD or keyboard.
287     */
288    public static final int SOURCE_HDMI = 0x02000000 | SOURCE_CLASS_BUTTON;
289
290    /**
291     * A special input source constant that is used when filtering input devices
292     * to match devices that provide any type of input source.
293     */
294    public static final int SOURCE_ANY = 0xffffff00;
295
296    /**
297     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_X}.
298     *
299     * @see #getMotionRange
300     * @deprecated Use {@link MotionEvent#AXIS_X} instead.
301     */
302    @Deprecated
303    public static final int MOTION_RANGE_X = MotionEvent.AXIS_X;
304
305    /**
306     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_Y}.
307     *
308     * @see #getMotionRange
309     * @deprecated Use {@link MotionEvent#AXIS_Y} instead.
310     */
311    @Deprecated
312    public static final int MOTION_RANGE_Y = MotionEvent.AXIS_Y;
313
314    /**
315     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_PRESSURE}.
316     *
317     * @see #getMotionRange
318     * @deprecated Use {@link MotionEvent#AXIS_PRESSURE} instead.
319     */
320    @Deprecated
321    public static final int MOTION_RANGE_PRESSURE = MotionEvent.AXIS_PRESSURE;
322
323    /**
324     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_SIZE}.
325     *
326     * @see #getMotionRange
327     * @deprecated Use {@link MotionEvent#AXIS_SIZE} instead.
328     */
329    @Deprecated
330    public static final int MOTION_RANGE_SIZE = MotionEvent.AXIS_SIZE;
331
332    /**
333     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MAJOR}.
334     *
335     * @see #getMotionRange
336     * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MAJOR} instead.
337     */
338    @Deprecated
339    public static final int MOTION_RANGE_TOUCH_MAJOR = MotionEvent.AXIS_TOUCH_MAJOR;
340
341    /**
342     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MINOR}.
343     *
344     * @see #getMotionRange
345     * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MINOR} instead.
346     */
347    @Deprecated
348    public static final int MOTION_RANGE_TOUCH_MINOR = MotionEvent.AXIS_TOUCH_MINOR;
349
350    /**
351     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MAJOR}.
352     *
353     * @see #getMotionRange
354     * @deprecated Use {@link MotionEvent#AXIS_TOOL_MAJOR} instead.
355     */
356    @Deprecated
357    public static final int MOTION_RANGE_TOOL_MAJOR = MotionEvent.AXIS_TOOL_MAJOR;
358
359    /**
360     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MINOR}.
361     *
362     * @see #getMotionRange
363     * @deprecated Use {@link MotionEvent#AXIS_TOOL_MINOR} instead.
364     */
365    @Deprecated
366    public static final int MOTION_RANGE_TOOL_MINOR = MotionEvent.AXIS_TOOL_MINOR;
367
368    /**
369     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_ORIENTATION}.
370     *
371     * @see #getMotionRange
372     * @deprecated Use {@link MotionEvent#AXIS_ORIENTATION} instead.
373     */
374    @Deprecated
375    public static final int MOTION_RANGE_ORIENTATION = MotionEvent.AXIS_ORIENTATION;
376
377    /**
378     * There is no keyboard.
379     */
380    public static final int KEYBOARD_TYPE_NONE = 0;
381
382    /**
383     * The keyboard is not fully alphabetic.  It may be a numeric keypad or an assortment
384     * of buttons that are not mapped as alphabetic keys suitable for text input.
385     */
386    public static final int KEYBOARD_TYPE_NON_ALPHABETIC = 1;
387
388    /**
389     * The keyboard supports a complement of alphabetic keys.
390     */
391    public static final int KEYBOARD_TYPE_ALPHABETIC = 2;
392
393    private static final int MAX_RANGES = 1000;
394
395    public static final Parcelable.Creator<InputDevice> CREATOR =
396            new Parcelable.Creator<InputDevice>() {
397        public InputDevice createFromParcel(Parcel in) {
398            return new InputDevice(in);
399        }
400        public InputDevice[] newArray(int size) {
401            return new InputDevice[size];
402        }
403    };
404
405    // Called by native code.
406    private InputDevice(int id, int generation, int controllerNumber, String name, int vendorId,
407            int productId, String descriptor, boolean isExternal, int sources, int keyboardType,
408            KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasMicrophone,
409            boolean hasButtonUnderPad) {
410        mId = id;
411        mGeneration = generation;
412        mControllerNumber = controllerNumber;
413        mName = name;
414        mVendorId = vendorId;
415        mProductId = productId;
416        mDescriptor = descriptor;
417        mIsExternal = isExternal;
418        mSources = sources;
419        mKeyboardType = keyboardType;
420        mKeyCharacterMap = keyCharacterMap;
421        mHasVibrator = hasVibrator;
422        mHasMicrophone = hasMicrophone;
423        mHasButtonUnderPad = hasButtonUnderPad;
424        mIdentifier = new InputDeviceIdentifier(descriptor, vendorId, productId);
425    }
426
427    private InputDevice(Parcel in) {
428        mId = in.readInt();
429        mGeneration = in.readInt();
430        mControllerNumber = in.readInt();
431        mName = in.readString();
432        mVendorId = in.readInt();
433        mProductId = in.readInt();
434        mDescriptor = in.readString();
435        mIsExternal = in.readInt() != 0;
436        mSources = in.readInt();
437        mKeyboardType = in.readInt();
438        mKeyCharacterMap = KeyCharacterMap.CREATOR.createFromParcel(in);
439        mHasVibrator = in.readInt() != 0;
440        mHasMicrophone = in.readInt() != 0;
441        mHasButtonUnderPad = in.readInt() != 0;
442        mIdentifier = new InputDeviceIdentifier(mDescriptor, mVendorId, mProductId);
443
444        int numRanges = in.readInt();
445        if (numRanges > MAX_RANGES) {
446            numRanges = MAX_RANGES;
447        }
448
449        for (int i = 0; i < numRanges; i++) {
450            addMotionRange(in.readInt(), in.readInt(), in.readFloat(), in.readFloat(),
451                    in.readFloat(), in.readFloat(), in.readFloat());
452        }
453    }
454
455    /**
456     * Gets information about the input device with the specified id.
457     * @param id The device id.
458     * @return The input device or null if not found.
459     */
460    public static InputDevice getDevice(int id) {
461        return InputManager.getInstance().getInputDevice(id);
462    }
463
464    /**
465     * Gets the ids of all input devices in the system.
466     * @return The input device ids.
467     */
468    public static int[] getDeviceIds() {
469        return InputManager.getInstance().getInputDeviceIds();
470    }
471
472    /**
473     * Gets the input device id.
474     * <p>
475     * Each input device receives a unique id when it is first configured
476     * by the system.  The input device id may change when the system is restarted or if the
477     * input device is disconnected, reconnected or reconfigured at any time.
478     * If you require a stable identifier for a device that persists across
479     * boots and reconfigurations, use {@link #getDescriptor()}.
480     * </p>
481     *
482     * @return The input device id.
483     */
484    public int getId() {
485        return mId;
486    }
487
488    /**
489     * The controller number for a given input device.
490     * <p>
491     * Each gamepad or joystick is given a unique, positive controller number when initially
492     * configured by the system. This number may change due to events such as device disconnects /
493     * reconnects or user initiated reassignment. Any change in number will trigger an event that
494     * can be observed by registering an {@link InputManager.InputDeviceListener}.
495     * </p>
496     * <p>
497     * All input devices which are not gamepads or joysticks will be assigned a controller number
498     * of 0.
499     * </p>
500     *
501     * @return The controller number of the device.
502     */
503    public int getControllerNumber() {
504        return mControllerNumber;
505    }
506
507    /**
508     * The set of identifying information for type of input device. This
509     * information can be used by the system to configure appropriate settings
510     * for the device.
511     *
512     * @return The identifier object for this device
513     * @hide
514     */
515    public InputDeviceIdentifier getIdentifier() {
516        return mIdentifier;
517    }
518
519    /**
520     * Gets a generation number for this input device.
521     * The generation number is incremented whenever the device is reconfigured and its
522     * properties may have changed.
523     *
524     * @return The generation number.
525     *
526     * @hide
527     */
528    public int getGeneration() {
529        return mGeneration;
530    }
531
532    /**
533     * Gets the vendor id for the given device, if available.
534     * <p>
535     * A vendor id uniquely identifies the company who manufactured the device. A value of 0 will
536     * be assigned where a vendor id is not available.
537     * </p>
538     *
539     * @return The vendor id of a given device
540     */
541    public int getVendorId() {
542        return mVendorId;
543    }
544
545    /**
546     * Gets the product id for the given device, if available.
547     * <p>
548     * A product id uniquely identifies which product within the address space of a given vendor,
549     * identified by the device's vendor id. A value of 0 will be assigned where a product id is
550     * not available.
551     * </p>
552     *
553     * @return The product id of a given device
554     */
555    public int getProductId() {
556        return mProductId;
557    }
558
559    /**
560     * Gets the input device descriptor, which is a stable identifier for an input device.
561     * <p>
562     * An input device descriptor uniquely identifies an input device.  Its value
563     * is intended to be persistent across system restarts, and should not change even
564     * if the input device is disconnected, reconnected or reconfigured at any time.
565     * </p><p>
566     * It is possible for there to be multiple {@link InputDevice} instances that have the
567     * same input device descriptor.  This might happen in situations where a single
568     * human input device registers multiple {@link InputDevice} instances (HID collections)
569     * that describe separate features of the device, such as a keyboard that also
570     * has a trackpad.  Alternately, it may be that the input devices are simply
571     * indistinguishable, such as two keyboards made by the same manufacturer.
572     * </p><p>
573     * The input device descriptor returned by {@link #getDescriptor} should only be
574     * used when an application needs to remember settings associated with a particular
575     * input device.  For all other purposes when referring to a logical
576     * {@link InputDevice} instance at runtime use the id returned by {@link #getId()}.
577     * </p>
578     *
579     * @return The input device descriptor.
580     */
581    public String getDescriptor() {
582        return mDescriptor;
583    }
584
585    /**
586     * Returns true if the device is a virtual input device rather than a real one,
587     * such as the virtual keyboard (see {@link KeyCharacterMap#VIRTUAL_KEYBOARD}).
588     * <p>
589     * Virtual input devices are provided to implement system-level functionality
590     * and should not be seen or configured by users.
591     * </p>
592     *
593     * @return True if the device is virtual.
594     *
595     * @see KeyCharacterMap#VIRTUAL_KEYBOARD
596     */
597    public boolean isVirtual() {
598        return mId < 0;
599    }
600
601    /**
602     * Returns true if the device is external (connected to USB or Bluetooth or some other
603     * peripheral bus), otherwise it is built-in.
604     *
605     * @return True if the device is external.
606     *
607     * @hide
608     */
609    public boolean isExternal() {
610        return mIsExternal;
611    }
612
613    /**
614     * Returns true if the device is a full keyboard.
615     *
616     * @return True if the device is a full keyboard.
617     *
618     * @hide
619     */
620    public boolean isFullKeyboard() {
621        return (mSources & SOURCE_KEYBOARD) == SOURCE_KEYBOARD
622                && mKeyboardType == KEYBOARD_TYPE_ALPHABETIC;
623    }
624
625    /**
626     * Gets the name of this input device.
627     * @return The input device name.
628     */
629    public String getName() {
630        return mName;
631    }
632
633    /**
634     * Gets the input sources supported by this input device as a combined bitfield.
635     * @return The supported input sources.
636     */
637    public int getSources() {
638        return mSources;
639    }
640
641    /**
642     * Determines whether the input device supports the given source or sources.
643     *
644     * @param source The input source or sources to check against. This can be a generic device
645     * type such as {@link InputDevice#SOURCE_MOUSE}, a more generic device class, such as
646     * {@link InputDevice#SOURCE_CLASS_POINTER}, or a combination of sources bitwise ORed together.
647     * @return Whether the device can produce all of the given sources.
648     */
649    public boolean supportsSource(int source) {
650        return (mSources & source) == source;
651    }
652
653    /**
654     * Gets the keyboard type.
655     * @return The keyboard type.
656     */
657    public int getKeyboardType() {
658        return mKeyboardType;
659    }
660
661    /**
662     * Gets the key character map associated with this input device.
663     * @return The key character map.
664     */
665    public KeyCharacterMap getKeyCharacterMap() {
666        return mKeyCharacterMap;
667    }
668
669    /**
670     * Gets whether the device is capable of producing the list of keycodes.
671     * @param keys The list of android keycodes to check for.
672     * @return An array of booleans where each member specifies whether the device is capable of
673     * generating the keycode given by the corresponding value at the same index in the keys array.
674     */
675    public boolean[] hasKeys(int... keys) {
676        return InputManager.getInstance().deviceHasKeys(mId, keys);
677    }
678
679    /**
680     * Gets information about the range of values for a particular {@link MotionEvent} axis.
681     * If the device supports multiple sources, the same axis may have different meanings
682     * for each source.  Returns information about the first axis found for any source.
683     * To obtain information about the axis for a specific source, use
684     * {@link #getMotionRange(int, int)}.
685     *
686     * @param axis The axis constant.
687     * @return The range of values, or null if the requested axis is not
688     * supported by the device.
689     *
690     * @see MotionEvent#AXIS_X
691     * @see MotionEvent#AXIS_Y
692     */
693    public MotionRange getMotionRange(int axis) {
694        final int numRanges = mMotionRanges.size();
695        for (int i = 0; i < numRanges; i++) {
696            final MotionRange range = mMotionRanges.get(i);
697            if (range.mAxis == axis) {
698                return range;
699            }
700        }
701        return null;
702    }
703
704    /**
705     * Gets information about the range of values for a particular {@link MotionEvent} axis
706     * used by a particular source on the device.
707     * If the device supports multiple sources, the same axis may have different meanings
708     * for each source.
709     *
710     * @param axis The axis constant.
711     * @param source The source for which to return information.
712     * @return The range of values, or null if the requested axis is not
713     * supported by the device.
714     *
715     * @see MotionEvent#AXIS_X
716     * @see MotionEvent#AXIS_Y
717     */
718    public MotionRange getMotionRange(int axis, int source) {
719        final int numRanges = mMotionRanges.size();
720        for (int i = 0; i < numRanges; i++) {
721            final MotionRange range = mMotionRanges.get(i);
722            if (range.mAxis == axis && range.mSource == source) {
723                return range;
724            }
725        }
726        return null;
727    }
728
729    /**
730     * Gets the ranges for all axes supported by the device.
731     * @return The motion ranges for the device.
732     *
733     * @see #getMotionRange(int, int)
734     */
735    public List<MotionRange> getMotionRanges() {
736        return mMotionRanges;
737    }
738
739    // Called from native code.
740    private void addMotionRange(int axis, int source,
741            float min, float max, float flat, float fuzz, float resolution) {
742        mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz, resolution));
743    }
744
745    /**
746     * Gets the vibrator service associated with the device, if there is one.
747     * Even if the device does not have a vibrator, the result is never null.
748     * Use {@link Vibrator#hasVibrator} to determine whether a vibrator is
749     * present.
750     *
751     * Note that the vibrator associated with the device may be different from
752     * the system vibrator.  To obtain an instance of the system vibrator instead, call
753     * {@link Context#getSystemService} with {@link Context#VIBRATOR_SERVICE} as argument.
754     *
755     * @return The vibrator service associated with the device, never null.
756     */
757    public Vibrator getVibrator() {
758        synchronized (mMotionRanges) {
759            if (mVibrator == null) {
760                if (mHasVibrator) {
761                    mVibrator = InputManager.getInstance().getInputDeviceVibrator(mId);
762                } else {
763                    mVibrator = NullVibrator.getInstance();
764                }
765            }
766            return mVibrator;
767        }
768    }
769
770    /**
771     * Reports whether the device has a built-in microphone.
772     * @return Whether the device has a built-in microphone.
773     */
774    public boolean hasMicrophone() {
775        return mHasMicrophone;
776    }
777
778    /**
779     * Reports whether the device has a button under its touchpad
780     * @return Whether the device has a button under its touchpad
781     * @hide
782     */
783    public boolean hasButtonUnderPad() {
784        return mHasButtonUnderPad;
785    }
786
787    /**
788     * Sets the current pointer type.
789     * @param pointerType the type of the pointer icon.
790     * @hide
791     */
792    public void setPointerType(int pointerType) {
793        InputManager.getInstance().setPointerIconType(pointerType);
794    }
795
796    /**
797     * Specifies the current custom pointer.
798     * @param icon the icon data.
799     * @hide
800     */
801    public void setCustomPointerIcon(PointerIcon icon) {
802        InputManager.getInstance().setCustomPointerIcon(icon);
803    }
804
805    /**
806     * Provides information about the range of values for a particular {@link MotionEvent} axis.
807     *
808     * @see InputDevice#getMotionRange(int)
809     */
810    public static final class MotionRange {
811        private int mAxis;
812        private int mSource;
813        private float mMin;
814        private float mMax;
815        private float mFlat;
816        private float mFuzz;
817        private float mResolution;
818
819        private MotionRange(int axis, int source, float min, float max, float flat, float fuzz,
820                float resolution) {
821            mAxis = axis;
822            mSource = source;
823            mMin = min;
824            mMax = max;
825            mFlat = flat;
826            mFuzz = fuzz;
827            mResolution = resolution;
828        }
829
830        /**
831         * Gets the axis id.
832         * @return The axis id.
833         */
834        public int getAxis() {
835            return mAxis;
836        }
837
838        /**
839         * Gets the source for which the axis is defined.
840         * @return The source.
841         */
842        public int getSource() {
843            return mSource;
844        }
845
846
847        /**
848         * Determines whether the event is from the given source.
849         *
850         * @param source The input source to check against. This can be a specific device type,
851         * such as {@link InputDevice#SOURCE_TOUCH_NAVIGATION}, or a more generic device class,
852         * such as {@link InputDevice#SOURCE_CLASS_POINTER}.
853         * @return Whether the event is from the given source.
854         */
855        public boolean isFromSource(int source) {
856            return (getSource() & source) == source;
857        }
858
859        /**
860         * Gets the inclusive minimum value for the axis.
861         * @return The inclusive minimum value.
862         */
863        public float getMin() {
864            return mMin;
865        }
866
867        /**
868         * Gets the inclusive maximum value for the axis.
869         * @return The inclusive maximum value.
870         */
871        public float getMax() {
872            return mMax;
873        }
874
875        /**
876         * Gets the range of the axis (difference between maximum and minimum).
877         * @return The range of values.
878         */
879        public float getRange() {
880            return mMax - mMin;
881        }
882
883        /**
884         * Gets the extent of the center flat position with respect to this axis.
885         * <p>
886         * For example, a flat value of 8 means that the center position is between -8 and +8.
887         * This value is mainly useful for calibrating self-centering devices.
888         * </p>
889         * @return The extent of the center flat position.
890         */
891        public float getFlat() {
892            return mFlat;
893        }
894
895        /**
896         * Gets the error tolerance for input device measurements with respect to this axis.
897         * <p>
898         * For example, a value of 2 indicates that the measured value may be up to +/- 2 units
899         * away from the actual value due to noise and device sensitivity limitations.
900         * </p>
901         * @return The error tolerance.
902         */
903        public float getFuzz() {
904            return mFuzz;
905        }
906
907        /**
908         * Gets the resolution for input device measurements with respect to this axis.
909         * @return The resolution in units per millimeter, or units per radian for rotational axes.
910         */
911        public float getResolution() {
912            return mResolution;
913        }
914    }
915
916    @Override
917    public void writeToParcel(Parcel out, int flags) {
918        out.writeInt(mId);
919        out.writeInt(mGeneration);
920        out.writeInt(mControllerNumber);
921        out.writeString(mName);
922        out.writeInt(mVendorId);
923        out.writeInt(mProductId);
924        out.writeString(mDescriptor);
925        out.writeInt(mIsExternal ? 1 : 0);
926        out.writeInt(mSources);
927        out.writeInt(mKeyboardType);
928        mKeyCharacterMap.writeToParcel(out, flags);
929        out.writeInt(mHasVibrator ? 1 : 0);
930        out.writeInt(mHasMicrophone ? 1 : 0);
931        out.writeInt(mHasButtonUnderPad ? 1 : 0);
932
933        final int numRanges = mMotionRanges.size();
934        out.writeInt(numRanges);
935        for (int i = 0; i < numRanges; i++) {
936            MotionRange range = mMotionRanges.get(i);
937            out.writeInt(range.mAxis);
938            out.writeInt(range.mSource);
939            out.writeFloat(range.mMin);
940            out.writeFloat(range.mMax);
941            out.writeFloat(range.mFlat);
942            out.writeFloat(range.mFuzz);
943            out.writeFloat(range.mResolution);
944        }
945    }
946
947    @Override
948    public int describeContents() {
949        return 0;
950    }
951
952    @Override
953    public String toString() {
954        StringBuilder description = new StringBuilder();
955        description.append("Input Device ").append(mId).append(": ").append(mName).append("\n");
956        description.append("  Descriptor: ").append(mDescriptor).append("\n");
957        description.append("  Generation: ").append(mGeneration).append("\n");
958        description.append("  Location: ").append(mIsExternal ? "external" : "built-in").append("\n");
959
960        description.append("  Keyboard Type: ");
961        switch (mKeyboardType) {
962            case KEYBOARD_TYPE_NONE:
963                description.append("none");
964                break;
965            case KEYBOARD_TYPE_NON_ALPHABETIC:
966                description.append("non-alphabetic");
967                break;
968            case KEYBOARD_TYPE_ALPHABETIC:
969                description.append("alphabetic");
970                break;
971        }
972        description.append("\n");
973
974        description.append("  Has Vibrator: ").append(mHasVibrator).append("\n");
975
976        description.append("  Has mic: ").append(mHasMicrophone).append("\n");
977
978        description.append("  Sources: 0x").append(Integer.toHexString(mSources)).append(" (");
979        appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard");
980        appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad");
981        appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen");
982        appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse");
983        appendSourceDescriptionIfApplicable(description, SOURCE_STYLUS, "stylus");
984        appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball");
985        appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE_RELATIVE, "mouse_relative");
986        appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad");
987        appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK, "joystick");
988        appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad");
989        description.append(" )\n");
990
991        final int numAxes = mMotionRanges.size();
992        for (int i = 0; i < numAxes; i++) {
993            MotionRange range = mMotionRanges.get(i);
994            description.append("    ").append(MotionEvent.axisToString(range.mAxis));
995            description.append(": source=0x").append(Integer.toHexString(range.mSource));
996            description.append(" min=").append(range.mMin);
997            description.append(" max=").append(range.mMax);
998            description.append(" flat=").append(range.mFlat);
999            description.append(" fuzz=").append(range.mFuzz);
1000            description.append(" resolution=").append(range.mResolution);
1001            description.append("\n");
1002        }
1003        return description.toString();
1004    }
1005
1006    private void appendSourceDescriptionIfApplicable(StringBuilder description, int source,
1007            String sourceName) {
1008        if ((mSources & source) == source) {
1009            description.append(" ");
1010            description.append(sourceName);
1011        }
1012    }
1013}
1014