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