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