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