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