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