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