InputDevice.java revision 91c69ab01539f7ba28708f41ec1835cc2920d0a0
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.SparseArray; 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. 33 * Applications can query the framework about the characteristics of each distinct source. 34 * </p><p> 35 * As a further wrinkle, different kinds of input sources uses different coordinate systems 36 * to describe motion events. Refer to the comments on the input source constants for 37 * the appropriate interpretation. 38 * </p> 39 */ 40public final class InputDevice implements Parcelable { 41 private int mId; 42 private String mName; 43 private int mSources; 44 private int mKeyboardType; 45 46 private final SparseArray<MotionRange> mMotionRanges = new SparseArray<MotionRange>(); 47 48 /** 49 * A mask for input source classes. 50 * 51 * Each distinct input source constant has one or more input source class bits set to 52 * specify the desired interpretation for its input events. 53 */ 54 public static final int SOURCE_CLASS_MASK = 0x000000ff; 55 56 /** 57 * The input source has buttons or keys. 58 * Examples: {@link #SOURCE_KEYBOARD}, {@link #SOURCE_DPAD}. 59 * 60 * A {@link KeyEvent} should be interpreted as a button or key press. 61 * 62 * Use {@link #getKeyCharacterMap} to query the device's button and key mappings. 63 */ 64 public static final int SOURCE_CLASS_BUTTON = 0x00000001; 65 66 /** 67 * The input source is a pointing device associated with a display. 68 * Examples: {@link #SOURCE_TOUCHSCREEN}, {@link #SOURCE_MOUSE}. 69 * 70 * A {@link MotionEvent} should be interpreted as absolute coordinates in 71 * display units according to the {@link View} hierarchy. Pointer down/up indicated when 72 * the finger touches the display or when the selection button is pressed/released. 73 * 74 * Use {@link #getMotionRange} to query the range of the pointing device. Some devices permit 75 * touches outside the display area so the effective range may be somewhat smaller or larger 76 * than the actual display size. 77 */ 78 public static final int SOURCE_CLASS_POINTER = 0x00000002; 79 80 /** 81 * The input source is a trackball navigation device. 82 * Examples: {@link #SOURCE_TRACKBALL}. 83 * 84 * A {@link MotionEvent} should be interpreted as relative movements in device-specific 85 * units used for navigation purposes. Pointer down/up indicates when the selection button 86 * is pressed/released. 87 * 88 * Use {@link #getMotionRange} to query the range of motion. 89 */ 90 public static final int SOURCE_CLASS_TRACKBALL = 0x00000004; 91 92 /** 93 * The input source is an absolute positioning device not associated with a display 94 * (unlike {@link #SOURCE_CLASS_POINTER}). 95 * 96 * A {@link MotionEvent} should be interpreted as absolute coordinates in 97 * device-specific surface units. 98 * 99 * Use {@link #getMotionRange} to query the range of positions. 100 */ 101 public static final int SOURCE_CLASS_POSITION = 0x00000008; 102 103 /** 104 * The input source is a joystick. 105 * 106 * A {@link MotionEvent} should be interpreted as absolute joystick movements. 107 * 108 * Use {@link #getMotionRange} to query the range of positions. 109 */ 110 public static final int SOURCE_CLASS_JOYSTICK = 0x00000010; 111 112 /** 113 * The input source is unknown. 114 */ 115 public static final int SOURCE_UNKNOWN = 0x00000000; 116 117 /** 118 * The input source is a keyboard. 119 * 120 * @see #SOURCE_CLASS_BUTTON 121 */ 122 public static final int SOURCE_KEYBOARD = 0x00000100 | SOURCE_CLASS_BUTTON; 123 124 /** 125 * The input source is a DPad. 126 * 127 * @see #SOURCE_CLASS_BUTTON 128 */ 129 public static final int SOURCE_DPAD = 0x00000200 | SOURCE_CLASS_BUTTON; 130 131 /** 132 * The input source is a game pad. 133 * (It may also be a {@link #SOURCE_JOYSTICK}). 134 * 135 * @see #SOURCE_CLASS_BUTTON 136 */ 137 public static final int SOURCE_GAMEPAD = 0x00000400 | SOURCE_CLASS_BUTTON; 138 139 /** 140 * The input source is a touch screen pointing device. 141 * 142 * @see #SOURCE_CLASS_POINTER 143 */ 144 public static final int SOURCE_TOUCHSCREEN = 0x00001000 | SOURCE_CLASS_POINTER; 145 146 /** 147 * The input source is a mouse pointing device. 148 * This code is also used for other mouse-like pointing devices such as trackpads 149 * and trackpoints. 150 * 151 * @see #SOURCE_CLASS_POINTER 152 */ 153 public static final int SOURCE_MOUSE = 0x00002000 | SOURCE_CLASS_POINTER; 154 155 /** 156 * The input source is a trackball. 157 * 158 * @see #SOURCE_CLASS_TRACKBALL 159 */ 160 public static final int SOURCE_TRACKBALL = 0x00010000 | SOURCE_CLASS_TRACKBALL; 161 162 /** 163 * The input source is a touch pad or digitizer tablet that is not 164 * associated with a display (unlike {@link #SOURCE_TOUCHSCREEN}). 165 * 166 * @see #SOURCE_CLASS_POSITION 167 */ 168 public static final int SOURCE_TOUCHPAD = 0x00100000 | SOURCE_CLASS_POSITION; 169 170 /** 171 * The input source is a joystick. 172 * (It may also be a {@link #SOURCE_GAMEPAD}). 173 * 174 * @see #SOURCE_CLASS_JOYSTICK 175 */ 176 public static final int SOURCE_JOYSTICK = 0x01000000 | SOURCE_CLASS_JOYSTICK; 177 178 /** 179 * A special input source constant that is used when filtering input devices 180 * to match devices that provide any type of input source. 181 */ 182 public static final int SOURCE_ANY = 0xffffff00; 183 184 /** 185 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_X}. 186 * 187 * @see #getMotionRange 188 * @deprecated Use {@link MotionEvent#AXIS_X} instead. 189 */ 190 @Deprecated 191 public static final int MOTION_RANGE_X = MotionEvent.AXIS_X; 192 193 /** 194 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_Y}. 195 * 196 * @see #getMotionRange 197 * @deprecated Use {@link MotionEvent#AXIS_Y} instead. 198 */ 199 @Deprecated 200 public static final int MOTION_RANGE_Y = MotionEvent.AXIS_Y; 201 202 /** 203 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_PRESSURE}. 204 * 205 * @see #getMotionRange 206 * @deprecated Use {@link MotionEvent#AXIS_PRESSURE} instead. 207 */ 208 @Deprecated 209 public static final int MOTION_RANGE_PRESSURE = MotionEvent.AXIS_PRESSURE; 210 211 /** 212 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_SIZE}. 213 * 214 * @see #getMotionRange 215 * @deprecated Use {@link MotionEvent#AXIS_SIZE} instead. 216 */ 217 @Deprecated 218 public static final int MOTION_RANGE_SIZE = MotionEvent.AXIS_SIZE; 219 220 /** 221 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MAJOR}. 222 * 223 * @see #getMotionRange 224 * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MAJOR} instead. 225 */ 226 @Deprecated 227 public static final int MOTION_RANGE_TOUCH_MAJOR = MotionEvent.AXIS_TOUCH_MAJOR; 228 229 /** 230 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOUCH_MINOR}. 231 * 232 * @see #getMotionRange 233 * @deprecated Use {@link MotionEvent#AXIS_TOUCH_MINOR} instead. 234 */ 235 @Deprecated 236 public static final int MOTION_RANGE_TOUCH_MINOR = MotionEvent.AXIS_TOUCH_MINOR; 237 238 /** 239 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MAJOR}. 240 * 241 * @see #getMotionRange 242 * @deprecated Use {@link MotionEvent#AXIS_TOOL_MAJOR} instead. 243 */ 244 @Deprecated 245 public static final int MOTION_RANGE_TOOL_MAJOR = MotionEvent.AXIS_TOOL_MAJOR; 246 247 /** 248 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_TOOL_MINOR}. 249 * 250 * @see #getMotionRange 251 * @deprecated Use {@link MotionEvent#AXIS_TOOL_MINOR} instead. 252 */ 253 @Deprecated 254 public static final int MOTION_RANGE_TOOL_MINOR = MotionEvent.AXIS_TOOL_MINOR; 255 256 /** 257 * Constant for retrieving the range of values for {@link MotionEvent#AXIS_ORIENTATION}. 258 * 259 * @see #getMotionRange 260 * @deprecated Use {@link MotionEvent#AXIS_ORIENTATION} instead. 261 */ 262 @Deprecated 263 public static final int MOTION_RANGE_ORIENTATION = MotionEvent.AXIS_ORIENTATION; 264 265 /** 266 * There is no keyboard. 267 */ 268 public static final int KEYBOARD_TYPE_NONE = 0; 269 270 /** 271 * The keyboard is not fully alphabetic. It may be a numeric keypad or an assortment 272 * of buttons that are not mapped as alphabetic keys suitable for text input. 273 */ 274 public static final int KEYBOARD_TYPE_NON_ALPHABETIC = 1; 275 276 /** 277 * The keyboard supports a complement of alphabetic keys. 278 */ 279 public static final int KEYBOARD_TYPE_ALPHABETIC = 2; 280 281 // Called by native code. 282 private InputDevice() { 283 } 284 285 /** 286 * Gets information about the input device with the specified id. 287 * @param id The device id. 288 * @return The input device or null if not found. 289 */ 290 public static InputDevice getDevice(int id) { 291 IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); 292 try { 293 return wm.getInputDevice(id); 294 } catch (RemoteException ex) { 295 throw new RuntimeException( 296 "Could not get input device information from Window Manager.", ex); 297 } 298 } 299 300 /** 301 * Gets the ids of all input devices in the system. 302 * @return The input device ids. 303 */ 304 public static int[] getDeviceIds() { 305 IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window")); 306 try { 307 return wm.getInputDeviceIds(); 308 } catch (RemoteException ex) { 309 throw new RuntimeException( 310 "Could not get input device ids from Window Manager.", ex); 311 } 312 } 313 314 /** 315 * Gets the input device id. 316 * @return The input device id. 317 */ 318 public int getId() { 319 return mId; 320 } 321 322 /** 323 * Gets the name of this input device. 324 * @return The input device name. 325 */ 326 public String getName() { 327 return mName; 328 } 329 330 /** 331 * Gets the input sources supported by this input device as a combined bitfield. 332 * @return The supported input sources. 333 */ 334 public int getSources() { 335 return mSources; 336 } 337 338 /** 339 * Gets the keyboard type. 340 * @return The keyboard type. 341 */ 342 public int getKeyboardType() { 343 return mKeyboardType; 344 } 345 346 /** 347 * Gets the key character map associated with this input device. 348 * @return The key character map. 349 */ 350 public KeyCharacterMap getKeyCharacterMap() { 351 return KeyCharacterMap.load(mId); 352 } 353 354 /** 355 * Gets information about the range of values for a particular {@link MotionEvent} axis. 356 * @param axis The axis constant. 357 * @return The range of values, or null if the requested axis is not 358 * supported by the device. 359 * 360 * @see MotionEvent#AXIS_X 361 * @see MotionEvent#AXIS_Y 362 */ 363 public MotionRange getMotionRange(int axis) { 364 return mMotionRanges.get(axis); 365 } 366 367 // Called by native code. 368 private void addMotionRange(int axis, float min, float max, float flat, float fuzz) { 369 mMotionRanges.append(axis, new MotionRange(min, max, flat, fuzz)); 370 } 371 372 /** 373 * Provides information about the range of values for a particular {@link MotionEvent} axis. 374 * 375 * @see InputDevice#getMotionRange(int) 376 */ 377 public static final class MotionRange { 378 private float mMin; 379 private float mMax; 380 private float mFlat; 381 private float mFuzz; 382 383 private MotionRange(float min, float max, float flat, float fuzz) { 384 mMin = min; 385 mMax = max; 386 mFlat = flat; 387 mFuzz = fuzz; 388 } 389 390 /** 391 * Gets the minimum value for the axis. 392 * @return The (inclusive) minimum value. 393 */ 394 public float getMin() { 395 return mMin; 396 } 397 398 /** 399 * Gets the maximum value for the axis. 400 * @return The (inclusive) maximum value. 401 */ 402 public float getMax() { 403 return mMax; 404 } 405 406 /** 407 * Gets the range of the axis (difference between maximum and minimum plus one). 408 * @return The range of values. 409 */ 410 public float getRange() { 411 return mMax - mMin + 1; 412 } 413 414 /** 415 * Gets the extent of the center flat position with respect to this axis. 416 * For example, a flat value of 8 means that the center position is between -8 and +8. 417 * This value is mainly useful for calibrating self-centering devices. 418 * @return The extent of the center flat position. 419 */ 420 public float getFlat() { 421 return mFlat; 422 } 423 424 /** 425 * Gets the error tolerance for input device measurements with respect to this axis. 426 * For example, a value of 2 indicates that the measured value may be up to +/- 2 units 427 * away from the actual value due to noise and device sensitivity limitations. 428 * @return The error tolerance. 429 */ 430 public float getFuzz() { 431 return mFuzz; 432 } 433 } 434 435 public static final Parcelable.Creator<InputDevice> CREATOR 436 = new Parcelable.Creator<InputDevice>() { 437 public InputDevice createFromParcel(Parcel in) { 438 InputDevice result = new InputDevice(); 439 result.readFromParcel(in); 440 return result; 441 } 442 443 public InputDevice[] newArray(int size) { 444 return new InputDevice[size]; 445 } 446 }; 447 448 private void readFromParcel(Parcel in) { 449 mId = in.readInt(); 450 mName = in.readString(); 451 mSources = in.readInt(); 452 mKeyboardType = in.readInt(); 453 454 for (;;) { 455 int axis = in.readInt(); 456 if (axis < 0) { 457 break; 458 } 459 addMotionRange(axis, 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 final int numAxes = mMotionRanges.size(); 471 for (int i = 0; i < numAxes; i++) { 472 int axis = mMotionRanges.keyAt(i); 473 MotionRange range = mMotionRanges.valueAt(i); 474 out.writeInt(axis); 475 out.writeFloat(range.mMin); 476 out.writeFloat(range.mMax); 477 out.writeFloat(range.mFlat); 478 out.writeFloat(range.mFuzz); 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: ").append(Integer.toHexString(mSources)).append(" ("); 508 appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard"); 509 appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad"); 510 appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHSCREEN, "touchscreen"); 511 appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse"); 512 appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball"); 513 appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad"); 514 appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK, "joystick"); 515 appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad"); 516 description.append(" )\n"); 517 518 final int numAxes = mMotionRanges.size(); 519 for (int i = 0; i < numAxes; i++) { 520 int axis = mMotionRanges.keyAt(i); 521 MotionRange range = mMotionRanges.valueAt(i); 522 description.append(" ").append(MotionEvent.axisToString(axis)); 523 description.append(": min=").append(range.mMin); 524 description.append(" max=").append(range.mMax); 525 description.append(" flat=").append(range.mFlat); 526 description.append(" fuzz=").append(range.mFuzz); 527 description.append("\n"); 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