InputDevice.java revision 91c69ab01539f7ba28708f41ec1835cc2920d0a0
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;
23import android.util.SparseArray;
24
25/**
26 * Describes the capabilities of a particular input device.
27 * <p>
28 * Each input device may support multiple classes of input.  For example, a multifunction
29 * keyboard may compose the capabilities of a standard keyboard together with a track pad mouse
30 * or other pointing device.
31 * </p><p>
32 * Some input devices present multiple distinguishable sources of input.
33 * Applications can query the framework about the characteristics of each distinct source.
34 * </p><p>
35 * As a further wrinkle, different kinds of input sources uses different coordinate systems
36 * to describe motion events.  Refer to the comments on the input source constants for
37 * the appropriate interpretation.
38 * </p>
39 */
40public final class InputDevice implements Parcelable {
41    private int mId;
42    private String mName;
43    private int mSources;
44    private int mKeyboardType;
45
46    private final SparseArray<MotionRange> mMotionRanges = new SparseArray<MotionRange>();
47
48    /**
49     * A mask for input source classes.
50     *
51     * Each distinct input source constant has one or more input source class bits set to
52     * specify the desired interpretation for its input events.
53     */
54    public static final int SOURCE_CLASS_MASK = 0x000000ff;
55
56    /**
57     * The input source has buttons or keys.
58     * Examples: {@link #SOURCE_KEYBOARD}, {@link #SOURCE_DPAD}.
59     *
60     * A {@link KeyEvent} should be interpreted as a button or key press.
61     *
62     * Use {@link #getKeyCharacterMap} to query the device's button and key mappings.
63     */
64    public static final int SOURCE_CLASS_BUTTON = 0x00000001;
65
66    /**
67     * The input source is a pointing device associated with a display.
68     * Examples: {@link #SOURCE_TOUCHSCREEN}, {@link #SOURCE_MOUSE}.
69     *
70     * A {@link MotionEvent} should be interpreted as absolute coordinates in
71     * display units according to the {@link View} hierarchy.  Pointer down/up indicated when
72     * the finger touches the display or when the selection button is pressed/released.
73     *
74     * Use {@link #getMotionRange} to query the range of the pointing device.  Some devices permit
75     * touches outside the display area so the effective range may be somewhat smaller or larger
76     * than the actual display size.
77     */
78    public static final int SOURCE_CLASS_POINTER = 0x00000002;
79
80    /**
81     * The input source is a trackball navigation device.
82     * Examples: {@link #SOURCE_TRACKBALL}.
83     *
84     * A {@link MotionEvent} should be interpreted as relative movements in device-specific
85     * units used for navigation purposes.  Pointer down/up indicates when the selection button
86     * is pressed/released.
87     *
88     * Use {@link #getMotionRange} to query the range of motion.
89     */
90    public static final int SOURCE_CLASS_TRACKBALL = 0x00000004;
91
92    /**
93     * The input source is an absolute positioning device not associated with a display
94     * (unlike {@link #SOURCE_CLASS_POINTER}).
95     *
96     * A {@link MotionEvent} should be interpreted as absolute coordinates in
97     * device-specific surface units.
98     *
99     * Use {@link #getMotionRange} to query the range of positions.
100     */
101    public static final int SOURCE_CLASS_POSITION = 0x00000008;
102
103    /**
104     * The input source is a joystick.
105     *
106     * A {@link MotionEvent} should be interpreted as absolute joystick movements.
107     *
108     * Use {@link #getMotionRange} to query the range of positions.
109     */
110    public static final int SOURCE_CLASS_JOYSTICK = 0x00000010;
111
112    /**
113     * The input source is unknown.
114     */
115    public static final int SOURCE_UNKNOWN = 0x00000000;
116
117    /**
118     * The input source is a keyboard.
119     *
120     * @see #SOURCE_CLASS_BUTTON
121     */
122    public static final int SOURCE_KEYBOARD = 0x00000100 | SOURCE_CLASS_BUTTON;
123
124    /**
125     * The input source is a DPad.
126     *
127     * @see #SOURCE_CLASS_BUTTON
128     */
129    public static final int SOURCE_DPAD = 0x00000200 | SOURCE_CLASS_BUTTON;
130
131    /**
132     * The input source is a game pad.
133     * (It may also be a {@link #SOURCE_JOYSTICK}).
134     *
135     * @see #SOURCE_CLASS_BUTTON
136     */
137    public static final int SOURCE_GAMEPAD = 0x00000400 | SOURCE_CLASS_BUTTON;
138
139    /**
140     * The input source is a touch screen pointing device.
141     *
142     * @see #SOURCE_CLASS_POINTER
143     */
144    public static final int SOURCE_TOUCHSCREEN = 0x00001000 | SOURCE_CLASS_POINTER;
145
146    /**
147     * The input source is a mouse pointing device.
148     * This code is also used for other mouse-like pointing devices such as trackpads
149     * and trackpoints.
150     *
151     * @see #SOURCE_CLASS_POINTER
152     */
153    public static final int SOURCE_MOUSE = 0x00002000 | SOURCE_CLASS_POINTER;
154
155    /**
156     * The input source is a trackball.
157     *
158     * @see #SOURCE_CLASS_TRACKBALL
159     */
160    public static final int SOURCE_TRACKBALL = 0x00010000 | SOURCE_CLASS_TRACKBALL;
161
162    /**
163     * The input source is a touch pad or digitizer tablet that is not
164     * associated with a display (unlike {@link #SOURCE_TOUCHSCREEN}).
165     *
166     * @see #SOURCE_CLASS_POSITION
167     */
168    public static final int SOURCE_TOUCHPAD = 0x00100000 | SOURCE_CLASS_POSITION;
169
170    /**
171     * The input source is a joystick.
172     * (It may also be a {@link #SOURCE_GAMEPAD}).
173     *
174     * @see #SOURCE_CLASS_JOYSTICK
175     */
176    public static final int SOURCE_JOYSTICK = 0x01000000 | SOURCE_CLASS_JOYSTICK;
177
178    /**
179     * A special input source constant that is used when filtering input devices
180     * to match devices that provide any type of input source.
181     */
182    public static final int SOURCE_ANY = 0xffffff00;
183
184    /**
185     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_X}.
186     *
187     * @see #getMotionRange
188     * @deprecated Use {@link MotionEvent#AXIS_X} instead.
189     */
190    @Deprecated
191    public static final int MOTION_RANGE_X = MotionEvent.AXIS_X;
192
193    /**
194     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_Y}.
195     *
196     * @see #getMotionRange
197     * @deprecated Use {@link MotionEvent#AXIS_Y} instead.
198     */
199    @Deprecated
200    public static final int MOTION_RANGE_Y = MotionEvent.AXIS_Y;
201
202    /**
203     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_PRESSURE}.
204     *
205     * @see #getMotionRange
206     * @deprecated Use {@link MotionEvent#AXIS_PRESSURE} instead.
207     */
208    @Deprecated
209    public static final int MOTION_RANGE_PRESSURE = MotionEvent.AXIS_PRESSURE;
210
211    /**
212     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_SIZE}.
213     *
214     * @see #getMotionRange
215     * @deprecated Use {@link MotionEvent#AXIS_SIZE} instead.
216     */
217    @Deprecated
218    public static final int MOTION_RANGE_SIZE = MotionEvent.AXIS_SIZE;
219
220    /**
221     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MAJOR}.
222     *
223     * @see #getMotionRange
224     * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MAJOR} instead.
225     */
226    @Deprecated
227    public static final int MOTION_RANGE_TOUCH_MAJOR = MotionEvent.AXIS_TOUCH_MAJOR;
228
229    /**
230     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MINOR}.
231     *
232     * @see #getMotionRange
233     * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MINOR} instead.
234     */
235    @Deprecated
236    public static final int MOTION_RANGE_TOUCH_MINOR = MotionEvent.AXIS_TOUCH_MINOR;
237
238    /**
239     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MAJOR}.
240     *
241     * @see #getMotionRange
242     * @deprecated Use {@link MotionEvent#AXIS_TOOL_MAJOR} instead.
243     */
244    @Deprecated
245    public static final int MOTION_RANGE_TOOL_MAJOR = MotionEvent.AXIS_TOOL_MAJOR;
246
247    /**
248     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MINOR}.
249     *
250     * @see #getMotionRange
251     * @deprecated Use {@link MotionEvent#AXIS_TOOL_MINOR} instead.
252     */
253    @Deprecated
254    public static final int MOTION_RANGE_TOOL_MINOR = MotionEvent.AXIS_TOOL_MINOR;
255
256    /**
257     * Constant for retrieving the range of values for {@link MotionEvent#AXIS_ORIENTATION}.
258     *
259     * @see #getMotionRange
260     * @deprecated Use {@link MotionEvent#AXIS_ORIENTATION} instead.
261     */
262    @Deprecated
263    public static final int MOTION_RANGE_ORIENTATION = MotionEvent.AXIS_ORIENTATION;
264
265    /**
266     * There is no keyboard.
267     */
268    public static final int KEYBOARD_TYPE_NONE = 0;
269
270    /**
271     * The keyboard is not fully alphabetic.  It may be a numeric keypad or an assortment
272     * of buttons that are not mapped as alphabetic keys suitable for text input.
273     */
274    public static final int KEYBOARD_TYPE_NON_ALPHABETIC = 1;
275
276    /**
277     * The keyboard supports a complement of alphabetic keys.
278     */
279    public static final int KEYBOARD_TYPE_ALPHABETIC = 2;
280
281    // Called by native code.
282    private InputDevice() {
283    }
284
285    /**
286     * Gets information about the input device with the specified id.
287     * @param id The device id.
288     * @return The input device or null if not found.
289     */
290    public static InputDevice getDevice(int id) {
291        IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
292        try {
293            return wm.getInputDevice(id);
294        } catch (RemoteException ex) {
295            throw new RuntimeException(
296                    "Could not get input device information from Window Manager.", ex);
297        }
298    }
299
300    /**
301     * Gets the ids of all input devices in the system.
302     * @return The input device ids.
303     */
304    public static int[] getDeviceIds() {
305        IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
306        try {
307            return wm.getInputDeviceIds();
308        } catch (RemoteException ex) {
309            throw new RuntimeException(
310                    "Could not get input device ids from Window Manager.", ex);
311        }
312    }
313
314    /**
315     * Gets the input device id.
316     * @return The input device id.
317     */
318    public int getId() {
319        return mId;
320    }
321
322    /**
323     * Gets the name of this input device.
324     * @return The input device name.
325     */
326    public String getName() {
327        return mName;
328    }
329
330    /**
331     * Gets the input sources supported by this input device as a combined bitfield.
332     * @return The supported input sources.
333     */
334    public int getSources() {
335        return mSources;
336    }
337
338    /**
339     * Gets the keyboard type.
340     * @return The keyboard type.
341     */
342    public int getKeyboardType() {
343        return mKeyboardType;
344    }
345
346    /**
347     * Gets the key character map associated with this input device.
348     * @return The key character map.
349     */
350    public KeyCharacterMap getKeyCharacterMap() {
351        return KeyCharacterMap.load(mId);
352    }
353
354    /**
355     * Gets information about the range of values for a particular {@link MotionEvent} axis.
356     * @param axis The axis constant.
357     * @return The range of values, or null if the requested axis is not
358     * supported by the device.
359     *
360     * @see MotionEvent#AXIS_X
361     * @see MotionEvent#AXIS_Y
362     */
363    public MotionRange getMotionRange(int axis) {
364        return mMotionRanges.get(axis);
365    }
366
367    // Called by native code.
368    private void addMotionRange(int axis, float min, float max, float flat, float fuzz) {
369        mMotionRanges.append(axis, new MotionRange(min, max, flat, fuzz));
370    }
371
372    /**
373     * Provides information about the range of values for a particular {@link MotionEvent} axis.
374     *
375     * @see InputDevice#getMotionRange(int)
376     */
377    public static final class MotionRange {
378        private float mMin;
379        private float mMax;
380        private float mFlat;
381        private float mFuzz;
382
383        private MotionRange(float min, float max, float flat, float fuzz) {
384            mMin = min;
385            mMax = max;
386            mFlat = flat;
387            mFuzz = fuzz;
388        }
389
390        /**
391         * Gets the minimum value for the axis.
392         * @return The (inclusive) minimum value.
393         */
394        public float getMin() {
395            return mMin;
396        }
397
398        /**
399         * Gets the maximum value for the axis.
400         * @return The (inclusive) maximum value.
401         */
402        public float getMax() {
403            return mMax;
404        }
405
406        /**
407         * Gets the range of the axis (difference between maximum and minimum plus one).
408         * @return The range of values.
409         */
410        public float getRange() {
411            return mMax - mMin + 1;
412        }
413
414        /**
415         * Gets the extent of the center flat position with respect to this axis.
416         * For example, a flat value of 8 means that the center position is between -8 and +8.
417         * This value is mainly useful for calibrating self-centering devices.
418         * @return The extent of the center flat position.
419         */
420        public float getFlat() {
421            return mFlat;
422        }
423
424        /**
425         * Gets the error tolerance for input device measurements with respect to this axis.
426         * For example, a value of 2 indicates that the measured value may be up to +/- 2 units
427         * away from the actual value due to noise and device sensitivity limitations.
428         * @return The error tolerance.
429         */
430        public float getFuzz() {
431            return mFuzz;
432        }
433    }
434
435    public static final Parcelable.Creator<InputDevice> CREATOR
436            = new Parcelable.Creator<InputDevice>() {
437        public InputDevice createFromParcel(Parcel in) {
438            InputDevice result = new InputDevice();
439            result.readFromParcel(in);
440            return result;
441        }
442
443        public InputDevice[] newArray(int size) {
444            return new InputDevice[size];
445        }
446    };
447
448    private void readFromParcel(Parcel in) {
449        mId = in.readInt();
450        mName = in.readString();
451        mSources = in.readInt();
452        mKeyboardType = in.readInt();
453
454        for (;;) {
455            int axis = in.readInt();
456            if (axis < 0) {
457                break;
458            }
459            addMotionRange(axis, in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat());
460        }
461    }
462
463    @Override
464    public void writeToParcel(Parcel out, int flags) {
465        out.writeInt(mId);
466        out.writeString(mName);
467        out.writeInt(mSources);
468        out.writeInt(mKeyboardType);
469
470        final int numAxes = mMotionRanges.size();
471        for (int i = 0; i < numAxes; i++) {
472            int axis = mMotionRanges.keyAt(i);
473            MotionRange range = mMotionRanges.valueAt(i);
474            out.writeInt(axis);
475            out.writeFloat(range.mMin);
476            out.writeFloat(range.mMax);
477            out.writeFloat(range.mFlat);
478            out.writeFloat(range.mFuzz);
479        }
480        out.writeInt(-1);
481    }
482
483    @Override
484    public int describeContents() {
485        return 0;
486    }
487
488    @Override
489    public String toString() {
490        StringBuilder description = new StringBuilder();
491        description.append("Input Device ").append(mId).append(": ").append(mName).append("\n");
492
493        description.append("  Keyboard Type: ");
494        switch (mKeyboardType) {
495            case KEYBOARD_TYPE_NONE:
496                description.append("none");
497                break;
498            case KEYBOARD_TYPE_NON_ALPHABETIC:
499                description.append("non-alphabetic");
500                break;
501            case KEYBOARD_TYPE_ALPHABETIC:
502                description.append("alphabetic");
503                break;
504        }
505        description.append("\n");
506
507        description.append("  Sources: ").append(Integer.toHexString(mSources)).append(" (");
508        appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard");
509        appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad");
510        appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen");
511        appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse");
512        appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball");
513        appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad");
514        appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK, "joystick");
515        appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad");
516        description.append(" )\n");
517
518        final int numAxes = mMotionRanges.size();
519        for (int i = 0; i < numAxes; i++) {
520            int axis = mMotionRanges.keyAt(i);
521            MotionRange range = mMotionRanges.valueAt(i);
522            description.append("    ").append(MotionEvent.axisToString(axis));
523            description.append(": min=").append(range.mMin);
524            description.append(" max=").append(range.mMax);
525            description.append(" flat=").append(range.mFlat);
526            description.append(" fuzz=").append(range.mFuzz);
527            description.append("\n");
528        }
529        return description.toString();
530    }
531
532    private void appendSourceDescriptionIfApplicable(StringBuilder description, int source,
533            String sourceName) {
534        if ((mSources & source) == source) {
535            description.append(" ");
536            description.append(sourceName);
537        }
538    }
539}
540