InputDevice.java revision 8d60866e2100db70ecf0502c14768a384514d7e9
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.Log;
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.  For example, a
33 * game pad may have two analog joysticks, a directional pad and a full complement of buttons.
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
47    private MotionRange[] mMotionRanges;
48
49    /**
50     * A mask for input source classes.
51     *
52     * Each distinct input source constant has one or more input source class bits set to
53     * specify the desired interpretation for its input events.
54     */
55    public static final int SOURCE_CLASS_MASK = 0x000000ff;
56
57    /**
58     * The input source has buttons or keys.
59     * Examples: {@link #SOURCE_KEYBOARD}, {@link #SOURCE_GAMEPAD}, {@link #SOURCE_DPAD}.
60     *
61     * A {@link KeyEvent} should be interpreted as a button or key press.
62     *
63     * Use {@link #hasKey} to query whether the device supports a particular button or key.
64     */
65    public static final int SOURCE_CLASS_BUTTON = 0x00000001;
66
67    /**
68     * The input source is a pointing device associated with a display.
69     * Examples: {@link #SOURCE_TOUCHSCREEN}, {@link #SOURCE_MOUSE}.
70     *
71     * A {@link MotionEvent} should be interpreted as absolute coordinates in
72     * display units according to the {@link View} hierarchy.  Pointer down/up indicated when
73     * the finger touches the display or when the selection button is pressed/released.
74     *
75     * Use {@link #getMotionRange} to query the range of the pointing device.  Some devices permit
76     * touches outside the display area so the effective range may be somewhat smaller or larger
77     * than the actual display size.
78     */
79    public static final int SOURCE_CLASS_POINTER = 0x00000002;
80
81    /**
82     * The input source is a trackball navigation device.
83     * Examples: {@link #SOURCE_TRACKBALL}.
84     *
85     * A {@link MotionEvent} should be interpreted as relative movements in device-specific
86     * units used for navigation purposes.  Pointer down/up indicates when the selection button
87     * is pressed/released.
88     *
89     * Use {@link #getMotionRange} to query the range of motion.
90     */
91    public static final int SOURCE_CLASS_TRACKBALL = 0x00000004;
92
93    /**
94     * The input source is an absolute positioning device not associated with a display
95     * (unlike {@link #SOURCE_CLASS_POINTER}).
96     *
97     * A {@link MotionEvent} should be interpreted as absolute coordinates in
98     * device-specific surface units.
99     *
100     * Use {@link #getMotionRange} to query the range of positions.
101     */
102    public static final int SOURCE_CLASS_POSITION = 0x00000008;
103
104    /**
105     * The input source is a joystick.
106     *
107     * A {@link KeyEvent} should be interpreted as a joystick button press.
108     *
109     * A {@link MotionEvent} should be interpreted in absolute coordinates as a joystick
110     * position in normalized device-specific units nominally between -1.0 and 1.0.
111     *
112     * Use {@link #getMotionRange} to query the range and precision of motion.
113     */
114    public static final int SOURCE_CLASS_JOYSTICK = 0x00000010;
115
116    /**
117     * The input source is unknown.
118     */
119    public static final int SOURCE_UNKNOWN = 0x00000000;
120
121    /**
122     * The input source is a keyboard.
123     *
124     * @see #SOURCE_CLASS_BUTTON
125     */
126    public static final int SOURCE_KEYBOARD = 0x00000100 | SOURCE_CLASS_BUTTON;
127
128    /**
129     * The input source is a DPad.
130     *
131     * @see #SOURCE_CLASS_BUTTON
132     */
133    public static final int SOURCE_DPAD = 0x00000200 | SOURCE_CLASS_BUTTON;
134
135    /**
136     * The input source is a gamepad.
137     *
138     * @see #SOURCE_CLASS_BUTTON
139     */
140    public static final int SOURCE_GAMEPAD = 0x00000400 | SOURCE_CLASS_BUTTON;
141
142    /**
143     * The input source is a touch screen pointing device.
144     *
145     * @see #SOURCE_CLASS_POINTER
146     */
147    public static final int SOURCE_TOUCHSCREEN = 0x00001000 | SOURCE_CLASS_POINTER;
148
149    /**
150     * The input source is a mouse pointing device.
151     * This code is also used for other mouse-like pointing devices such as trackpads
152     * and trackpoints.
153     *
154     * @see #SOURCE_CLASS_POINTER
155     */
156    public static final int SOURCE_MOUSE = 0x00002000 | SOURCE_CLASS_POINTER;
157
158    /**
159     * The input source is a trackball.
160     *
161     * @see #SOURCE_CLASS_TRACKBALL
162     */
163    public static final int SOURCE_TRACKBALL = 0x00010000 | SOURCE_CLASS_TRACKBALL;
164
165    /**
166     * The input source is a touch pad or digitizer tablet that is not
167     * associated with a display (unlike {@link #SOURCE_TOUCHSCREEN}).
168     *
169     * @see #SOURCE_CLASS_POSITION
170     */
171    public static final int SOURCE_TOUCHPAD = 0x00100000 | SOURCE_CLASS_POSITION;
172
173    /**
174     * The input source is a joystick mounted on the left or is a standalone joystick.
175     *
176     * @see #SOURCE_CLASS_JOYSTICK
177     */
178    public static final int SOURCE_JOYSTICK_LEFT = 0x01000000 | SOURCE_CLASS_JOYSTICK;
179
180    /**
181     * The input source is a joystick mounted on the right.
182     *
183     * @see #SOURCE_CLASS_JOYSTICK
184     */
185    public static final int SOURCE_JOYSTICK_RIGHT = 0x02000000 | SOURCE_CLASS_JOYSTICK;
186
187    /**
188     * A special input source constant that is used when filtering input devices
189     * to match devices that provide any type of input source.
190     */
191    public static final int SOURCE_ANY = 0xffffff00;
192
193    /**
194     * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#x}.
195     *
196     * @see #getMotionRange
197     */
198    public static final int MOTION_RANGE_X = 0;
199
200    /**
201     * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#y}.
202     *
203     * @see #getMotionRange
204     */
205    public static final int MOTION_RANGE_Y = 1;
206
207    /**
208     * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#pressure}.
209     *
210     * @see #getMotionRange
211     */
212    public static final int MOTION_RANGE_PRESSURE = 2;
213
214    /**
215     * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#size}.
216     *
217     * @see #getMotionRange
218     */
219    public static final int MOTION_RANGE_SIZE = 3;
220
221    /**
222     * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#touchMajor}.
223     *
224     * @see #getMotionRange
225     */
226    public static final int MOTION_RANGE_TOUCH_MAJOR = 4;
227
228    /**
229     * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#touchMinor}.
230     *
231     * @see #getMotionRange
232     */
233    public static final int MOTION_RANGE_TOUCH_MINOR = 5;
234
235    /**
236     * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#toolMajor}.
237     *
238     * @see #getMotionRange
239     */
240    public static final int MOTION_RANGE_TOOL_MAJOR = 6;
241
242    /**
243     * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#toolMinor}.
244     *
245     * @see #getMotionRange
246     */
247    public static final int MOTION_RANGE_TOOL_MINOR = 7;
248
249    /**
250     * Constant for retrieving the range of values for
251     * {@link MotionEvent.PointerCoords#orientation}.
252     *
253     * @see #getMotionRange
254     */
255    public static final int MOTION_RANGE_ORIENTATION = 8;
256
257    private static final int MOTION_RANGE_LAST = MOTION_RANGE_ORIENTATION;
258
259    /**
260     * There is no keyboard.
261     */
262    public static final int KEYBOARD_TYPE_NONE = 0;
263
264    /**
265     * The keyboard is not fully alphabetic.  It may be a numeric keypad or an assortment
266     * of buttons that are not mapped as alphabetic keys suitable for text input.
267     */
268    public static final int KEYBOARD_TYPE_NON_ALPHABETIC = 1;
269
270    /**
271     * The keyboard supports a complement of alphabetic keys.
272     */
273    public static final int KEYBOARD_TYPE_ALPHABETIC = 2;
274
275    // Called by native code.
276    private InputDevice() {
277        mMotionRanges = new MotionRange[MOTION_RANGE_LAST + 1];
278    }
279
280    /**
281     * Gets information about the input device with the specified id.
282     * @param id The device id.
283     * @return The input device or null if not found.
284     */
285    public static InputDevice getDevice(int id) {
286        IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
287        try {
288            return wm.getInputDevice(id);
289        } catch (RemoteException ex) {
290            throw new RuntimeException(
291                    "Could not get input device information from Window Manager.", ex);
292        }
293    }
294
295    /**
296     * Gets the ids of all input devices in the system.
297     * @return The input device ids.
298     */
299    public static int[] getDeviceIds() {
300        IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
301        try {
302            return wm.getInputDeviceIds();
303        } catch (RemoteException ex) {
304            throw new RuntimeException(
305                    "Could not get input device ids from Window Manager.", ex);
306        }
307    }
308
309    /**
310     * Gets the input device id.
311     * @return The input device id.
312     */
313    public int getId() {
314        return mId;
315    }
316
317    /**
318     * Gets the name of this input device.
319     * @return The input device name.
320     */
321    public String getName() {
322        return mName;
323    }
324
325    /**
326     * Gets the input sources supported by this input device as a combined bitfield.
327     * @return The supported input sources.
328     */
329    public int getSources() {
330        return mSources;
331    }
332
333    /**
334     * Gets the keyboard type.
335     * @return The keyboard type.
336     */
337    public int getKeyboardType() {
338        return mKeyboardType;
339    }
340
341    /**
342     * Gets the key character map associated with this input device.
343     * @return The key character map.
344     */
345    public KeyCharacterMap getKeyCharacterMap() {
346        return KeyCharacterMap.load(mId);
347    }
348
349    /**
350     * Gets information about the range of values for a particular {@link MotionEvent}
351     * coordinate.
352     * @param rangeType The motion range constant.
353     * @return The range of values, or null if the requested coordinate is not
354     * supported by the device.
355     */
356    public MotionRange getMotionRange(int rangeType) {
357        if (rangeType < 0 || rangeType > MOTION_RANGE_LAST) {
358            throw new IllegalArgumentException("Requested range is out of bounds.");
359        }
360
361        return mMotionRanges[rangeType];
362    }
363
364    private void addMotionRange(int rangeType, float min, float max, float flat, float fuzz) {
365        if (rangeType >= 0 && rangeType <= MOTION_RANGE_LAST) {
366            MotionRange range = new MotionRange(min, max, flat, fuzz);
367            mMotionRanges[rangeType] = range;
368        }
369    }
370
371    /**
372     * Provides information about the range of values for a particular {@link MotionEvent}
373     * coordinate.
374     */
375    public static final class MotionRange {
376        private float mMin;
377        private float mMax;
378        private float mFlat;
379        private float mFuzz;
380
381        private MotionRange(float min, float max, float flat, float fuzz) {
382            mMin = min;
383            mMax = max;
384            mFlat = flat;
385            mFuzz = fuzz;
386        }
387
388        /**
389         * Gets the minimum value for the coordinate.
390         * @return The minimum value.
391         */
392        public float getMin() {
393            return mMin;
394        }
395
396        /**
397         * Gets the maximum value for the coordinate.
398         * @return The minimum value.
399         */
400        public float getMax() {
401            return mMax;
402        }
403
404        /**
405         * Gets the range of the coordinate (difference between maximum and minimum).
406         * @return The range of values.
407         */
408        public float getRange() {
409            return mMax - mMin;
410        }
411
412        /**
413         * Gets the extent of the center flat position with respect to this coordinate.
414         * For example, a flat value of 8 means that the center position is between -8 and +8.
415         * This value is mainly useful for calibrating joysticks.
416         * @return The extent of the center flat position.
417         */
418        public float getFlat() {
419            return mFlat;
420        }
421
422        /**
423         * Gets the error tolerance for input device measurements with respect to this coordinate.
424         * For example, a value of 2 indicates that the measured value may be up to +/- 2 units
425         * away from the actual value due to noise and device sensitivity limitations.
426         * @return The error tolerance.
427         */
428        public float getFuzz() {
429            return mFuzz;
430        }
431    }
432
433    public static final Parcelable.Creator<InputDevice> CREATOR
434            = new Parcelable.Creator<InputDevice>() {
435        public InputDevice createFromParcel(Parcel in) {
436            InputDevice result = new InputDevice();
437            result.readFromParcel(in);
438            return result;
439        }
440
441        public InputDevice[] newArray(int size) {
442            return new InputDevice[size];
443        }
444    };
445
446    private void readFromParcel(Parcel in) {
447        mId = in.readInt();
448        mName = in.readString();
449        mSources = in.readInt();
450        mKeyboardType = in.readInt();
451
452        for (;;) {
453            int rangeType = in.readInt();
454            if (rangeType < 0) {
455                break;
456            }
457
458            addMotionRange(rangeType,
459                    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        for (int i = 0; i <= MOTION_RANGE_LAST; i++) {
471            MotionRange range = mMotionRanges[i];
472            if (range != null) {
473                out.writeInt(i);
474                out.writeFloat(range.mMin);
475                out.writeFloat(range.mMax);
476                out.writeFloat(range.mFlat);
477                out.writeFloat(range.mFuzz);
478            }
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:");
508        appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard");
509        appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad");
510        appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad");
511        appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen");
512        appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse");
513        appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball");
514        appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad");
515        appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK_LEFT, "joystick_left");
516        appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK_RIGHT, "joystick_right");
517        description.append("\n");
518
519        appendRangeDescriptionIfApplicable(description, MOTION_RANGE_X, "x");
520        appendRangeDescriptionIfApplicable(description, MOTION_RANGE_Y, "y");
521        appendRangeDescriptionIfApplicable(description, MOTION_RANGE_PRESSURE, "pressure");
522        appendRangeDescriptionIfApplicable(description, MOTION_RANGE_SIZE, "size");
523        appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOUCH_MAJOR, "touchMajor");
524        appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOUCH_MINOR, "touchMinor");
525        appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOOL_MAJOR, "toolMajor");
526        appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOOL_MINOR, "toolMinor");
527        appendRangeDescriptionIfApplicable(description, MOTION_RANGE_ORIENTATION, "orientation");
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    private void appendRangeDescriptionIfApplicable(StringBuilder description,
541            int rangeType, String rangeName) {
542        MotionRange range = mMotionRanges[rangeType];
543        if (range != null) {
544            description.append("  Range[").append(rangeName);
545            description.append("]: min=").append(range.mMin);
546            description.append(" max=").append(range.mMax);
547            description.append(" flat=").append(range.mFlat);
548            description.append(" fuzz=").append(range.mFuzz);
549            description.append("\n");
550        }
551    }
552}
553