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