• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package android.view;
18 
19 import android.content.Context;
20 import android.hardware.input.InputManager;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.os.Vibrator;
24 import android.os.NullVibrator;
25 
26 import java.util.ArrayList;
27 import java.util.List;
28 
29 /**
30  * Describes the capabilities of a particular input device.
31  * <p>
32  * Each input device may support multiple classes of input.  For example, a multi-function
33  * keyboard may compose the capabilities of a standard keyboard together with a track pad mouse
34  * or other pointing device.
35  * </p><p>
36  * Some input devices present multiple distinguishable sources of input.
37  * Applications can query the framework about the characteristics of each distinct source.
38  * </p><p>
39  * As a further wrinkle, different kinds of input sources uses different coordinate systems
40  * to describe motion events.  Refer to the comments on the input source constants for
41  * the appropriate interpretation.
42  * </p>
43  */
44 public final class InputDevice implements Parcelable {
45     private final int mId;
46     private final int mGeneration;
47     private final String mName;
48     private final String mDescriptor;
49     private final boolean mIsExternal;
50     private final int mSources;
51     private final int mKeyboardType;
52     private final KeyCharacterMap mKeyCharacterMap;
53     private final boolean mHasVibrator;
54     private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>();
55 
56     private Vibrator mVibrator; // guarded by mMotionRanges during initialization
57 
58     /**
59      * A mask for input source classes.
60      *
61      * Each distinct input source constant has one or more input source class bits set to
62      * specify the desired interpretation for its input events.
63      */
64     public static final int SOURCE_CLASS_MASK = 0x000000ff;
65 
66     /**
67      * The input source has buttons or keys.
68      * Examples: {@link #SOURCE_KEYBOARD}, {@link #SOURCE_DPAD}.
69      *
70      * A {@link KeyEvent} should be interpreted as a button or key press.
71      *
72      * Use {@link #getKeyCharacterMap} to query the device's button and key mappings.
73      */
74     public static final int SOURCE_CLASS_BUTTON = 0x00000001;
75 
76     /**
77      * The input source is a pointing device associated with a display.
78      * Examples: {@link #SOURCE_TOUCHSCREEN}, {@link #SOURCE_MOUSE}.
79      *
80      * A {@link MotionEvent} should be interpreted as absolute coordinates in
81      * display units according to the {@link View} hierarchy.  Pointer down/up indicated when
82      * the finger touches the display or when the selection button is pressed/released.
83      *
84      * Use {@link #getMotionRange} to query the range of the pointing device.  Some devices permit
85      * touches outside the display area so the effective range may be somewhat smaller or larger
86      * than the actual display size.
87      */
88     public static final int SOURCE_CLASS_POINTER = 0x00000002;
89 
90     /**
91      * The input source is a trackball navigation device.
92      * Examples: {@link #SOURCE_TRACKBALL}.
93      *
94      * A {@link MotionEvent} should be interpreted as relative movements in device-specific
95      * units used for navigation purposes.  Pointer down/up indicates when the selection button
96      * is pressed/released.
97      *
98      * Use {@link #getMotionRange} to query the range of motion.
99      */
100     public static final int SOURCE_CLASS_TRACKBALL = 0x00000004;
101 
102     /**
103      * The input source is an absolute positioning device not associated with a display
104      * (unlike {@link #SOURCE_CLASS_POINTER}).
105      *
106      * A {@link MotionEvent} should be interpreted as absolute coordinates in
107      * device-specific surface units.
108      *
109      * Use {@link #getMotionRange} to query the range of positions.
110      */
111     public static final int SOURCE_CLASS_POSITION = 0x00000008;
112 
113     /**
114      * The input source is a joystick.
115      *
116      * A {@link MotionEvent} should be interpreted as absolute joystick movements.
117      *
118      * Use {@link #getMotionRange} to query the range of positions.
119      */
120     public static final int SOURCE_CLASS_JOYSTICK = 0x00000010;
121 
122     /**
123      * The input source is unknown.
124      */
125     public static final int SOURCE_UNKNOWN = 0x00000000;
126 
127     /**
128      * The input source is a keyboard.
129      *
130      * This source indicates pretty much anything that has buttons.  Use
131      * {@link #getKeyboardType()} to determine whether the keyboard has alphabetic keys
132      * and can be used to enter text.
133      *
134      * @see #SOURCE_CLASS_BUTTON
135      */
136     public static final int SOURCE_KEYBOARD = 0x00000100 | SOURCE_CLASS_BUTTON;
137 
138     /**
139      * The input source is a DPad.
140      *
141      * @see #SOURCE_CLASS_BUTTON
142      */
143     public static final int SOURCE_DPAD = 0x00000200 | SOURCE_CLASS_BUTTON;
144 
145     /**
146      * The input source is a game pad.
147      * (It may also be a {@link #SOURCE_JOYSTICK}).
148      *
149      * @see #SOURCE_CLASS_BUTTON
150      */
151     public static final int SOURCE_GAMEPAD = 0x00000400 | SOURCE_CLASS_BUTTON;
152 
153     /**
154      * The input source is a touch screen pointing device.
155      *
156      * @see #SOURCE_CLASS_POINTER
157      */
158     public static final int SOURCE_TOUCHSCREEN = 0x00001000 | SOURCE_CLASS_POINTER;
159 
160     /**
161      * The input source is a mouse pointing device.
162      * This code is also used for other mouse-like pointing devices such as trackpads
163      * and trackpoints.
164      *
165      * @see #SOURCE_CLASS_POINTER
166      */
167     public static final int SOURCE_MOUSE = 0x00002000 | SOURCE_CLASS_POINTER;
168 
169     /**
170      * The input source is a stylus pointing device.
171      * <p>
172      * Note that this bit merely indicates that an input device is capable of obtaining
173      * input from a stylus.  To determine whether a given touch event was produced
174      * by a stylus, examine the tool type returned by {@link MotionEvent#getToolType(int)}
175      * for each individual pointer.
176      * </p><p>
177      * A single touch event may multiple pointers with different tool types,
178      * such as an event that has one pointer with tool type
179      * {@link MotionEvent#TOOL_TYPE_FINGER} and another pointer with tool type
180      * {@link MotionEvent#TOOL_TYPE_STYLUS}.  So it is important to examine
181      * the tool type of each pointer, regardless of the source reported
182      * by {@link MotionEvent#getSource()}.
183      * </p>
184      *
185      * @see #SOURCE_CLASS_POINTER
186      */
187     public static final int SOURCE_STYLUS = 0x00004000 | SOURCE_CLASS_POINTER;
188 
189     /**
190      * The input source is a trackball.
191      *
192      * @see #SOURCE_CLASS_TRACKBALL
193      */
194     public static final int SOURCE_TRACKBALL = 0x00010000 | SOURCE_CLASS_TRACKBALL;
195 
196     /**
197      * The input source is a touch pad or digitizer tablet that is not
198      * associated with a display (unlike {@link #SOURCE_TOUCHSCREEN}).
199      *
200      * @see #SOURCE_CLASS_POSITION
201      */
202     public static final int SOURCE_TOUCHPAD = 0x00100000 | SOURCE_CLASS_POSITION;
203 
204     /**
205      * The input source is a joystick.
206      * (It may also be a {@link #SOURCE_GAMEPAD}).
207      *
208      * @see #SOURCE_CLASS_JOYSTICK
209      */
210     public static final int SOURCE_JOYSTICK = 0x01000000 | SOURCE_CLASS_JOYSTICK;
211 
212     /**
213      * A special input source constant that is used when filtering input devices
214      * to match devices that provide any type of input source.
215      */
216     public static final int SOURCE_ANY = 0xffffff00;
217 
218     /**
219      * Constant for retrieving the range of values for {@link MotionEvent#AXIS_X}.
220      *
221      * @see #getMotionRange
222      * @deprecated Use {@link MotionEvent#AXIS_X} instead.
223      */
224     @Deprecated
225     public static final int MOTION_RANGE_X = MotionEvent.AXIS_X;
226 
227     /**
228      * Constant for retrieving the range of values for {@link MotionEvent#AXIS_Y}.
229      *
230      * @see #getMotionRange
231      * @deprecated Use {@link MotionEvent#AXIS_Y} instead.
232      */
233     @Deprecated
234     public static final int MOTION_RANGE_Y = MotionEvent.AXIS_Y;
235 
236     /**
237      * Constant for retrieving the range of values for {@link MotionEvent#AXIS_PRESSURE}.
238      *
239      * @see #getMotionRange
240      * @deprecated Use {@link MotionEvent#AXIS_PRESSURE} instead.
241      */
242     @Deprecated
243     public static final int MOTION_RANGE_PRESSURE = MotionEvent.AXIS_PRESSURE;
244 
245     /**
246      * Constant for retrieving the range of values for {@link MotionEvent#AXIS_SIZE}.
247      *
248      * @see #getMotionRange
249      * @deprecated Use {@link MotionEvent#AXIS_SIZE} instead.
250      */
251     @Deprecated
252     public static final int MOTION_RANGE_SIZE = MotionEvent.AXIS_SIZE;
253 
254     /**
255      * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MAJOR}.
256      *
257      * @see #getMotionRange
258      * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MAJOR} instead.
259      */
260     @Deprecated
261     public static final int MOTION_RANGE_TOUCH_MAJOR = MotionEvent.AXIS_TOUCH_MAJOR;
262 
263     /**
264      * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MINOR}.
265      *
266      * @see #getMotionRange
267      * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MINOR} instead.
268      */
269     @Deprecated
270     public static final int MOTION_RANGE_TOUCH_MINOR = MotionEvent.AXIS_TOUCH_MINOR;
271 
272     /**
273      * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MAJOR}.
274      *
275      * @see #getMotionRange
276      * @deprecated Use {@link MotionEvent#AXIS_TOOL_MAJOR} instead.
277      */
278     @Deprecated
279     public static final int MOTION_RANGE_TOOL_MAJOR = MotionEvent.AXIS_TOOL_MAJOR;
280 
281     /**
282      * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MINOR}.
283      *
284      * @see #getMotionRange
285      * @deprecated Use {@link MotionEvent#AXIS_TOOL_MINOR} instead.
286      */
287     @Deprecated
288     public static final int MOTION_RANGE_TOOL_MINOR = MotionEvent.AXIS_TOOL_MINOR;
289 
290     /**
291      * Constant for retrieving the range of values for {@link MotionEvent#AXIS_ORIENTATION}.
292      *
293      * @see #getMotionRange
294      * @deprecated Use {@link MotionEvent#AXIS_ORIENTATION} instead.
295      */
296     @Deprecated
297     public static final int MOTION_RANGE_ORIENTATION = MotionEvent.AXIS_ORIENTATION;
298 
299     /**
300      * There is no keyboard.
301      */
302     public static final int KEYBOARD_TYPE_NONE = 0;
303 
304     /**
305      * The keyboard is not fully alphabetic.  It may be a numeric keypad or an assortment
306      * of buttons that are not mapped as alphabetic keys suitable for text input.
307      */
308     public static final int KEYBOARD_TYPE_NON_ALPHABETIC = 1;
309 
310     /**
311      * The keyboard supports a complement of alphabetic keys.
312      */
313     public static final int KEYBOARD_TYPE_ALPHABETIC = 2;
314 
315     public static final Parcelable.Creator<InputDevice> CREATOR =
316             new Parcelable.Creator<InputDevice>() {
317         public InputDevice createFromParcel(Parcel in) {
318             return new InputDevice(in);
319         }
320         public InputDevice[] newArray(int size) {
321             return new InputDevice[size];
322         }
323     };
324 
325     // Called by native code.
InputDevice(int id, int generation, String name, String descriptor, boolean isExternal, int sources, int keyboardType, KeyCharacterMap keyCharacterMap, boolean hasVibrator)326     private InputDevice(int id, int generation, String name, String descriptor,
327             boolean isExternal, int sources,
328             int keyboardType, KeyCharacterMap keyCharacterMap, boolean hasVibrator) {
329         mId = id;
330         mGeneration = generation;
331         mName = name;
332         mDescriptor = descriptor;
333         mIsExternal = isExternal;
334         mSources = sources;
335         mKeyboardType = keyboardType;
336         mKeyCharacterMap = keyCharacterMap;
337         mHasVibrator = hasVibrator;
338     }
339 
InputDevice(Parcel in)340     private InputDevice(Parcel in) {
341         mId = in.readInt();
342         mGeneration = in.readInt();
343         mName = in.readString();
344         mDescriptor = in.readString();
345         mIsExternal = in.readInt() != 0;
346         mSources = in.readInt();
347         mKeyboardType = in.readInt();
348         mKeyCharacterMap = KeyCharacterMap.CREATOR.createFromParcel(in);
349         mHasVibrator = in.readInt() != 0;
350 
351         for (;;) {
352             int axis = in.readInt();
353             if (axis < 0) {
354                 break;
355             }
356             addMotionRange(axis, in.readInt(),
357                     in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat());
358         }
359     }
360 
361     /**
362      * Gets information about the input device with the specified id.
363      * @param id The device id.
364      * @return The input device or null if not found.
365      */
getDevice(int id)366     public static InputDevice getDevice(int id) {
367         return InputManager.getInstance().getInputDevice(id);
368     }
369 
370     /**
371      * Gets the ids of all input devices in the system.
372      * @return The input device ids.
373      */
getDeviceIds()374     public static int[] getDeviceIds() {
375         return InputManager.getInstance().getInputDeviceIds();
376     }
377 
378     /**
379      * Gets the input device id.
380      * <p>
381      * Each input device receives a unique id when it is first configured
382      * by the system.  The input device id may change when the system is restarted or if the
383      * input device is disconnected, reconnected or reconfigured at any time.
384      * If you require a stable identifier for a device that persists across
385      * boots and reconfigurations, use {@link #getDescriptor()}.
386      * </p>
387      *
388      * @return The input device id.
389      */
getId()390     public int getId() {
391         return mId;
392     }
393 
394     /**
395      * Gets a generation number for this input device.
396      * The generation number is incremented whenever the device is reconfigured and its
397      * properties may have changed.
398      *
399      * @return The generation number.
400      *
401      * @hide
402      */
getGeneration()403     public int getGeneration() {
404         return mGeneration;
405     }
406 
407     /**
408      * Gets the input device descriptor, which is a stable identifier for an input device.
409      * <p>
410      * An input device descriptor uniquely identifies an input device.  Its value
411      * is intended to be persistent across system restarts, and should not change even
412      * if the input device is disconnected, reconnected or reconfigured at any time.
413      * </p><p>
414      * It is possible for there to be multiple {@link InputDevice} instances that have the
415      * same input device descriptor.  This might happen in situations where a single
416      * human input device registers multiple {@link InputDevice} instances (HID collections)
417      * that describe separate features of the device, such as a keyboard that also
418      * has a trackpad.  Alternately, it may be that the input devices are simply
419      * indistinguishable, such as two keyboards made by the same manufacturer.
420      * </p><p>
421      * The input device descriptor returned by {@link #getDescriptor} should only be
422      * used when an application needs to remember settings associated with a particular
423      * input device.  For all other purposes when referring to a logical
424      * {@link InputDevice} instance at runtime use the id returned by {@link #getId()}.
425      * </p>
426      *
427      * @return The input device descriptor.
428      */
getDescriptor()429     public String getDescriptor() {
430         return mDescriptor;
431     }
432 
433     /**
434      * Returns true if the device is a virtual input device rather than a real one,
435      * such as the virtual keyboard (see {@link KeyCharacterMap#VIRTUAL_KEYBOARD}).
436      * <p>
437      * Virtual input devices are provided to implement system-level functionality
438      * and should not be seen or configured by users.
439      * </p>
440      *
441      * @return True if the device is virtual.
442      *
443      * @see KeyCharacterMap#VIRTUAL_KEYBOARD
444      */
isVirtual()445     public boolean isVirtual() {
446         return mId < 0;
447     }
448 
449     /**
450      * Returns true if the device is external (connected to USB or Bluetooth or some other
451      * peripheral bus), otherwise it is built-in.
452      *
453      * @return True if the device is external.
454      *
455      * @hide
456      */
isExternal()457     public boolean isExternal() {
458         return mIsExternal;
459     }
460 
461     /**
462      * Returns true if the device is a full keyboard.
463      *
464      * @return True if the device is a full keyboard.
465      *
466      * @hide
467      */
isFullKeyboard()468     public boolean isFullKeyboard() {
469         return (mSources & SOURCE_KEYBOARD) == SOURCE_KEYBOARD
470                 && mKeyboardType == KEYBOARD_TYPE_ALPHABETIC;
471     }
472 
473     /**
474      * Gets the name of this input device.
475      * @return The input device name.
476      */
getName()477     public String getName() {
478         return mName;
479     }
480 
481     /**
482      * Gets the input sources supported by this input device as a combined bitfield.
483      * @return The supported input sources.
484      */
getSources()485     public int getSources() {
486         return mSources;
487     }
488 
489     /**
490      * Gets the keyboard type.
491      * @return The keyboard type.
492      */
getKeyboardType()493     public int getKeyboardType() {
494         return mKeyboardType;
495     }
496 
497     /**
498      * Gets the key character map associated with this input device.
499      * @return The key character map.
500      */
getKeyCharacterMap()501     public KeyCharacterMap getKeyCharacterMap() {
502         return mKeyCharacterMap;
503     }
504 
505     /**
506      * Gets information about the range of values for a particular {@link MotionEvent} axis.
507      * If the device supports multiple sources, the same axis may have different meanings
508      * for each source.  Returns information about the first axis found for any source.
509      * To obtain information about the axis for a specific source, use
510      * {@link #getMotionRange(int, int)}.
511      *
512      * @param axis The axis constant.
513      * @return The range of values, or null if the requested axis is not
514      * supported by the device.
515      *
516      * @see MotionEvent#AXIS_X
517      * @see MotionEvent#AXIS_Y
518      * @see #getSupportedAxes()
519      */
getMotionRange(int axis)520     public MotionRange getMotionRange(int axis) {
521         final int numRanges = mMotionRanges.size();
522         for (int i = 0; i < numRanges; i++) {
523             final MotionRange range = mMotionRanges.get(i);
524             if (range.mAxis == axis) {
525                 return range;
526             }
527         }
528         return null;
529     }
530 
531     /**
532      * Gets information about the range of values for a particular {@link MotionEvent} axis
533      * used by a particular source on the device.
534      * If the device supports multiple sources, the same axis may have different meanings
535      * for each source.
536      *
537      * @param axis The axis constant.
538      * @param source The source for which to return information.
539      * @return The range of values, or null if the requested axis is not
540      * supported by the device.
541      *
542      * @see MotionEvent#AXIS_X
543      * @see MotionEvent#AXIS_Y
544      * @see #getSupportedAxes()
545      */
getMotionRange(int axis, int source)546     public MotionRange getMotionRange(int axis, int source) {
547         final int numRanges = mMotionRanges.size();
548         for (int i = 0; i < numRanges; i++) {
549             final MotionRange range = mMotionRanges.get(i);
550             if (range.mAxis == axis && range.mSource == source) {
551                 return range;
552             }
553         }
554         return null;
555     }
556 
557     /**
558      * Gets the ranges for all axes supported by the device.
559      * @return The motion ranges for the device.
560      *
561      * @see #getMotionRange(int, int)
562      */
getMotionRanges()563     public List<MotionRange> getMotionRanges() {
564         return mMotionRanges;
565     }
566 
567     // Called from native code.
addMotionRange(int axis, int source, float min, float max, float flat, float fuzz)568     private void addMotionRange(int axis, int source,
569             float min, float max, float flat, float fuzz) {
570         mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz));
571     }
572 
573     /**
574      * Gets the vibrator service associated with the device, if there is one.
575      * Even if the device does not have a vibrator, the result is never null.
576      * Use {@link Vibrator#hasVibrator} to determine whether a vibrator is
577      * present.
578      *
579      * Note that the vibrator associated with the device may be different from
580      * the system vibrator.  To obtain an instance of the system vibrator instead, call
581      * {@link Context#getSystemService} with {@link Context#VIBRATOR_SERVICE} as argument.
582      *
583      * @return The vibrator service associated with the device, never null.
584      */
getVibrator()585     public Vibrator getVibrator() {
586         synchronized (mMotionRanges) {
587             if (mVibrator == null) {
588                 if (mHasVibrator) {
589                     mVibrator = InputManager.getInstance().getInputDeviceVibrator(mId);
590                 } else {
591                     mVibrator = NullVibrator.getInstance();
592                 }
593             }
594             return mVibrator;
595         }
596     }
597 
598     /**
599      * Provides information about the range of values for a particular {@link MotionEvent} axis.
600      *
601      * @see InputDevice#getMotionRange(int)
602      */
603     public static final class MotionRange {
604         private int mAxis;
605         private int mSource;
606         private float mMin;
607         private float mMax;
608         private float mFlat;
609         private float mFuzz;
610 
MotionRange(int axis, int source, float min, float max, float flat, float fuzz)611         private MotionRange(int axis, int source, float min, float max, float flat, float fuzz) {
612             mAxis = axis;
613             mSource = source;
614             mMin = min;
615             mMax = max;
616             mFlat = flat;
617             mFuzz = fuzz;
618         }
619 
620         /**
621          * Gets the axis id.
622          * @return The axis id.
623          */
getAxis()624         public int getAxis() {
625             return mAxis;
626         }
627 
628         /**
629          * Gets the source for which the axis is defined.
630          * @return The source.
631          */
getSource()632         public int getSource() {
633             return mSource;
634         }
635 
636         /**
637          * Gets the inclusive minimum value for the axis.
638          * @return The inclusive minimum value.
639          */
getMin()640         public float getMin() {
641             return mMin;
642         }
643 
644         /**
645          * Gets the inclusive maximum value for the axis.
646          * @return The inclusive maximum value.
647          */
getMax()648         public float getMax() {
649             return mMax;
650         }
651 
652         /**
653          * Gets the range of the axis (difference between maximum and minimum).
654          * @return The range of values.
655          */
getRange()656         public float getRange() {
657             return mMax - mMin;
658         }
659 
660         /**
661          * Gets the extent of the center flat position with respect to this axis.
662          * <p>
663          * For example, a flat value of 8 means that the center position is between -8 and +8.
664          * This value is mainly useful for calibrating self-centering devices.
665          * </p>
666          * @return The extent of the center flat position.
667          */
getFlat()668         public float getFlat() {
669             return mFlat;
670         }
671 
672         /**
673          * Gets the error tolerance for input device measurements with respect to this axis.
674          * <p>
675          * For example, a value of 2 indicates that the measured value may be up to +/- 2 units
676          * away from the actual value due to noise and device sensitivity limitations.
677          * </p>
678          * @return The error tolerance.
679          */
getFuzz()680         public float getFuzz() {
681             return mFuzz;
682         }
683     }
684 
685     @Override
writeToParcel(Parcel out, int flags)686     public void writeToParcel(Parcel out, int flags) {
687         out.writeInt(mId);
688         out.writeInt(mGeneration);
689         out.writeString(mName);
690         out.writeString(mDescriptor);
691         out.writeInt(mIsExternal ? 1 : 0);
692         out.writeInt(mSources);
693         out.writeInt(mKeyboardType);
694         mKeyCharacterMap.writeToParcel(out, flags);
695         out.writeInt(mHasVibrator ? 1 : 0);
696 
697         final int numRanges = mMotionRanges.size();
698         for (int i = 0; i < numRanges; i++) {
699             MotionRange range = mMotionRanges.get(i);
700             out.writeInt(range.mAxis);
701             out.writeInt(range.mSource);
702             out.writeFloat(range.mMin);
703             out.writeFloat(range.mMax);
704             out.writeFloat(range.mFlat);
705             out.writeFloat(range.mFuzz);
706         }
707         out.writeInt(-1);
708     }
709 
710     @Override
describeContents()711     public int describeContents() {
712         return 0;
713     }
714 
715     @Override
toString()716     public String toString() {
717         StringBuilder description = new StringBuilder();
718         description.append("Input Device ").append(mId).append(": ").append(mName).append("\n");
719         description.append("  Descriptor: ").append(mDescriptor).append("\n");
720         description.append("  Generation: ").append(mGeneration).append("\n");
721         description.append("  Location: ").append(mIsExternal ? "external" : "built-in").append("\n");
722 
723         description.append("  Keyboard Type: ");
724         switch (mKeyboardType) {
725             case KEYBOARD_TYPE_NONE:
726                 description.append("none");
727                 break;
728             case KEYBOARD_TYPE_NON_ALPHABETIC:
729                 description.append("non-alphabetic");
730                 break;
731             case KEYBOARD_TYPE_ALPHABETIC:
732                 description.append("alphabetic");
733                 break;
734         }
735         description.append("\n");
736 
737         description.append("  Has Vibrator: ").append(mHasVibrator).append("\n");
738 
739         description.append("  Sources: 0x").append(Integer.toHexString(mSources)).append(" (");
740         appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard");
741         appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad");
742         appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen");
743         appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse");
744         appendSourceDescriptionIfApplicable(description, SOURCE_STYLUS, "stylus");
745         appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball");
746         appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad");
747         appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK, "joystick");
748         appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad");
749         description.append(" )\n");
750 
751         final int numAxes = mMotionRanges.size();
752         for (int i = 0; i < numAxes; i++) {
753             MotionRange range = mMotionRanges.get(i);
754             description.append("    ").append(MotionEvent.axisToString(range.mAxis));
755             description.append(": source=0x").append(Integer.toHexString(range.mSource));
756             description.append(" min=").append(range.mMin);
757             description.append(" max=").append(range.mMax);
758             description.append(" flat=").append(range.mFlat);
759             description.append(" fuzz=").append(range.mFuzz);
760             description.append("\n");
761         }
762         return description.toString();
763     }
764 
appendSourceDescriptionIfApplicable(StringBuilder description, int source, String sourceName)765     private void appendSourceDescriptionIfApplicable(StringBuilder description, int source,
766             String sourceName) {
767         if ((mSources & source) == source) {
768             description.append(" ");
769             description.append(sourceName);
770         }
771     }
772 }
773