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.os.Parcel;
     20 import android.os.Parcelable;
     21 import android.os.RemoteException;
     22 
     23 import java.util.ArrayList;
     24 import java.util.List;
     25 
     26 /**
     27  * Describes the capabilities of a particular input device.
     28  * <p>
     29  * Each input device may support multiple classes of input.  For example, a multifunction
     30  * keyboard may compose the capabilities of a standard keyboard together with a track pad mouse
     31  * or other pointing device.
     32  * </p><p>
     33  * Some input devices present multiple distinguishable sources of input.
     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  */
     41 public final class InputDevice implements Parcelable {
     42     private int mId;
     43     private String mName;
     44     private int mSources;
     45     private int mKeyboardType;
     46     private String mKeyCharacterMapFile;
     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     String getKeyCharacterMapFile() {
    364         return mKeyCharacterMapFile;
    365     }
    366 
    367     /**
    368      * Gets information about the range of values for a particular {@link MotionEvent} axis.
    369      * If the device supports multiple sources, the same axis may have different meanings
    370      * for each source.  Returns information about the first axis found for any source.
    371      * To obtain information about the axis for a specific source, use
    372      * {@link #getMotionRange(int, int)}.
    373      *
    374      * @param axis The axis constant.
    375      * @return The range of values, or null if the requested axis is not
    376      * supported by the device.
    377      *
    378      * @see MotionEvent#AXIS_X
    379      * @see MotionEvent#AXIS_Y
    380      * @see #getSupportedAxes()
    381      */
    382     public MotionRange getMotionRange(int axis) {
    383         final int numRanges = mMotionRanges.size();
    384         for (int i = 0; i < numRanges; i++) {
    385             final MotionRange range = mMotionRanges.get(i);
    386             if (range.mAxis == axis) {
    387                 return range;
    388             }
    389         }
    390         return null;
    391     }
    392 
    393     /**
    394      * Gets information about the range of values for a particular {@link MotionEvent} axis
    395      * used by a particular source on the device.
    396      * If the device supports multiple sources, the same axis may have different meanings
    397      * for each source.
    398      *
    399      * @param axis The axis constant.
    400      * @param source The source for which to return information.
    401      * @return The range of values, or null if the requested axis is not
    402      * supported by the device.
    403      *
    404      * @see MotionEvent#AXIS_X
    405      * @see MotionEvent#AXIS_Y
    406      * @see #getSupportedAxes()
    407      */
    408     public MotionRange getMotionRange(int axis, int source) {
    409         final int numRanges = mMotionRanges.size();
    410         for (int i = 0; i < numRanges; i++) {
    411             final MotionRange range = mMotionRanges.get(i);
    412             if (range.mAxis == axis && range.mSource == source) {
    413                 return range;
    414             }
    415         }
    416         return null;
    417     }
    418 
    419     /**
    420      * Gets the ranges for all axes supported by the device.
    421      * @return The motion ranges for the device.
    422      *
    423      * @see #getMotionRange(int, int)
    424      */
    425     public List<MotionRange> getMotionRanges() {
    426         return mMotionRanges;
    427     }
    428 
    429     private void addMotionRange(int axis, int source,
    430             float min, float max, float flat, float fuzz) {
    431         mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz));
    432     }
    433 
    434     /**
    435      * Provides information about the range of values for a particular {@link MotionEvent} axis.
    436      *
    437      * @see InputDevice#getMotionRange(int)
    438      */
    439     public static final class MotionRange {
    440         private int mAxis;
    441         private int mSource;
    442         private float mMin;
    443         private float mMax;
    444         private float mFlat;
    445         private float mFuzz;
    446 
    447         private MotionRange(int axis, int source, float min, float max, float flat, float fuzz) {
    448             mAxis = axis;
    449             mSource = source;
    450             mMin = min;
    451             mMax = max;
    452             mFlat = flat;
    453             mFuzz = fuzz;
    454         }
    455 
    456         /**
    457          * Gets the axis id.
    458          * @return The axis id.
    459          */
    460         public int getAxis() {
    461             return mAxis;
    462         }
    463 
    464         /**
    465          * Gets the source for which the axis is defined.
    466          * @return The source.
    467          */
    468         public int getSource() {
    469             return mSource;
    470         }
    471 
    472         /**
    473          * Gets the inclusive minimum value for the axis.
    474          * @return The inclusive minimum value.
    475          */
    476         public float getMin() {
    477             return mMin;
    478         }
    479 
    480         /**
    481          * Gets the inclusive maximum value for the axis.
    482          * @return The inclusive maximum value.
    483          */
    484         public float getMax() {
    485             return mMax;
    486         }
    487 
    488         /**
    489          * Gets the range of the axis (difference between maximum and minimum).
    490          * @return The range of values.
    491          */
    492         public float getRange() {
    493             return mMax - mMin;
    494         }
    495 
    496         /**
    497          * Gets the extent of the center flat position with respect to this axis.
    498          * <p>
    499          * For example, a flat value of 8 means that the center position is between -8 and +8.
    500          * This value is mainly useful for calibrating self-centering devices.
    501          * </p>
    502          * @return The extent of the center flat position.
    503          */
    504         public float getFlat() {
    505             return mFlat;
    506         }
    507 
    508         /**
    509          * Gets the error tolerance for input device measurements with respect to this axis.
    510          * <p>
    511          * For example, a value of 2 indicates that the measured value may be up to +/- 2 units
    512          * away from the actual value due to noise and device sensitivity limitations.
    513          * </p>
    514          * @return The error tolerance.
    515          */
    516         public float getFuzz() {
    517             return mFuzz;
    518         }
    519     }
    520 
    521     public static final Parcelable.Creator<InputDevice> CREATOR
    522             = new Parcelable.Creator<InputDevice>() {
    523         public InputDevice createFromParcel(Parcel in) {
    524             InputDevice result = new InputDevice();
    525             result.readFromParcel(in);
    526             return result;
    527         }
    528 
    529         public InputDevice[] newArray(int size) {
    530             return new InputDevice[size];
    531         }
    532     };
    533 
    534     private void readFromParcel(Parcel in) {
    535         mId = in.readInt();
    536         mName = in.readString();
    537         mSources = in.readInt();
    538         mKeyboardType = in.readInt();
    539         mKeyCharacterMapFile = in.readString();
    540 
    541         for (;;) {
    542             int axis = in.readInt();
    543             if (axis < 0) {
    544                 break;
    545             }
    546             addMotionRange(axis, in.readInt(),
    547                     in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat());
    548         }
    549     }
    550 
    551     @Override
    552     public void writeToParcel(Parcel out, int flags) {
    553         out.writeInt(mId);
    554         out.writeString(mName);
    555         out.writeInt(mSources);
    556         out.writeInt(mKeyboardType);
    557         out.writeString(mKeyCharacterMapFile);
    558 
    559         final int numRanges = mMotionRanges.size();
    560         for (int i = 0; i < numRanges; i++) {
    561             MotionRange range = mMotionRanges.get(i);
    562             out.writeInt(range.mAxis);
    563             out.writeInt(range.mSource);
    564             out.writeFloat(range.mMin);
    565             out.writeFloat(range.mMax);
    566             out.writeFloat(range.mFlat);
    567             out.writeFloat(range.mFuzz);
    568         }
    569         out.writeInt(-1);
    570     }
    571 
    572     @Override
    573     public int describeContents() {
    574         return 0;
    575     }
    576 
    577     @Override
    578     public String toString() {
    579         StringBuilder description = new StringBuilder();
    580         description.append("Input Device ").append(mId).append(": ").append(mName).append("\n");
    581 
    582         description.append("  Keyboard Type: ");
    583         switch (mKeyboardType) {
    584             case KEYBOARD_TYPE_NONE:
    585                 description.append("none");
    586                 break;
    587             case KEYBOARD_TYPE_NON_ALPHABETIC:
    588                 description.append("non-alphabetic");
    589                 break;
    590             case KEYBOARD_TYPE_ALPHABETIC:
    591                 description.append("alphabetic");
    592                 break;
    593         }
    594         description.append("\n");
    595 
    596         description.append("  Key Character Map: ").append(mKeyCharacterMapFile).append("\n");
    597 
    598         description.append("  Sources: 0x").append(Integer.toHexString(mSources)).append(" (");
    599         appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard");
    600         appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad");
    601         appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen");
    602         appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse");
    603         appendSourceDescriptionIfApplicable(description, SOURCE_STYLUS, "stylus");
    604         appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball");
    605         appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad");
    606         appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK, "joystick");
    607         appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad");
    608         description.append(" )\n");
    609 
    610         final int numAxes = mMotionRanges.size();
    611         for (int i = 0; i < numAxes; i++) {
    612             MotionRange range = mMotionRanges.get(i);
    613             description.append("    ").append(MotionEvent.axisToString(range.mAxis));
    614             description.append(": source=0x").append(Integer.toHexString(range.mSource));
    615             description.append(" min=").append(range.mMin);
    616             description.append(" max=").append(range.mMax);
    617             description.append(" flat=").append(range.mFlat);
    618             description.append(" fuzz=").append(range.mFuzz);
    619             description.append("\n");
    620         }
    621         return description.toString();
    622     }
    623 
    624     private void appendSourceDescriptionIfApplicable(StringBuilder description, int source,
    625             String sourceName) {
    626         if ((mSources & source) == source) {
    627             description.append(" ");
    628             description.append(sourceName);
    629         }
    630     }
    631 }
    632