InputDevice.java revision 8d60866e2100db70ecf0502c14768a384514d7e9
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; 23import android.util.Log; 24 25/** 26 * Describes the capabilities of a particular input device. 27 * <p> 28 * Each input device may support multiple classes of input. For example, a multifunction 29 * keyboard may compose the capabilities of a standard keyboard together with a track pad mouse 30 * or other pointing device. 31 * </p><p> 32 * Some input devices present multiple distinguishable sources of input. For example, a 33 * game pad may have two analog joysticks, a directional pad and a full complement of buttons. 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 47 private MotionRange[] mMotionRanges; 48 49 /** 50 * A mask for input source classes. 51 * 52 * Each distinct input source constant has one or more input source class bits set to 53 * specify the desired interpretation for its input events. 54 */ 55 public static final int SOURCE_CLASS_MASK = 0x000000ff; 56 57 /** 58 * The input source has buttons or keys. 59 * Examples: {@link #SOURCE_KEYBOARD}, {@link #SOURCE_GAMEPAD}, {@link #SOURCE_DPAD}. 60 * 61 * A {@link KeyEvent} should be interpreted as a button or key press. 62 * 63 * Use {@link #hasKey} to query whether the device supports a particular button or key. 64 */ 65 public static final int SOURCE_CLASS_BUTTON = 0x00000001; 66 67 /** 68 * The input source is a pointing device associated with a display. 69 * Examples: {@link #SOURCE_TOUCHSCREEN}, {@link #SOURCE_MOUSE}. 70 * 71 * A {@link MotionEvent} should be interpreted as absolute coordinates in 72 * display units according to the {@link View} hierarchy. Pointer down/up indicated when 73 * the finger touches the display or when the selection button is pressed/released. 74 * 75 * Use {@link #getMotionRange} to query the range of the pointing device. Some devices permit 76 * touches outside the display area so the effective range may be somewhat smaller or larger 77 * than the actual display size. 78 */ 79 public static final int SOURCE_CLASS_POINTER = 0x00000002; 80 81 /** 82 * The input source is a trackball navigation device. 83 * Examples: {@link #SOURCE_TRACKBALL}. 84 * 85 * A {@link MotionEvent} should be interpreted as relative movements in device-specific 86 * units used for navigation purposes. Pointer down/up indicates when the selection button 87 * is pressed/released. 88 * 89 * Use {@link #getMotionRange} to query the range of motion. 90 */ 91 public static final int SOURCE_CLASS_TRACKBALL = 0x00000004; 92 93 /** 94 * The input source is an absolute positioning device not associated with a display 95 * (unlike {@link #SOURCE_CLASS_POINTER}). 96 * 97 * A {@link MotionEvent} should be interpreted as absolute coordinates in 98 * device-specific surface units. 99 * 100 * Use {@link #getMotionRange} to query the range of positions. 101 */ 102 public static final int SOURCE_CLASS_POSITION = 0x00000008; 103 104 /** 105 * The input source is a joystick. 106 * 107 * A {@link KeyEvent} should be interpreted as a joystick button press. 108 * 109 * A {@link MotionEvent} should be interpreted in absolute coordinates as a joystick 110 * position in normalized device-specific units nominally between -1.0 and 1.0. 111 * 112 * Use {@link #getMotionRange} to query the range and precision of motion. 113 */ 114 public static final int SOURCE_CLASS_JOYSTICK = 0x00000010; 115 116 /** 117 * The input source is unknown. 118 */ 119 public static final int SOURCE_UNKNOWN = 0x00000000; 120 121 /** 122 * The input source is a keyboard. 123 * 124 * @see #SOURCE_CLASS_BUTTON 125 */ 126 public static final int SOURCE_KEYBOARD = 0x00000100 | SOURCE_CLASS_BUTTON; 127 128 /** 129 * The input source is a DPad. 130 * 131 * @see #SOURCE_CLASS_BUTTON 132 */ 133 public static final int SOURCE_DPAD = 0x00000200 | SOURCE_CLASS_BUTTON; 134 135 /** 136 * The input source is a gamepad. 137 * 138 * @see #SOURCE_CLASS_BUTTON 139 */ 140 public static final int SOURCE_GAMEPAD = 0x00000400 | SOURCE_CLASS_BUTTON; 141 142 /** 143 * The input source is a touch screen pointing device. 144 * 145 * @see #SOURCE_CLASS_POINTER 146 */ 147 public static final int SOURCE_TOUCHSCREEN = 0x00001000 | SOURCE_CLASS_POINTER; 148 149 /** 150 * The input source is a mouse pointing device. 151 * This code is also used for other mouse-like pointing devices such as trackpads 152 * and trackpoints. 153 * 154 * @see #SOURCE_CLASS_POINTER 155 */ 156 public static final int SOURCE_MOUSE = 0x00002000 | SOURCE_CLASS_POINTER; 157 158 /** 159 * The input source is a trackball. 160 * 161 * @see #SOURCE_CLASS_TRACKBALL 162 */ 163 public static final int SOURCE_TRACKBALL = 0x00010000 | SOURCE_CLASS_TRACKBALL; 164 165 /** 166 * The input source is a touch pad or digitizer tablet that is not 167 * associated with a display (unlike {@link #SOURCE_TOUCHSCREEN}). 168 * 169 * @see #SOURCE_CLASS_POSITION 170 */ 171 public static final int SOURCE_TOUCHPAD = 0x00100000 | SOURCE_CLASS_POSITION; 172 173 /** 174 * The input source is a joystick mounted on the left or is a standalone joystick. 175 * 176 * @see #SOURCE_CLASS_JOYSTICK 177 */ 178 public static final int SOURCE_JOYSTICK_LEFT = 0x01000000 | SOURCE_CLASS_JOYSTICK; 179 180 /** 181 * The input source is a joystick mounted on the right. 182 * 183 * @see #SOURCE_CLASS_JOYSTICK 184 */ 185 public static final int SOURCE_JOYSTICK_RIGHT = 0x02000000 | 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.PointerCoords#x}. 195 * 196 * @see #getMotionRange 197 */ 198 public static final int MOTION_RANGE_X = 0; 199 200 /** 201 * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#y}. 202 * 203 * @see #getMotionRange 204 */ 205 public static final int MOTION_RANGE_Y = 1; 206 207 /** 208 * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#pressure}. 209 * 210 * @see #getMotionRange 211 */ 212 public static final int MOTION_RANGE_PRESSURE = 2; 213 214 /** 215 * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#size}. 216 * 217 * @see #getMotionRange 218 */ 219 public static final int MOTION_RANGE_SIZE = 3; 220 221 /** 222 * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#touchMajor}. 223 * 224 * @see #getMotionRange 225 */ 226 public static final int MOTION_RANGE_TOUCH_MAJOR = 4; 227 228 /** 229 * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#touchMinor}. 230 * 231 * @see #getMotionRange 232 */ 233 public static final int MOTION_RANGE_TOUCH_MINOR = 5; 234 235 /** 236 * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#toolMajor}. 237 * 238 * @see #getMotionRange 239 */ 240 public static final int MOTION_RANGE_TOOL_MAJOR = 6; 241 242 /** 243 * Constant for retrieving the range of values for {@link MotionEvent.PointerCoords#toolMinor}. 244 * 245 * @see #getMotionRange 246 */ 247 public static final int MOTION_RANGE_TOOL_MINOR = 7; 248 249 /** 250 * Constant for retrieving the range of values for 251 * {@link MotionEvent.PointerCoords#orientation}. 252 * 253 * @see #getMotionRange 254 */ 255 public static final int MOTION_RANGE_ORIENTATION = 8; 256 257 private static final int MOTION_RANGE_LAST = MOTION_RANGE_ORIENTATION; 258 259 /** 260 * There is no keyboard. 261 */ 262 public static final int KEYBOARD_TYPE_NONE = 0; 263 264 /** 265 * The keyboard is not fully alphabetic. It may be a numeric keypad or an assortment 266 * of buttons that are not mapped as alphabetic keys suitable for text input. 267 */ 268 public static final int KEYBOARD_TYPE_NON_ALPHABETIC = 1; 269 270 /** 271 * The keyboard supports a complement of alphabetic keys. 272 */ 273 public static final int KEYBOARD_TYPE_ALPHABETIC = 2; 274 275 // Called by native code. 276 private InputDevice() { 277 mMotionRanges = new MotionRange[MOTION_RANGE_LAST + 1]; 278 } 279 280 /** 281 * Gets information about the input device with the specified id. 282 * @param id The device id. 283 * @return The input device or null if not found. 284 */ 285 public static InputDevice getDevice(int id) { 286 IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); 287 try { 288 return wm.getInputDevice(id); 289 } catch (RemoteException ex) { 290 throw new RuntimeException( 291 "Could not get input device information from Window Manager.", ex); 292 } 293 } 294 295 /** 296 * Gets the ids of all input devices in the system. 297 * @return The input device ids. 298 */ 299 public static int[] getDeviceIds() { 300 IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); 301 try { 302 return wm.getInputDeviceIds(); 303 } catch (RemoteException ex) { 304 throw new RuntimeException( 305 "Could not get input device ids from Window Manager.", ex); 306 } 307 } 308 309 /** 310 * Gets the input device id. 311 * @return The input device id. 312 */ 313 public int getId() { 314 return mId; 315 } 316 317 /** 318 * Gets the name of this input device. 319 * @return The input device name. 320 */ 321 public String getName() { 322 return mName; 323 } 324 325 /** 326 * Gets the input sources supported by this input device as a combined bitfield. 327 * @return The supported input sources. 328 */ 329 public int getSources() { 330 return mSources; 331 } 332 333 /** 334 * Gets the keyboard type. 335 * @return The keyboard type. 336 */ 337 public int getKeyboardType() { 338 return mKeyboardType; 339 } 340 341 /** 342 * Gets the key character map associated with this input device. 343 * @return The key character map. 344 */ 345 public KeyCharacterMap getKeyCharacterMap() { 346 return KeyCharacterMap.load(mId); 347 } 348 349 /** 350 * Gets information about the range of values for a particular {@link MotionEvent} 351 * coordinate. 352 * @param rangeType The motion range constant. 353 * @return The range of values, or null if the requested coordinate is not 354 * supported by the device. 355 */ 356 public MotionRange getMotionRange(int rangeType) { 357 if (rangeType < 0 || rangeType > MOTION_RANGE_LAST) { 358 throw new IllegalArgumentException("Requested range is out of bounds."); 359 } 360 361 return mMotionRanges[rangeType]; 362 } 363 364 private void addMotionRange(int rangeType, float min, float max, float flat, float fuzz) { 365 if (rangeType >= 0 && rangeType <= MOTION_RANGE_LAST) { 366 MotionRange range = new MotionRange(min, max, flat, fuzz); 367 mMotionRanges[rangeType] = range; 368 } 369 } 370 371 /** 372 * Provides information about the range of values for a particular {@link MotionEvent} 373 * coordinate. 374 */ 375 public static final class MotionRange { 376 private float mMin; 377 private float mMax; 378 private float mFlat; 379 private float mFuzz; 380 381 private MotionRange(float min, float max, float flat, float fuzz) { 382 mMin = min; 383 mMax = max; 384 mFlat = flat; 385 mFuzz = fuzz; 386 } 387 388 /** 389 * Gets the minimum value for the coordinate. 390 * @return The minimum value. 391 */ 392 public float getMin() { 393 return mMin; 394 } 395 396 /** 397 * Gets the maximum value for the coordinate. 398 * @return The minimum value. 399 */ 400 public float getMax() { 401 return mMax; 402 } 403 404 /** 405 * Gets the range of the coordinate (difference between maximum and minimum). 406 * @return The range of values. 407 */ 408 public float getRange() { 409 return mMax - mMin; 410 } 411 412 /** 413 * Gets the extent of the center flat position with respect to this coordinate. 414 * For example, a flat value of 8 means that the center position is between -8 and +8. 415 * This value is mainly useful for calibrating joysticks. 416 * @return The extent of the center flat position. 417 */ 418 public float getFlat() { 419 return mFlat; 420 } 421 422 /** 423 * Gets the error tolerance for input device measurements with respect to this coordinate. 424 * For example, a value of 2 indicates that the measured value may be up to +/- 2 units 425 * away from the actual value due to noise and device sensitivity limitations. 426 * @return The error tolerance. 427 */ 428 public float getFuzz() { 429 return mFuzz; 430 } 431 } 432 433 public static final Parcelable.Creator<InputDevice> CREATOR 434 = new Parcelable.Creator<InputDevice>() { 435 public InputDevice createFromParcel(Parcel in) { 436 InputDevice result = new InputDevice(); 437 result.readFromParcel(in); 438 return result; 439 } 440 441 public InputDevice[] newArray(int size) { 442 return new InputDevice[size]; 443 } 444 }; 445 446 private void readFromParcel(Parcel in) { 447 mId = in.readInt(); 448 mName = in.readString(); 449 mSources = in.readInt(); 450 mKeyboardType = in.readInt(); 451 452 for (;;) { 453 int rangeType = in.readInt(); 454 if (rangeType < 0) { 455 break; 456 } 457 458 addMotionRange(rangeType, 459 in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat()); 460 } 461 } 462 463 @Override 464 public void writeToParcel(Parcel out, int flags) { 465 out.writeInt(mId); 466 out.writeString(mName); 467 out.writeInt(mSources); 468 out.writeInt(mKeyboardType); 469 470 for (int i = 0; i <= MOTION_RANGE_LAST; i++) { 471 MotionRange range = mMotionRanges[i]; 472 if (range != null) { 473 out.writeInt(i); 474 out.writeFloat(range.mMin); 475 out.writeFloat(range.mMax); 476 out.writeFloat(range.mFlat); 477 out.writeFloat(range.mFuzz); 478 } 479 } 480 out.writeInt(-1); 481 } 482 483 @Override 484 public int describeContents() { 485 return 0; 486 } 487 488 @Override 489 public String toString() { 490 StringBuilder description = new StringBuilder(); 491 description.append("Input Device ").append(mId).append(": ").append(mName).append("\n"); 492 493 description.append(" Keyboard Type: "); 494 switch (mKeyboardType) { 495 case KEYBOARD_TYPE_NONE: 496 description.append("none"); 497 break; 498 case KEYBOARD_TYPE_NON_ALPHABETIC: 499 description.append("non-alphabetic"); 500 break; 501 case KEYBOARD_TYPE_ALPHABETIC: 502 description.append("alphabetic"); 503 break; 504 } 505 description.append("\n"); 506 507 description.append(" Sources:"); 508 appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard"); 509 appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad"); 510 appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad"); 511 appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen"); 512 appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse"); 513 appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball"); 514 appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad"); 515 appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK_LEFT, "joystick_left"); 516 appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK_RIGHT, "joystick_right"); 517 description.append("\n"); 518 519 appendRangeDescriptionIfApplicable(description, MOTION_RANGE_X, "x"); 520 appendRangeDescriptionIfApplicable(description, MOTION_RANGE_Y, "y"); 521 appendRangeDescriptionIfApplicable(description, MOTION_RANGE_PRESSURE, "pressure"); 522 appendRangeDescriptionIfApplicable(description, MOTION_RANGE_SIZE, "size"); 523 appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOUCH_MAJOR, "touchMajor"); 524 appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOUCH_MINOR, "touchMinor"); 525 appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOOL_MAJOR, "toolMajor"); 526 appendRangeDescriptionIfApplicable(description, MOTION_RANGE_TOOL_MINOR, "toolMinor"); 527 appendRangeDescriptionIfApplicable(description, MOTION_RANGE_ORIENTATION, "orientation"); 528 529 return description.toString(); 530 } 531 532 private void appendSourceDescriptionIfApplicable(StringBuilder description, int source, 533 String sourceName) { 534 if ((mSources & source) == source) { 535 description.append(" "); 536 description.append(sourceName); 537 } 538 } 539 540 private void appendRangeDescriptionIfApplicable(StringBuilder description, 541 int rangeType, String rangeName) { 542 MotionRange range = mMotionRanges[rangeType]; 543 if (range != null) { 544 description.append(" Range[").append(rangeName); 545 description.append("]: min=").append(range.mMin); 546 description.append(" max=").append(range.mMax); 547 description.append(" flat=").append(range.mFlat); 548 description.append(" fuzz=").append(range.mFuzz); 549 description.append("\n"); 550 } 551 } 552} 553