InputDevice.java revision efd3266b719eed5f1b217021c0a9e76e4b274b06
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;
22import android.os.ServiceManager;
23
24import java.util.ArrayList;
25import java.util.List;
26
27/**
28 * Describes the capabilities of a particular input device.
29 * <p>
30 * Each input device may support multiple classes of input.  For example, a multifunction
31 * keyboard may compose the capabilities of a standard keyboard together with a track pad mouse
32 * or other pointing device.
33 * </p><p>
34 * Some input devices present multiple distinguishable sources of input.
35 * Applications can query the framework about the characteristics of each distinct source.
36 * </p><p>
37 * As a further wrinkle, different kinds of input sources uses different coordinate systems
38 * to describe motion events.  Refer to the comments on the input source constants for
39 * the appropriate interpretation.
40 * </p>
41 */
42public final class InputDevice implements Parcelable {
43    private int mId;
44    private String mName;
45    private int mSources;
46    private int mKeyboardType;
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     * @see #SOURCE_CLASS_BUTTON
123     */
124    public static final int SOURCE_KEYBOARD = 0x00000100 | SOURCE_CLASS_BUTTON;
125
126    /**
127     * The input source is a DPad.
128     *
129     * @see #SOURCE_CLASS_BUTTON
130     */
131    public static final int SOURCE_DPAD = 0x00000200 | SOURCE_CLASS_BUTTON;
132
133    /**
134     * The input source is a game pad.
135     * (It may also be a {@link #SOURCE_JOYSTICK}).
136     *
137     * @see #SOURCE_CLASS_BUTTON
138     */
139    public static final int SOURCE_GAMEPAD = 0x00000400 | SOURCE_CLASS_BUTTON;
140
141    /**
142     * The input source is a touch screen pointing device.
143     *
144     * @see #SOURCE_CLASS_POINTER
145     */
146    public static final int SOURCE_TOUCHSCREEN = 0x00001000 | SOURCE_CLASS_POINTER;
147
148    /**
149     * The input source is a mouse pointing device.
150     * This code is also used for other mouse-like pointing devices such as trackpads
151     * and trackpoints.
152     *
153     * @see #SOURCE_CLASS_POINTER
154     */
155    public static final int SOURCE_MOUSE = 0x00002000 | SOURCE_CLASS_POINTER;
156
157    /**
158     * The input source is a trackball.
159     *
160     * @see #SOURCE_CLASS_TRACKBALL
161     */
162    public static final int SOURCE_TRACKBALL = 0x00010000 | SOURCE_CLASS_TRACKBALL;
163
164    /**
165     * The input source is a touch pad or digitizer tablet that is not
166     * associated with a display (unlike {@link #SOURCE_TOUCHSCREEN}).
167     *
168     * @see #SOURCE_CLASS_POSITION
169     */
170    public static final int SOURCE_TOUCHPAD = 0x00100000 | SOURCE_CLASS_POSITION;
171
172    /**
173     * The input source is a joystick.
174     * (It may also be a {@link #SOURCE_GAMEPAD}).
175     *
176     * @see #SOURCE_CLASS_JOYSTICK
177     */
178    public static final int SOURCE_JOYSTICK = 0x01000000 | SOURCE_CLASS_JOYSTICK;
179
180    /**
181     * A special input source constant that is used when filtering input devices
182     * to match devices that provide any type of input source.
183     */
184    public static final int SOURCE_ANY = 0xffffff00;
185
186    /**
187     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_X}.
188     *
189     * @see #getMotionRange
190     * @deprecated Use {@link MotionEvent#AXIS_X} instead.
191     */
192    @Deprecated
193    public static final int MOTION_RANGE_X = MotionEvent.AXIS_X;
194
195    /**
196     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_Y}.
197     *
198     * @see #getMotionRange
199     * @deprecated Use {@link MotionEvent#AXIS_Y} instead.
200     */
201    @Deprecated
202    public static final int MOTION_RANGE_Y = MotionEvent.AXIS_Y;
203
204    /**
205     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_PRESSURE}.
206     *
207     * @see #getMotionRange
208     * @deprecated Use {@link MotionEvent#AXIS_PRESSURE} instead.
209     */
210    @Deprecated
211    public static final int MOTION_RANGE_PRESSURE = MotionEvent.AXIS_PRESSURE;
212
213    /**
214     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_SIZE}.
215     *
216     * @see #getMotionRange
217     * @deprecated Use {@link MotionEvent#AXIS_SIZE} instead.
218     */
219    @Deprecated
220    public static final int MOTION_RANGE_SIZE = MotionEvent.AXIS_SIZE;
221
222    /**
223     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MAJOR}.
224     *
225     * @see #getMotionRange
226     * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MAJOR} instead.
227     */
228    @Deprecated
229    public static final int MOTION_RANGE_TOUCH_MAJOR = MotionEvent.AXIS_TOUCH_MAJOR;
230
231    /**
232     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MINOR}.
233     *
234     * @see #getMotionRange
235     * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MINOR} instead.
236     */
237    @Deprecated
238    public static final int MOTION_RANGE_TOUCH_MINOR = MotionEvent.AXIS_TOUCH_MINOR;
239
240    /**
241     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MAJOR}.
242     *
243     * @see #getMotionRange
244     * @deprecated Use {@link MotionEvent#AXIS_TOOL_MAJOR} instead.
245     */
246    @Deprecated
247    public static final int MOTION_RANGE_TOOL_MAJOR = MotionEvent.AXIS_TOOL_MAJOR;
248
249    /**
250     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MINOR}.
251     *
252     * @see #getMotionRange
253     * @deprecated Use {@link MotionEvent#AXIS_TOOL_MINOR} instead.
254     */
255    @Deprecated
256    public static final int MOTION_RANGE_TOOL_MINOR = MotionEvent.AXIS_TOOL_MINOR;
257
258    /**
259     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_ORIENTATION}.
260     *
261     * @see #getMotionRange
262     * @deprecated Use {@link MotionEvent#AXIS_ORIENTATION} instead.
263     */
264    @Deprecated
265    public static final int MOTION_RANGE_ORIENTATION = MotionEvent.AXIS_ORIENTATION;
266
267    /**
268     * There is no keyboard.
269     */
270    public static final int KEYBOARD_TYPE_NONE = 0;
271
272    /**
273     * The keyboard is not fully alphabetic.  It may be a numeric keypad or an assortment
274     * of buttons that are not mapped as alphabetic keys suitable for text input.
275     */
276    public static final int KEYBOARD_TYPE_NON_ALPHABETIC = 1;
277
278    /**
279     * The keyboard supports a complement of alphabetic keys.
280     */
281    public static final int KEYBOARD_TYPE_ALPHABETIC = 2;
282
283    // Called by native code.
284    private InputDevice() {
285    }
286
287    /**
288     * Gets information about the input device with the specified id.
289     * @param id The device id.
290     * @return The input device or null if not found.
291     */
292    public static InputDevice getDevice(int id) {
293        IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
294        try {
295            return wm.getInputDevice(id);
296        } catch (RemoteException ex) {
297            throw new RuntimeException(
298                    "Could not get input device information from Window Manager.", ex);
299        }
300    }
301
302    /**
303     * Gets the ids of all input devices in the system.
304     * @return The input device ids.
305     */
306    public static int[] getDeviceIds() {
307        IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
308        try {
309            return wm.getInputDeviceIds();
310        } catch (RemoteException ex) {
311            throw new RuntimeException(
312                    "Could not get input device ids from Window Manager.", ex);
313        }
314    }
315
316    /**
317     * Gets the input device id.
318     * @return The input device id.
319     */
320    public int getId() {
321        return mId;
322    }
323
324    /**
325     * Gets the name of this input device.
326     * @return The input device name.
327     */
328    public String getName() {
329        return mName;
330    }
331
332    /**
333     * Gets the input sources supported by this input device as a combined bitfield.
334     * @return The supported input sources.
335     */
336    public int getSources() {
337        return mSources;
338    }
339
340    /**
341     * Gets the keyboard type.
342     * @return The keyboard type.
343     */
344    public int getKeyboardType() {
345        return mKeyboardType;
346    }
347
348    /**
349     * Gets the key character map associated with this input device.
350     * @return The key character map.
351     */
352    public KeyCharacterMap getKeyCharacterMap() {
353        return KeyCharacterMap.load(mId);
354    }
355
356    /**
357     * Gets information about the range of values for a particular {@link MotionEvent} axis.
358     * If the device supports multiple sources, the same axis may have different meanings
359     * for each source.  Returns information about the first axis found for any source.
360     * To obtain information about the axis for a specific source, use
361     * {@link #getMotionRange(int, int)}.
362     *
363     * @param axis The axis constant.
364     * @return The range of values, or null if the requested axis is not
365     * supported by the device.
366     *
367     * @see MotionEvent#AXIS_X
368     * @see MotionEvent#AXIS_Y
369     * @see #getSupportedAxes()
370     */
371    public MotionRange getMotionRange(int axis) {
372        final int numRanges = mMotionRanges.size();
373        for (int i = 0; i < numRanges; i++) {
374            final MotionRange range = mMotionRanges.get(i);
375            if (range.mAxis == axis) {
376                return range;
377            }
378        }
379        return null;
380    }
381
382    /**
383     * Gets information about the range of values for a particular {@link MotionEvent} axis
384     * used by a particular source on the device.
385     * If the device supports multiple sources, the same axis may have different meanings
386     * for each source.
387     *
388     * @param axis The axis constant.
389     * @param source The source for which to return information.
390     * @return The range of values, or null if the requested axis is not
391     * supported by the device.
392     *
393     * @see MotionEvent#AXIS_X
394     * @see MotionEvent#AXIS_Y
395     * @see #getSupportedAxes()
396     */
397    public MotionRange getMotionRange(int axis, int source) {
398        final int numRanges = mMotionRanges.size();
399        for (int i = 0; i < numRanges; i++) {
400            final MotionRange range = mMotionRanges.get(i);
401            if (range.mAxis == axis && range.mSource == source) {
402                return range;
403            }
404        }
405        return null;
406    }
407
408    /**
409     * Gets the ranges for all axes supported by the device.
410     * @return The motion ranges for the device.
411     *
412     * @see #getMotionRange(int, int)
413     */
414    public List<MotionRange> getMotionRanges() {
415        return mMotionRanges;
416    }
417
418    private void addMotionRange(int axis, int source,
419            float min, float max, float flat, float fuzz) {
420        mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz));
421    }
422
423    /**
424     * Provides information about the range of values for a particular {@link MotionEvent} axis.
425     *
426     * @see InputDevice#getMotionRange(int)
427     */
428    public static final class MotionRange {
429        private int mAxis;
430        private int mSource;
431        private float mMin;
432        private float mMax;
433        private float mFlat;
434        private float mFuzz;
435
436        private MotionRange(int axis, int source, float min, float max, float flat, float fuzz) {
437            mAxis = axis;
438            mSource = source;
439            mMin = min;
440            mMax = max;
441            mFlat = flat;
442            mFuzz = fuzz;
443        }
444
445        /**
446         * Gets the axis id.
447         * @return The axis id.
448         */
449        public int getAxis() {
450            return mAxis;
451        }
452
453        /**
454         * Gets the source for which the axis is defined.
455         * @return The source.
456         */
457        public int getSource() {
458            return mSource;
459        }
460
461        /**
462         * Gets the inclusive minimum value for the axis.
463         * @return The inclusive minimum value.
464         */
465        public float getMin() {
466            return mMin;
467        }
468
469        /**
470         * Gets the inclusive maximum value for the axis.
471         * @return The inclusive maximum value.
472         */
473        public float getMax() {
474            return mMax;
475        }
476
477        /**
478         * Gets the range of the axis (difference between maximum and minimum).
479         * @return The range of values.
480         */
481        public float getRange() {
482            return mMax - mMin;
483        }
484
485        /**
486         * Gets the extent of the center flat position with respect to this axis.
487         * <p>
488         * For example, a flat value of 8 means that the center position is between -8 and +8.
489         * This value is mainly useful for calibrating self-centering devices.
490         * </p>
491         * @return The extent of the center flat position.
492         */
493        public float getFlat() {
494            return mFlat;
495        }
496
497        /**
498         * Gets the error tolerance for input device measurements with respect to this axis.
499         * <p>
500         * For example, a value of 2 indicates that the measured value may be up to +/- 2 units
501         * away from the actual value due to noise and device sensitivity limitations.
502         * </p>
503         * @return The error tolerance.
504         */
505        public float getFuzz() {
506            return mFuzz;
507        }
508    }
509
510    public static final Parcelable.Creator<InputDevice> CREATOR
511            = new Parcelable.Creator<InputDevice>() {
512        public InputDevice createFromParcel(Parcel in) {
513            InputDevice result = new InputDevice();
514            result.readFromParcel(in);
515            return result;
516        }
517
518        public InputDevice[] newArray(int size) {
519            return new InputDevice[size];
520        }
521    };
522
523    private void readFromParcel(Parcel in) {
524        mId = in.readInt();
525        mName = in.readString();
526        mSources = in.readInt();
527        mKeyboardType = in.readInt();
528
529        for (;;) {
530            int axis = in.readInt();
531            if (axis < 0) {
532                break;
533            }
534            addMotionRange(axis, in.readInt(),
535                    in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat());
536        }
537    }
538
539    @Override
540    public void writeToParcel(Parcel out, int flags) {
541        out.writeInt(mId);
542        out.writeString(mName);
543        out.writeInt(mSources);
544        out.writeInt(mKeyboardType);
545
546        final int numRanges = mMotionRanges.size();
547        for (int i = 0; i < numRanges; i++) {
548            MotionRange range = mMotionRanges.get(i);
549            out.writeInt(range.mAxis);
550            out.writeInt(range.mSource);
551            out.writeFloat(range.mMin);
552            out.writeFloat(range.mMax);
553            out.writeFloat(range.mFlat);
554            out.writeFloat(range.mFuzz);
555        }
556        out.writeInt(-1);
557    }
558
559    @Override
560    public int describeContents() {
561        return 0;
562    }
563
564    @Override
565    public String toString() {
566        StringBuilder description = new StringBuilder();
567        description.append("Input Device ").append(mId).append(": ").append(mName).append("\n");
568
569        description.append("  Keyboard Type: ");
570        switch (mKeyboardType) {
571            case KEYBOARD_TYPE_NONE:
572                description.append("none");
573                break;
574            case KEYBOARD_TYPE_NON_ALPHABETIC:
575                description.append("non-alphabetic");
576                break;
577            case KEYBOARD_TYPE_ALPHABETIC:
578                description.append("alphabetic");
579                break;
580        }
581        description.append("\n");
582
583        description.append("  Sources: 0x").append(Integer.toHexString(mSources)).append(" (");
584        appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard");
585        appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad");
586        appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen");
587        appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse");
588        appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball");
589        appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad");
590        appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK, "joystick");
591        appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad");
592        description.append(" )\n");
593
594        final int numAxes = mMotionRanges.size();
595        for (int i = 0; i < numAxes; i++) {
596            MotionRange range = mMotionRanges.get(i);
597            description.append("    ").append(MotionEvent.axisToString(range.mAxis));
598            description.append(": source=0x").append(Integer.toHexString(range.mSource));
599            description.append(" min=").append(range.mMin);
600            description.append(" max=").append(range.mMax);
601            description.append(" flat=").append(range.mFlat);
602            description.append(" fuzz=").append(range.mFuzz);
603            description.append("\n");
604        }
605        return description.toString();
606    }
607
608    private void appendSourceDescriptionIfApplicable(StringBuilder description, int source,
609            String sourceName) {
610        if ((mSources & source) == source) {
611            description.append(" ");
612            description.append(sourceName);
613        }
614    }
615}
616