InputDevice.java revision efd3266b719eed5f1b217021c0a9e76e4b274b06
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; 22import android.os.ServiceManager; 23 24import java.util.ArrayList; 25import 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 */ 42public 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 trackball. 159 * 160 * @see #SOURCE_CLASS_TRACKBALL 161 */ 162 public static final int SOURCE_TRACKBALL = 0x00010000 | SOURCE_CLASS_TRACKBALL; 163 164 /** 165 * The input source is a touch pad or digitizer tablet that is not 166 * associated with a display (unlike {@link #SOURCE_TOUCHSCREEN}). 167 * 168 * @see #SOURCE_CLASS_POSITION 169 */ 170 public static final int SOURCE_TOUCHPAD = 0x00100000 | SOURCE_CLASS_POSITION; 171 172 /** 173 * The input source is a joystick. 174 * (It may also be a {@link #SOURCE_GAMEPAD}). 175 * 176 * @see #SOURCE_CLASS_JOYSTICK 177 */ 178 public static final int SOURCE_JOYSTICK = 0x01000000 | SOURCE_CLASS_JOYSTICK; 179 180 /** 181 * A special input source constant that is used when filtering input devices 182 * to match devices that provide any type of input source. 183 */ 184 public static final int SOURCE_ANY = 0xffffff00; 185 186 /** 187 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_X}. 188 * 189 * @see #getMotionRange 190 * @deprecated Use {@link MotionEvent#AXIS_X} instead. 191 */ 192 @Deprecated 193 public static final int MOTION_RANGE_X = MotionEvent.AXIS_X; 194 195 /** 196 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_Y}. 197 * 198 * @see #getMotionRange 199 * @deprecated Use {@link MotionEvent#AXIS_Y} instead. 200 */ 201 @Deprecated 202 public static final int MOTION_RANGE_Y = MotionEvent.AXIS_Y; 203 204 /** 205 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_PRESSURE}. 206 * 207 * @see #getMotionRange 208 * @deprecated Use {@link MotionEvent#AXIS_PRESSURE} instead. 209 */ 210 @Deprecated 211 public static final int MOTION_RANGE_PRESSURE = MotionEvent.AXIS_PRESSURE; 212 213 /** 214 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_SIZE}. 215 * 216 * @see #getMotionRange 217 * @deprecated Use {@link MotionEvent#AXIS_SIZE} instead. 218 */ 219 @Deprecated 220 public static final int MOTION_RANGE_SIZE = MotionEvent.AXIS_SIZE; 221 222 /** 223 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MAJOR}. 224 * 225 * @see #getMotionRange 226 * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MAJOR} instead. 227 */ 228 @Deprecated 229 public static final int MOTION_RANGE_TOUCH_MAJOR = MotionEvent.AXIS_TOUCH_MAJOR; 230 231 /** 232 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MINOR}. 233 * 234 * @see #getMotionRange 235 * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MINOR} instead. 236 */ 237 @Deprecated 238 public static final int MOTION_RANGE_TOUCH_MINOR = MotionEvent.AXIS_TOUCH_MINOR; 239 240 /** 241 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MAJOR}. 242 * 243 * @see #getMotionRange 244 * @deprecated Use {@link MotionEvent#AXIS_TOOL_MAJOR} instead. 245 */ 246 @Deprecated 247 public static final int MOTION_RANGE_TOOL_MAJOR = MotionEvent.AXIS_TOOL_MAJOR; 248 249 /** 250 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MINOR}. 251 * 252 * @see #getMotionRange 253 * @deprecated Use {@link MotionEvent#AXIS_TOOL_MINOR} instead. 254 */ 255 @Deprecated 256 public static final int MOTION_RANGE_TOOL_MINOR = MotionEvent.AXIS_TOOL_MINOR; 257 258 /** 259 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_ORIENTATION}. 260 * 261 * @see #getMotionRange 262 * @deprecated Use {@link MotionEvent#AXIS_ORIENTATION} instead. 263 */ 264 @Deprecated 265 public static final int MOTION_RANGE_ORIENTATION = MotionEvent.AXIS_ORIENTATION; 266 267 /** 268 * There is no keyboard. 269 */ 270 public static final int KEYBOARD_TYPE_NONE = 0; 271 272 /** 273 * The keyboard is not fully alphabetic. It may be a numeric keypad or an assortment 274 * of buttons that are not mapped as alphabetic keys suitable for text input. 275 */ 276 public static final int KEYBOARD_TYPE_NON_ALPHABETIC = 1; 277 278 /** 279 * The keyboard supports a complement of alphabetic keys. 280 */ 281 public static final int KEYBOARD_TYPE_ALPHABETIC = 2; 282 283 // Called by native code. 284 private InputDevice() { 285 } 286 287 /** 288 * Gets information about the input device with the specified id. 289 * @param id The device id. 290 * @return The input device or null if not found. 291 */ 292 public static InputDevice getDevice(int id) { 293 IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); 294 try { 295 return wm.getInputDevice(id); 296 } catch (RemoteException ex) { 297 throw new RuntimeException( 298 "Could not get input device information from Window Manager.", ex); 299 } 300 } 301 302 /** 303 * Gets the ids of all input devices in the system. 304 * @return The input device ids. 305 */ 306 public static int[] getDeviceIds() { 307 IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); 308 try { 309 return wm.getInputDeviceIds(); 310 } catch (RemoteException ex) { 311 throw new RuntimeException( 312 "Could not get input device ids from Window Manager.", ex); 313 } 314 } 315 316 /** 317 * Gets the input device id. 318 * @return The input device id. 319 */ 320 public int getId() { 321 return mId; 322 } 323 324 /** 325 * Gets the name of this input device. 326 * @return The input device name. 327 */ 328 public String getName() { 329 return mName; 330 } 331 332 /** 333 * Gets the input sources supported by this input device as a combined bitfield. 334 * @return The supported input sources. 335 */ 336 public int getSources() { 337 return mSources; 338 } 339 340 /** 341 * Gets the keyboard type. 342 * @return The keyboard type. 343 */ 344 public int getKeyboardType() { 345 return mKeyboardType; 346 } 347 348 /** 349 * Gets the key character map associated with this input device. 350 * @return The key character map. 351 */ 352 public KeyCharacterMap getKeyCharacterMap() { 353 return KeyCharacterMap.load(mId); 354 } 355 356 /** 357 * Gets information about the range of values for a particular {@link MotionEvent} axis. 358 * If the device supports multiple sources, the same axis may have different meanings 359 * for each source. Returns information about the first axis found for any source. 360 * To obtain information about the axis for a specific source, use 361 * {@link #getMotionRange(int, int)}. 362 * 363 * @param axis The axis constant. 364 * @return The range of values, or null if the requested axis is not 365 * supported by the device. 366 * 367 * @see MotionEvent#AXIS_X 368 * @see MotionEvent#AXIS_Y 369 * @see #getSupportedAxes() 370 */ 371 public MotionRange getMotionRange(int axis) { 372 final int numRanges = mMotionRanges.size(); 373 for (int i = 0; i < numRanges; i++) { 374 final MotionRange range = mMotionRanges.get(i); 375 if (range.mAxis == axis) { 376 return range; 377 } 378 } 379 return null; 380 } 381 382 /** 383 * Gets information about the range of values for a particular {@link MotionEvent} axis 384 * used by a particular source on the device. 385 * If the device supports multiple sources, the same axis may have different meanings 386 * for each source. 387 * 388 * @param axis The axis constant. 389 * @param source The source for which to return information. 390 * @return The range of values, or null if the requested axis is not 391 * supported by the device. 392 * 393 * @see MotionEvent#AXIS_X 394 * @see MotionEvent#AXIS_Y 395 * @see #getSupportedAxes() 396 */ 397 public MotionRange getMotionRange(int axis, int source) { 398 final int numRanges = mMotionRanges.size(); 399 for (int i = 0; i < numRanges; i++) { 400 final MotionRange range = mMotionRanges.get(i); 401 if (range.mAxis == axis && range.mSource == source) { 402 return range; 403 } 404 } 405 return null; 406 } 407 408 /** 409 * Gets the ranges for all axes supported by the device. 410 * @return The motion ranges for the device. 411 * 412 * @see #getMotionRange(int, int) 413 */ 414 public List<MotionRange> getMotionRanges() { 415 return mMotionRanges; 416 } 417 418 private void addMotionRange(int axis, int source, 419 float min, float max, float flat, float fuzz) { 420 mMotionRanges.add(new MotionRange(axis, source, min, max, flat, fuzz)); 421 } 422 423 /** 424 * Provides information about the range of values for a particular {@link MotionEvent} axis. 425 * 426 * @see InputDevice#getMotionRange(int) 427 */ 428 public static final class MotionRange { 429 private int mAxis; 430 private int mSource; 431 private float mMin; 432 private float mMax; 433 private float mFlat; 434 private float mFuzz; 435 436 private MotionRange(int axis, int source, float min, float max, float flat, float fuzz) { 437 mAxis = axis; 438 mSource = source; 439 mMin = min; 440 mMax = max; 441 mFlat = flat; 442 mFuzz = fuzz; 443 } 444 445 /** 446 * Gets the axis id. 447 * @return The axis id. 448 */ 449 public int getAxis() { 450 return mAxis; 451 } 452 453 /** 454 * Gets the source for which the axis is defined. 455 * @return The source. 456 */ 457 public int getSource() { 458 return mSource; 459 } 460 461 /** 462 * Gets the inclusive minimum value for the axis. 463 * @return The inclusive minimum value. 464 */ 465 public float getMin() { 466 return mMin; 467 } 468 469 /** 470 * Gets the inclusive maximum value for the axis. 471 * @return The inclusive maximum value. 472 */ 473 public float getMax() { 474 return mMax; 475 } 476 477 /** 478 * Gets the range of the axis (difference between maximum and minimum). 479 * @return The range of values. 480 */ 481 public float getRange() { 482 return mMax - mMin; 483 } 484 485 /** 486 * Gets the extent of the center flat position with respect to this axis. 487 * <p> 488 * For example, a flat value of 8 means that the center position is between -8 and +8. 489 * This value is mainly useful for calibrating self-centering devices. 490 * </p> 491 * @return The extent of the center flat position. 492 */ 493 public float getFlat() { 494 return mFlat; 495 } 496 497 /** 498 * Gets the error tolerance for input device measurements with respect to this axis. 499 * <p> 500 * For example, a value of 2 indicates that the measured value may be up to +/- 2 units 501 * away from the actual value due to noise and device sensitivity limitations. 502 * </p> 503 * @return The error tolerance. 504 */ 505 public float getFuzz() { 506 return mFuzz; 507 } 508 } 509 510 public static final Parcelable.Creator<InputDevice> CREATOR 511 = new Parcelable.Creator<InputDevice>() { 512 public InputDevice createFromParcel(Parcel in) { 513 InputDevice result = new InputDevice(); 514 result.readFromParcel(in); 515 return result; 516 } 517 518 public InputDevice[] newArray(int size) { 519 return new InputDevice[size]; 520 } 521 }; 522 523 private void readFromParcel(Parcel in) { 524 mId = in.readInt(); 525 mName = in.readString(); 526 mSources = in.readInt(); 527 mKeyboardType = in.readInt(); 528 529 for (;;) { 530 int axis = in.readInt(); 531 if (axis < 0) { 532 break; 533 } 534 addMotionRange(axis, in.readInt(), 535 in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat()); 536 } 537 } 538 539 @Override 540 public void writeToParcel(Parcel out, int flags) { 541 out.writeInt(mId); 542 out.writeString(mName); 543 out.writeInt(mSources); 544 out.writeInt(mKeyboardType); 545 546 final int numRanges = mMotionRanges.size(); 547 for (int i = 0; i < numRanges; i++) { 548 MotionRange range = mMotionRanges.get(i); 549 out.writeInt(range.mAxis); 550 out.writeInt(range.mSource); 551 out.writeFloat(range.mMin); 552 out.writeFloat(range.mMax); 553 out.writeFloat(range.mFlat); 554 out.writeFloat(range.mFuzz); 555 } 556 out.writeInt(-1); 557 } 558 559 @Override 560 public int describeContents() { 561 return 0; 562 } 563 564 @Override 565 public String toString() { 566 StringBuilder description = new StringBuilder(); 567 description.append("Input Device ").append(mId).append(": ").append(mName).append("\n"); 568 569 description.append(" Keyboard Type: "); 570 switch (mKeyboardType) { 571 case KEYBOARD_TYPE_NONE: 572 description.append("none"); 573 break; 574 case KEYBOARD_TYPE_NON_ALPHABETIC: 575 description.append("non-alphabetic"); 576 break; 577 case KEYBOARD_TYPE_ALPHABETIC: 578 description.append("alphabetic"); 579 break; 580 } 581 description.append("\n"); 582 583 description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" ("); 584 appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard"); 585 appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad"); 586 appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen"); 587 appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse"); 588 appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball"); 589 appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad"); 590 appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK, "joystick"); 591 appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad"); 592 description.append(" )\n"); 593 594 final int numAxes = mMotionRanges.size(); 595 for (int i = 0; i < numAxes; i++) { 596 MotionRange range = mMotionRanges.get(i); 597 description.append(" ").append(MotionEvent.axisToString(range.mAxis)); 598 description.append(": source=0x").append(Integer.toHexString(range.mSource)); 599 description.append(" min=").append(range.mMin); 600 description.append(" max=").append(range.mMax); 601 description.append(" flat=").append(range.mFlat); 602 description.append(" fuzz=").append(range.mFuzz); 603 description.append("\n"); 604 } 605 return description.toString(); 606 } 607 608 private void appendSourceDescriptionIfApplicable(StringBuilder description, int source, 609 String sourceName) { 610 if ((mSources & source) == source) { 611 description.append(" "); 612 description.append(sourceName); 613 } 614 } 615} 616