InputDevice.java revision 9df6e7a926ce480baf70e97ee1b9ea387193f6ad
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.view; 18 19import android.os.Parcel; 20import android.os.Parcelable; 21import android.os.RemoteException; 22 23import java.util.ArrayList; 24import 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 multi-function 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 */ 41public 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 * This source indicates pretty much anything that has buttons. Use 123 * {@link #getKeyboardType()} to determine whether the keyboard has alphabetic keys 124 * and can be used to enter text. 125 * 126 * @see #SOURCE_CLASS_BUTTON 127 */ 128 public static final int SOURCE_KEYBOARD = 0x00000100 | SOURCE_CLASS_BUTTON; 129 130 /** 131 * The input source is a DPad. 132 * 133 * @see #SOURCE_CLASS_BUTTON 134 */ 135 public static final int SOURCE_DPAD = 0x00000200 | SOURCE_CLASS_BUTTON; 136 137 /** 138 * The input source is a game pad. 139 * (It may also be a {@link #SOURCE_JOYSTICK}). 140 * 141 * @see #SOURCE_CLASS_BUTTON 142 */ 143 public static final int SOURCE_GAMEPAD = 0x00000400 | SOURCE_CLASS_BUTTON; 144 145 /** 146 * The input source is a touch screen pointing device. 147 * 148 * @see #SOURCE_CLASS_POINTER 149 */ 150 public static final int SOURCE_TOUCHSCREEN = 0x00001000 | SOURCE_CLASS_POINTER; 151 152 /** 153 * The input source is a mouse pointing device. 154 * This code is also used for other mouse-like pointing devices such as trackpads 155 * and trackpoints. 156 * 157 * @see #SOURCE_CLASS_POINTER 158 */ 159 public static final int SOURCE_MOUSE = 0x00002000 | SOURCE_CLASS_POINTER; 160 161 /** 162 * The input source is a stylus pointing device. 163 * 164 * @see #SOURCE_CLASS_POINTER 165 */ 166 public static final int SOURCE_STYLUS = 0x00004000 | SOURCE_CLASS_POINTER; 167 168 /** 169 * The input source is a trackball. 170 * 171 * @see #SOURCE_CLASS_TRACKBALL 172 */ 173 public static final int SOURCE_TRACKBALL = 0x00010000 | SOURCE_CLASS_TRACKBALL; 174 175 /** 176 * The input source is a touch pad or digitizer tablet that is not 177 * associated with a display (unlike {@link #SOURCE_TOUCHSCREEN}). 178 * 179 * @see #SOURCE_CLASS_POSITION 180 */ 181 public static final int SOURCE_TOUCHPAD = 0x00100000 | SOURCE_CLASS_POSITION; 182 183 /** 184 * The input source is a joystick. 185 * (It may also be a {@link #SOURCE_GAMEPAD}). 186 * 187 * @see #SOURCE_CLASS_JOYSTICK 188 */ 189 public static final int SOURCE_JOYSTICK = 0x01000000 | SOURCE_CLASS_JOYSTICK; 190 191 /** 192 * A special input source constant that is used when filtering input devices 193 * to match devices that provide any type of input source. 194 */ 195 public static final int SOURCE_ANY = 0xffffff00; 196 197 /** 198 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_X}. 199 * 200 * @see #getMotionRange 201 * @deprecated Use {@link MotionEvent#AXIS_X} instead. 202 */ 203 @Deprecated 204 public static final int MOTION_RANGE_X = MotionEvent.AXIS_X; 205 206 /** 207 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_Y}. 208 * 209 * @see #getMotionRange 210 * @deprecated Use {@link MotionEvent#AXIS_Y} instead. 211 */ 212 @Deprecated 213 public static final int MOTION_RANGE_Y = MotionEvent.AXIS_Y; 214 215 /** 216 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_PRESSURE}. 217 * 218 * @see #getMotionRange 219 * @deprecated Use {@link MotionEvent#AXIS_PRESSURE} instead. 220 */ 221 @Deprecated 222 public static final int MOTION_RANGE_PRESSURE = MotionEvent.AXIS_PRESSURE; 223 224 /** 225 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_SIZE}. 226 * 227 * @see #getMotionRange 228 * @deprecated Use {@link MotionEvent#AXIS_SIZE} instead. 229 */ 230 @Deprecated 231 public static final int MOTION_RANGE_SIZE = MotionEvent.AXIS_SIZE; 232 233 /** 234 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MAJOR}. 235 * 236 * @see #getMotionRange 237 * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MAJOR} instead. 238 */ 239 @Deprecated 240 public static final int MOTION_RANGE_TOUCH_MAJOR = MotionEvent.AXIS_TOUCH_MAJOR; 241 242 /** 243 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MINOR}. 244 * 245 * @see #getMotionRange 246 * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MINOR} instead. 247 */ 248 @Deprecated 249 public static final int MOTION_RANGE_TOUCH_MINOR = MotionEvent.AXIS_TOUCH_MINOR; 250 251 /** 252 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MAJOR}. 253 * 254 * @see #getMotionRange 255 * @deprecated Use {@link MotionEvent#AXIS_TOOL_MAJOR} instead. 256 */ 257 @Deprecated 258 public static final int MOTION_RANGE_TOOL_MAJOR = MotionEvent.AXIS_TOOL_MAJOR; 259 260 /** 261 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MINOR}. 262 * 263 * @see #getMotionRange 264 * @deprecated Use {@link MotionEvent#AXIS_TOOL_MINOR} instead. 265 */ 266 @Deprecated 267 public static final int MOTION_RANGE_TOOL_MINOR = MotionEvent.AXIS_TOOL_MINOR; 268 269 /** 270 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_ORIENTATION}. 271 * 272 * @see #getMotionRange 273 * @deprecated Use {@link MotionEvent#AXIS_ORIENTATION} instead. 274 */ 275 @Deprecated 276 public static final int MOTION_RANGE_ORIENTATION = MotionEvent.AXIS_ORIENTATION; 277 278 /** 279 * There is no keyboard. 280 */ 281 public static final int KEYBOARD_TYPE_NONE = 0; 282 283 /** 284 * The keyboard is not fully alphabetic. It may be a numeric keypad or an assortment 285 * of buttons that are not mapped as alphabetic keys suitable for text input. 286 */ 287 public static final int KEYBOARD_TYPE_NON_ALPHABETIC = 1; 288 289 /** 290 * The keyboard supports a complement of alphabetic keys. 291 */ 292 public static final int KEYBOARD_TYPE_ALPHABETIC = 2; 293 294 // Called by native code. 295 private InputDevice() { 296 } 297 298 /** 299 * Gets information about the input device with the specified id. 300 * @param id The device id. 301 * @return The input device or null if not found. 302 */ 303 public static InputDevice getDevice(int id) { 304 IWindowManager wm = Display.getWindowManager(); 305 try { 306 return wm.getInputDevice(id); 307 } catch (RemoteException ex) { 308 throw new RuntimeException( 309 "Could not get input device information from Window Manager.", ex); 310 } 311 } 312 313 /** 314 * Gets the ids of all input devices in the system. 315 * @return The input device ids. 316 */ 317 public static int[] getDeviceIds() { 318 IWindowManager wm = Display.getWindowManager(); 319 try { 320 return wm.getInputDeviceIds(); 321 } catch (RemoteException ex) { 322 throw new RuntimeException( 323 "Could not get input device ids from Window Manager.", ex); 324 } 325 } 326 327 /** 328 * Gets the input device id. 329 * <p> 330 * Each input device receives a unique id when it is first configured 331 * by the system. The input device id may change when the system is restarted or if the 332 * input device is disconnected, reconnected or reconfigured at any time. 333 * If you require a stable identifier for a device that persists across 334 * boots and reconfigurations, use {@link #getDescriptor()}. 335 * </p> 336 * 337 * @return The input device id. 338 */ 339 public int getId() { 340 return mId; 341 } 342 343 /** 344 * Gets the input device descriptor, which is a stable identifier for an input device. 345 * <p> 346 * An input device descriptor uniquely identifies an input device. Its value 347 * is intended to be persistent across system restarts, and should not change even 348 * if the input device is disconnected, reconnected or reconfigured at any time. 349 * </p> 350 * 351 * @return The input device descriptor. 352 */ 353 public String getDescriptor() { 354 return "PLACEHOLDER"; // TODO: implement for real 355 } 356 357 /** 358 * Gets the name of this input device. 359 * @return The input device name. 360 */ 361 public String getName() { 362 return mName; 363 } 364 365 /** 366 * Gets the input sources supported by this input device as a combined bitfield. 367 * @return The supported input sources. 368 */ 369 public int getSources() { 370 return mSources; 371 } 372 373 /** 374 * Gets the keyboard type. 375 * @return The keyboard type. 376 */ 377 public int getKeyboardType() { 378 return mKeyboardType; 379 } 380 381 /** 382 * Gets the key character map associated with this input device. 383 * @return The key character map. 384 */ 385 public KeyCharacterMap getKeyCharacterMap() { 386 return KeyCharacterMap.load(mId); 387 } 388 389 String getKeyCharacterMapFile() { 390 return mKeyCharacterMapFile; 391 } 392 393 /** 394 * Gets information about the range of values for a particular {@link MotionEvent} axis. 395 * If the device supports multiple sources, the same axis may have different meanings 396 * for each source. Returns information about the first axis found for any source. 397 * To obtain information about the axis for a specific source, use 398 * {@link #getMotionRange(int, int)}. 399 * 400 * @param axis The axis constant. 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) { 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) { 413 return range; 414 } 415 } 416 return null; 417 } 418 419 /** 420 * Gets information about the range of values for a particular {@link MotionEvent} axis 421 * used by a particular source on the device. 422 * If the device supports multiple sources, the same axis may have different meanings 423 * for each source. 424 * 425 * @param axis The axis constant. 426 * @param source The source for which to return information. 427 * @return The range of values, or null if the requested axis is not 428 * supported by the device. 429 * 430 * @see MotionEvent#AXIS_X 431 * @see MotionEvent#AXIS_Y 432 * @see #getSupportedAxes() 433 */ 434 public MotionRange getMotionRange(int axis, int source) { 435 final int numRanges = mMotionRanges.size(); 436 for (int i = 0; i < numRanges; i++) { 437 final MotionRange range = mMotionRanges.get(i); 438 if (range.mAxis == axis && range.mSource == source) { 439 return range; 440 } 441 } 442 return null; 443 } 444 445 /** 446 * Gets the ranges for all axes supported by the device. 447 * @return The motion ranges for the device. 448 * 449 * @see #getMotionRange(int, int) 450 */ 451 public List<MotionRange> getMotionRanges() { 452 return mMotionRanges; 453 } 454 455 private void addMotionRange(int axis, int source, 456 float min, float max, float flat, float fuzz) { 457 mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz)); 458 } 459 460 /** 461 * Provides information about the range of values for a particular {@link MotionEvent} axis. 462 * 463 * @see InputDevice#getMotionRange(int) 464 */ 465 public static final class MotionRange { 466 private int mAxis; 467 private int mSource; 468 private float mMin; 469 private float mMax; 470 private float mFlat; 471 private float mFuzz; 472 473 private MotionRange(int axis, int source, float min, float max, float flat, float fuzz) { 474 mAxis = axis; 475 mSource = source; 476 mMin = min; 477 mMax = max; 478 mFlat = flat; 479 mFuzz = fuzz; 480 } 481 482 /** 483 * Gets the axis id. 484 * @return The axis id. 485 */ 486 public int getAxis() { 487 return mAxis; 488 } 489 490 /** 491 * Gets the source for which the axis is defined. 492 * @return The source. 493 */ 494 public int getSource() { 495 return mSource; 496 } 497 498 /** 499 * Gets the inclusive minimum value for the axis. 500 * @return The inclusive minimum value. 501 */ 502 public float getMin() { 503 return mMin; 504 } 505 506 /** 507 * Gets the inclusive maximum value for the axis. 508 * @return The inclusive maximum value. 509 */ 510 public float getMax() { 511 return mMax; 512 } 513 514 /** 515 * Gets the range of the axis (difference between maximum and minimum). 516 * @return The range of values. 517 */ 518 public float getRange() { 519 return mMax - mMin; 520 } 521 522 /** 523 * Gets the extent of the center flat position with respect to this axis. 524 * <p> 525 * For example, a flat value of 8 means that the center position is between -8 and +8. 526 * This value is mainly useful for calibrating self-centering devices. 527 * </p> 528 * @return The extent of the center flat position. 529 */ 530 public float getFlat() { 531 return mFlat; 532 } 533 534 /** 535 * Gets the error tolerance for input device measurements with respect to this axis. 536 * <p> 537 * For example, a value of 2 indicates that the measured value may be up to +/- 2 units 538 * away from the actual value due to noise and device sensitivity limitations. 539 * </p> 540 * @return The error tolerance. 541 */ 542 public float getFuzz() { 543 return mFuzz; 544 } 545 } 546 547 public static final Parcelable.Creator<InputDevice> CREATOR 548 = new Parcelable.Creator<InputDevice>() { 549 public InputDevice createFromParcel(Parcel in) { 550 InputDevice result = new InputDevice(); 551 result.readFromParcel(in); 552 return result; 553 } 554 555 public InputDevice[] newArray(int size) { 556 return new InputDevice[size]; 557 } 558 }; 559 560 private void readFromParcel(Parcel in) { 561 mId = in.readInt(); 562 mName = in.readString(); 563 mSources = in.readInt(); 564 mKeyboardType = in.readInt(); 565 mKeyCharacterMapFile = in.readString(); 566 567 for (;;) { 568 int axis = in.readInt(); 569 if (axis < 0) { 570 break; 571 } 572 addMotionRange(axis, in.readInt(), 573 in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat()); 574 } 575 } 576 577 @Override 578 public void writeToParcel(Parcel out, int flags) { 579 out.writeInt(mId); 580 out.writeString(mName); 581 out.writeInt(mSources); 582 out.writeInt(mKeyboardType); 583 out.writeString(mKeyCharacterMapFile); 584 585 final int numRanges = mMotionRanges.size(); 586 for (int i = 0; i < numRanges; i++) { 587 MotionRange range = mMotionRanges.get(i); 588 out.writeInt(range.mAxis); 589 out.writeInt(range.mSource); 590 out.writeFloat(range.mMin); 591 out.writeFloat(range.mMax); 592 out.writeFloat(range.mFlat); 593 out.writeFloat(range.mFuzz); 594 } 595 out.writeInt(-1); 596 } 597 598 @Override 599 public int describeContents() { 600 return 0; 601 } 602 603 @Override 604 public String toString() { 605 StringBuilder description = new StringBuilder(); 606 description.append("Input Device ").append(mId).append(": ").append(mName).append("\n"); 607 608 description.append(" Keyboard Type: "); 609 switch (mKeyboardType) { 610 case KEYBOARD_TYPE_NONE: 611 description.append("none"); 612 break; 613 case KEYBOARD_TYPE_NON_ALPHABETIC: 614 description.append("non-alphabetic"); 615 break; 616 case KEYBOARD_TYPE_ALPHABETIC: 617 description.append("alphabetic"); 618 break; 619 } 620 description.append("\n"); 621 622 description.append(" Key Character Map: ").append(mKeyCharacterMapFile).append("\n"); 623 624 description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" ("); 625 appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard"); 626 appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad"); 627 appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen"); 628 appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse"); 629 appendSourceDescriptionIfApplicable(description, SOURCE_STYLUS, "stylus"); 630 appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball"); 631 appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad"); 632 appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK, "joystick"); 633 appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad"); 634 description.append(" )\n"); 635 636 final int numAxes = mMotionRanges.size(); 637 for (int i = 0; i < numAxes; i++) { 638 MotionRange range = mMotionRanges.get(i); 639 description.append(" ").append(MotionEvent.axisToString(range.mAxis)); 640 description.append(": source=0x").append(Integer.toHexString(range.mSource)); 641 description.append(" min=").append(range.mMin); 642 description.append(" max=").append(range.mMax); 643 description.append(" flat=").append(range.mFlat); 644 description.append(" fuzz=").append(range.mFuzz); 645 description.append("\n"); 646 } 647 return description.toString(); 648 } 649 650 private void appendSourceDescriptionIfApplicable(StringBuilder description, int source, 651 String sourceName) { 652 if ((mSources & source) == source) { 653 description.append(" "); 654 description.append(sourceName); 655 } 656 } 657} 658