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.content.Context; 20import android.hardware.input.InputManager; 21import android.os.Parcel; 22import android.os.Parcelable; 23import android.os.Vibrator; 24import android.os.NullVibrator; 25 26import java.util.ArrayList; 27import 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 */ 44public 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. 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 485 public int getSources() { 486 return mSources; 487 } 488 489 /** 490 * Gets the keyboard type. 491 * @return The keyboard type. 492 */ 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 */ 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 */ 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 */ 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 */ 563 public List<MotionRange> getMotionRanges() { 564 return mMotionRanges; 565 } 566 567 // Called from native code. 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 680 public float getFuzz() { 681 return mFuzz; 682 } 683 } 684 685 @Override 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 711 public int describeContents() { 712 return 0; 713 } 714 715 @Override 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 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