Input.cpp revision f086ddbb97e59bd4a0c27745f6e6cc9832a2d4f8
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#define LOG_TAG "Input" 18//#define LOG_NDEBUG 0 19 20#include <math.h> 21#include <limits.h> 22 23#include <input/Input.h> 24 25#ifdef HAVE_ANDROID_OS 26#include <binder/Parcel.h> 27#endif 28 29namespace android { 30 31// --- InputEvent --- 32 33void InputEvent::initialize(int32_t deviceId, int32_t source) { 34 mDeviceId = deviceId; 35 mSource = source; 36} 37 38void InputEvent::initialize(const InputEvent& from) { 39 mDeviceId = from.mDeviceId; 40 mSource = from.mSource; 41} 42 43// --- KeyEvent --- 44 45bool KeyEvent::hasDefaultAction(int32_t keyCode) { 46 switch (keyCode) { 47 case AKEYCODE_HOME: 48 case AKEYCODE_BACK: 49 case AKEYCODE_CALL: 50 case AKEYCODE_ENDCALL: 51 case AKEYCODE_VOLUME_UP: 52 case AKEYCODE_VOLUME_DOWN: 53 case AKEYCODE_VOLUME_MUTE: 54 case AKEYCODE_POWER: 55 case AKEYCODE_CAMERA: 56 case AKEYCODE_HEADSETHOOK: 57 case AKEYCODE_MENU: 58 case AKEYCODE_NOTIFICATION: 59 case AKEYCODE_FOCUS: 60 case AKEYCODE_SEARCH: 61 case AKEYCODE_MEDIA_PLAY: 62 case AKEYCODE_MEDIA_PAUSE: 63 case AKEYCODE_MEDIA_PLAY_PAUSE: 64 case AKEYCODE_MEDIA_STOP: 65 case AKEYCODE_MEDIA_NEXT: 66 case AKEYCODE_MEDIA_PREVIOUS: 67 case AKEYCODE_MEDIA_REWIND: 68 case AKEYCODE_MEDIA_RECORD: 69 case AKEYCODE_MEDIA_FAST_FORWARD: 70 case AKEYCODE_MUTE: 71 case AKEYCODE_BRIGHTNESS_DOWN: 72 case AKEYCODE_BRIGHTNESS_UP: 73 case AKEYCODE_MEDIA_AUDIO_TRACK: 74 return true; 75 } 76 77 return false; 78} 79 80bool KeyEvent::hasDefaultAction() const { 81 return hasDefaultAction(getKeyCode()); 82} 83 84bool KeyEvent::isSystemKey(int32_t keyCode) { 85 switch (keyCode) { 86 case AKEYCODE_MENU: 87 case AKEYCODE_SOFT_RIGHT: 88 case AKEYCODE_HOME: 89 case AKEYCODE_BACK: 90 case AKEYCODE_CALL: 91 case AKEYCODE_ENDCALL: 92 case AKEYCODE_VOLUME_UP: 93 case AKEYCODE_VOLUME_DOWN: 94 case AKEYCODE_VOLUME_MUTE: 95 case AKEYCODE_MUTE: 96 case AKEYCODE_POWER: 97 case AKEYCODE_HEADSETHOOK: 98 case AKEYCODE_MEDIA_PLAY: 99 case AKEYCODE_MEDIA_PAUSE: 100 case AKEYCODE_MEDIA_PLAY_PAUSE: 101 case AKEYCODE_MEDIA_STOP: 102 case AKEYCODE_MEDIA_NEXT: 103 case AKEYCODE_MEDIA_PREVIOUS: 104 case AKEYCODE_MEDIA_REWIND: 105 case AKEYCODE_MEDIA_RECORD: 106 case AKEYCODE_MEDIA_FAST_FORWARD: 107 case AKEYCODE_CAMERA: 108 case AKEYCODE_FOCUS: 109 case AKEYCODE_SEARCH: 110 case AKEYCODE_BRIGHTNESS_DOWN: 111 case AKEYCODE_BRIGHTNESS_UP: 112 case AKEYCODE_MEDIA_AUDIO_TRACK: 113 return true; 114 } 115 116 return false; 117} 118 119bool KeyEvent::isSystemKey() const { 120 return isSystemKey(getKeyCode()); 121} 122 123void KeyEvent::initialize( 124 int32_t deviceId, 125 int32_t source, 126 int32_t action, 127 int32_t flags, 128 int32_t keyCode, 129 int32_t scanCode, 130 int32_t metaState, 131 int32_t repeatCount, 132 nsecs_t downTime, 133 nsecs_t eventTime) { 134 InputEvent::initialize(deviceId, source); 135 mAction = action; 136 mFlags = flags; 137 mKeyCode = keyCode; 138 mScanCode = scanCode; 139 mMetaState = metaState; 140 mRepeatCount = repeatCount; 141 mDownTime = downTime; 142 mEventTime = eventTime; 143} 144 145void KeyEvent::initialize(const KeyEvent& from) { 146 InputEvent::initialize(from); 147 mAction = from.mAction; 148 mFlags = from.mFlags; 149 mKeyCode = from.mKeyCode; 150 mScanCode = from.mScanCode; 151 mMetaState = from.mMetaState; 152 mRepeatCount = from.mRepeatCount; 153 mDownTime = from.mDownTime; 154 mEventTime = from.mEventTime; 155} 156 157 158// --- PointerCoords --- 159 160float PointerCoords::getAxisValue(int32_t axis) const { 161 if (axis < 0 || axis > 63) { 162 return 0; 163 } 164 165 uint64_t axisBit = 1LL << axis; 166 if (!(bits & axisBit)) { 167 return 0; 168 } 169 uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); 170 return values[index]; 171} 172 173status_t PointerCoords::setAxisValue(int32_t axis, float value) { 174 if (axis < 0 || axis > 63) { 175 return NAME_NOT_FOUND; 176 } 177 178 uint64_t axisBit = 1LL << axis; 179 uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); 180 if (!(bits & axisBit)) { 181 if (value == 0) { 182 return OK; // axes with value 0 do not need to be stored 183 } 184 uint32_t count = __builtin_popcountll(bits); 185 if (count >= MAX_AXES) { 186 tooManyAxes(axis); 187 return NO_MEMORY; 188 } 189 bits |= axisBit; 190 for (uint32_t i = count; i > index; i--) { 191 values[i] = values[i - 1]; 192 } 193 } 194 values[index] = value; 195 return OK; 196} 197 198static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) { 199 float value = c.getAxisValue(axis); 200 if (value != 0) { 201 c.setAxisValue(axis, value * scaleFactor); 202 } 203} 204 205void PointerCoords::scale(float scaleFactor) { 206 // No need to scale pressure or size since they are normalized. 207 // No need to scale orientation since it is meaningless to do so. 208 scaleAxisValue(*this, AMOTION_EVENT_AXIS_X, scaleFactor); 209 scaleAxisValue(*this, AMOTION_EVENT_AXIS_Y, scaleFactor); 210 scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MAJOR, scaleFactor); 211 scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MINOR, scaleFactor); 212 scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MAJOR, scaleFactor); 213 scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor); 214} 215 216void PointerCoords::applyOffset(float xOffset, float yOffset) { 217 setAxisValue(AMOTION_EVENT_AXIS_X, getX() + xOffset); 218 setAxisValue(AMOTION_EVENT_AXIS_Y, getY() + yOffset); 219} 220 221#ifdef HAVE_ANDROID_OS 222status_t PointerCoords::readFromParcel(Parcel* parcel) { 223 bits = parcel->readInt64(); 224 225 uint32_t count = __builtin_popcountll(bits); 226 if (count > MAX_AXES) { 227 return BAD_VALUE; 228 } 229 230 for (uint32_t i = 0; i < count; i++) { 231 values[i] = parcel->readFloat(); 232 } 233 return OK; 234} 235 236status_t PointerCoords::writeToParcel(Parcel* parcel) const { 237 parcel->writeInt64(bits); 238 239 uint32_t count = __builtin_popcountll(bits); 240 for (uint32_t i = 0; i < count; i++) { 241 parcel->writeFloat(values[i]); 242 } 243 return OK; 244} 245#endif 246 247void PointerCoords::tooManyAxes(int axis) { 248 ALOGW("Could not set value for axis %d because the PointerCoords structure is full and " 249 "cannot contain more than %d axis values.", axis, int(MAX_AXES)); 250} 251 252bool PointerCoords::operator==(const PointerCoords& other) const { 253 if (bits != other.bits) { 254 return false; 255 } 256 uint32_t count = __builtin_popcountll(bits); 257 for (uint32_t i = 0; i < count; i++) { 258 if (values[i] != other.values[i]) { 259 return false; 260 } 261 } 262 return true; 263} 264 265void PointerCoords::copyFrom(const PointerCoords& other) { 266 bits = other.bits; 267 uint32_t count = __builtin_popcountll(bits); 268 for (uint32_t i = 0; i < count; i++) { 269 values[i] = other.values[i]; 270 } 271} 272 273 274// --- PointerProperties --- 275 276bool PointerProperties::operator==(const PointerProperties& other) const { 277 return id == other.id 278 && toolType == other.toolType; 279} 280 281void PointerProperties::copyFrom(const PointerProperties& other) { 282 id = other.id; 283 toolType = other.toolType; 284} 285 286 287// --- MotionEvent --- 288 289void MotionEvent::initialize( 290 int32_t deviceId, 291 int32_t source, 292 int32_t action, 293 int32_t flags, 294 int32_t edgeFlags, 295 int32_t metaState, 296 int32_t buttonState, 297 float xOffset, 298 float yOffset, 299 float xPrecision, 300 float yPrecision, 301 nsecs_t downTime, 302 nsecs_t eventTime, 303 size_t pointerCount, 304 const PointerProperties* pointerProperties, 305 const PointerCoords* pointerCoords) { 306 InputEvent::initialize(deviceId, source); 307 mAction = action; 308 mFlags = flags; 309 mEdgeFlags = edgeFlags; 310 mMetaState = metaState; 311 mButtonState = buttonState; 312 mXOffset = xOffset; 313 mYOffset = yOffset; 314 mXPrecision = xPrecision; 315 mYPrecision = yPrecision; 316 mDownTime = downTime; 317 mPointerProperties.clear(); 318 mPointerProperties.appendArray(pointerProperties, pointerCount); 319 mSampleEventTimes.clear(); 320 mSamplePointerCoords.clear(); 321 addSample(eventTime, pointerCoords); 322} 323 324void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) { 325 InputEvent::initialize(other->mDeviceId, other->mSource); 326 mAction = other->mAction; 327 mFlags = other->mFlags; 328 mEdgeFlags = other->mEdgeFlags; 329 mMetaState = other->mMetaState; 330 mButtonState = other->mButtonState; 331 mXOffset = other->mXOffset; 332 mYOffset = other->mYOffset; 333 mXPrecision = other->mXPrecision; 334 mYPrecision = other->mYPrecision; 335 mDownTime = other->mDownTime; 336 mPointerProperties = other->mPointerProperties; 337 338 if (keepHistory) { 339 mSampleEventTimes = other->mSampleEventTimes; 340 mSamplePointerCoords = other->mSamplePointerCoords; 341 } else { 342 mSampleEventTimes.clear(); 343 mSampleEventTimes.push(other->getEventTime()); 344 mSamplePointerCoords.clear(); 345 size_t pointerCount = other->getPointerCount(); 346 size_t historySize = other->getHistorySize(); 347 mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array() 348 + (historySize * pointerCount), pointerCount); 349 } 350} 351 352void MotionEvent::addSample( 353 int64_t eventTime, 354 const PointerCoords* pointerCoords) { 355 mSampleEventTimes.push(eventTime); 356 mSamplePointerCoords.appendArray(pointerCoords, getPointerCount()); 357} 358 359const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const { 360 return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex]; 361} 362 363float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const { 364 return getRawPointerCoords(pointerIndex)->getAxisValue(axis); 365} 366 367float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const { 368 float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis); 369 switch (axis) { 370 case AMOTION_EVENT_AXIS_X: 371 return value + mXOffset; 372 case AMOTION_EVENT_AXIS_Y: 373 return value + mYOffset; 374 } 375 return value; 376} 377 378const PointerCoords* MotionEvent::getHistoricalRawPointerCoords( 379 size_t pointerIndex, size_t historicalIndex) const { 380 return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex]; 381} 382 383float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, 384 size_t historicalIndex) const { 385 return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis); 386} 387 388float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex, 389 size_t historicalIndex) const { 390 float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis); 391 switch (axis) { 392 case AMOTION_EVENT_AXIS_X: 393 return value + mXOffset; 394 case AMOTION_EVENT_AXIS_Y: 395 return value + mYOffset; 396 } 397 return value; 398} 399 400ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const { 401 size_t pointerCount = mPointerProperties.size(); 402 for (size_t i = 0; i < pointerCount; i++) { 403 if (mPointerProperties.itemAt(i).id == pointerId) { 404 return i; 405 } 406 } 407 return -1; 408} 409 410void MotionEvent::offsetLocation(float xOffset, float yOffset) { 411 mXOffset += xOffset; 412 mYOffset += yOffset; 413} 414 415void MotionEvent::scale(float scaleFactor) { 416 mXOffset *= scaleFactor; 417 mYOffset *= scaleFactor; 418 mXPrecision *= scaleFactor; 419 mYPrecision *= scaleFactor; 420 421 size_t numSamples = mSamplePointerCoords.size(); 422 for (size_t i = 0; i < numSamples; i++) { 423 mSamplePointerCoords.editItemAt(i).scale(scaleFactor); 424 } 425} 426 427static void transformPoint(const float matrix[9], float x, float y, float *outX, float *outY) { 428 // Apply perspective transform like Skia. 429 float newX = matrix[0] * x + matrix[1] * y + matrix[2]; 430 float newY = matrix[3] * x + matrix[4] * y + matrix[5]; 431 float newZ = matrix[6] * x + matrix[7] * y + matrix[8]; 432 if (newZ) { 433 newZ = 1.0f / newZ; 434 } 435 *outX = newX * newZ; 436 *outY = newY * newZ; 437} 438 439static float transformAngle(const float matrix[9], float angleRadians, 440 float originX, float originY) { 441 // Construct and transform a vector oriented at the specified clockwise angle from vertical. 442 // Coordinate system: down is increasing Y, right is increasing X. 443 float x = sinf(angleRadians); 444 float y = -cosf(angleRadians); 445 transformPoint(matrix, x, y, &x, &y); 446 x -= originX; 447 y -= originY; 448 449 // Derive the transformed vector's clockwise angle from vertical. 450 float result = atan2f(x, -y); 451 if (result < - M_PI_2) { 452 result += M_PI; 453 } else if (result > M_PI_2) { 454 result -= M_PI; 455 } 456 return result; 457} 458 459void MotionEvent::transform(const float matrix[9]) { 460 // The tricky part of this implementation is to preserve the value of 461 // rawX and rawY. So we apply the transformation to the first point 462 // then derive an appropriate new X/Y offset that will preserve rawX 463 // and rawY for that point. 464 float oldXOffset = mXOffset; 465 float oldYOffset = mYOffset; 466 float newX, newY; 467 float rawX = getRawX(0); 468 float rawY = getRawY(0); 469 transformPoint(matrix, rawX + oldXOffset, rawY + oldYOffset, &newX, &newY); 470 mXOffset = newX - rawX; 471 mYOffset = newY - rawY; 472 473 // Determine how the origin is transformed by the matrix so that we 474 // can transform orientation vectors. 475 float originX, originY; 476 transformPoint(matrix, 0, 0, &originX, &originY); 477 478 // Apply the transformation to all samples. 479 size_t numSamples = mSamplePointerCoords.size(); 480 for (size_t i = 0; i < numSamples; i++) { 481 PointerCoords& c = mSamplePointerCoords.editItemAt(i); 482 float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset; 483 float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset; 484 transformPoint(matrix, x, y, &x, &y); 485 c.setAxisValue(AMOTION_EVENT_AXIS_X, x - mXOffset); 486 c.setAxisValue(AMOTION_EVENT_AXIS_Y, y - mYOffset); 487 488 float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION); 489 c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 490 transformAngle(matrix, orientation, originX, originY)); 491 } 492} 493 494#ifdef HAVE_ANDROID_OS 495status_t MotionEvent::readFromParcel(Parcel* parcel) { 496 size_t pointerCount = parcel->readInt32(); 497 size_t sampleCount = parcel->readInt32(); 498 if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) { 499 return BAD_VALUE; 500 } 501 502 mDeviceId = parcel->readInt32(); 503 mSource = parcel->readInt32(); 504 mAction = parcel->readInt32(); 505 mFlags = parcel->readInt32(); 506 mEdgeFlags = parcel->readInt32(); 507 mMetaState = parcel->readInt32(); 508 mButtonState = parcel->readInt32(); 509 mXOffset = parcel->readFloat(); 510 mYOffset = parcel->readFloat(); 511 mXPrecision = parcel->readFloat(); 512 mYPrecision = parcel->readFloat(); 513 mDownTime = parcel->readInt64(); 514 515 mPointerProperties.clear(); 516 mPointerProperties.setCapacity(pointerCount); 517 mSampleEventTimes.clear(); 518 mSampleEventTimes.setCapacity(sampleCount); 519 mSamplePointerCoords.clear(); 520 mSamplePointerCoords.setCapacity(sampleCount * pointerCount); 521 522 for (size_t i = 0; i < pointerCount; i++) { 523 mPointerProperties.push(); 524 PointerProperties& properties = mPointerProperties.editTop(); 525 properties.id = parcel->readInt32(); 526 properties.toolType = parcel->readInt32(); 527 } 528 529 while (sampleCount-- > 0) { 530 mSampleEventTimes.push(parcel->readInt64()); 531 for (size_t i = 0; i < pointerCount; i++) { 532 mSamplePointerCoords.push(); 533 status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel); 534 if (status) { 535 return status; 536 } 537 } 538 } 539 return OK; 540} 541 542status_t MotionEvent::writeToParcel(Parcel* parcel) const { 543 size_t pointerCount = mPointerProperties.size(); 544 size_t sampleCount = mSampleEventTimes.size(); 545 546 parcel->writeInt32(pointerCount); 547 parcel->writeInt32(sampleCount); 548 549 parcel->writeInt32(mDeviceId); 550 parcel->writeInt32(mSource); 551 parcel->writeInt32(mAction); 552 parcel->writeInt32(mFlags); 553 parcel->writeInt32(mEdgeFlags); 554 parcel->writeInt32(mMetaState); 555 parcel->writeInt32(mButtonState); 556 parcel->writeFloat(mXOffset); 557 parcel->writeFloat(mYOffset); 558 parcel->writeFloat(mXPrecision); 559 parcel->writeFloat(mYPrecision); 560 parcel->writeInt64(mDownTime); 561 562 for (size_t i = 0; i < pointerCount; i++) { 563 const PointerProperties& properties = mPointerProperties.itemAt(i); 564 parcel->writeInt32(properties.id); 565 parcel->writeInt32(properties.toolType); 566 } 567 568 const PointerCoords* pc = mSamplePointerCoords.array(); 569 for (size_t h = 0; h < sampleCount; h++) { 570 parcel->writeInt64(mSampleEventTimes.itemAt(h)); 571 for (size_t i = 0; i < pointerCount; i++) { 572 status_t status = (pc++)->writeToParcel(parcel); 573 if (status) { 574 return status; 575 } 576 } 577 } 578 return OK; 579} 580#endif 581 582bool MotionEvent::isTouchEvent(int32_t source, int32_t action) { 583 if (source & AINPUT_SOURCE_CLASS_POINTER) { 584 // Specifically excludes HOVER_MOVE and SCROLL. 585 switch (action & AMOTION_EVENT_ACTION_MASK) { 586 case AMOTION_EVENT_ACTION_DOWN: 587 case AMOTION_EVENT_ACTION_MOVE: 588 case AMOTION_EVENT_ACTION_UP: 589 case AMOTION_EVENT_ACTION_POINTER_DOWN: 590 case AMOTION_EVENT_ACTION_POINTER_UP: 591 case AMOTION_EVENT_ACTION_CANCEL: 592 case AMOTION_EVENT_ACTION_OUTSIDE: 593 return true; 594 } 595 } 596 return false; 597} 598 599 600// --- PooledInputEventFactory --- 601 602PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) : 603 mMaxPoolSize(maxPoolSize) { 604} 605 606PooledInputEventFactory::~PooledInputEventFactory() { 607 for (size_t i = 0; i < mKeyEventPool.size(); i++) { 608 delete mKeyEventPool.itemAt(i); 609 } 610 for (size_t i = 0; i < mMotionEventPool.size(); i++) { 611 delete mMotionEventPool.itemAt(i); 612 } 613} 614 615KeyEvent* PooledInputEventFactory::createKeyEvent() { 616 if (!mKeyEventPool.isEmpty()) { 617 KeyEvent* event = mKeyEventPool.top(); 618 mKeyEventPool.pop(); 619 return event; 620 } 621 return new KeyEvent(); 622} 623 624MotionEvent* PooledInputEventFactory::createMotionEvent() { 625 if (!mMotionEventPool.isEmpty()) { 626 MotionEvent* event = mMotionEventPool.top(); 627 mMotionEventPool.pop(); 628 return event; 629 } 630 return new MotionEvent(); 631} 632 633void PooledInputEventFactory::recycle(InputEvent* event) { 634 switch (event->getType()) { 635 case AINPUT_EVENT_TYPE_KEY: 636 if (mKeyEventPool.size() < mMaxPoolSize) { 637 mKeyEventPool.push(static_cast<KeyEvent*>(event)); 638 return; 639 } 640 break; 641 case AINPUT_EVENT_TYPE_MOTION: 642 if (mMotionEventPool.size() < mMaxPoolSize) { 643 mMotionEventPool.push(static_cast<MotionEvent*>(event)); 644 return; 645 } 646 break; 647 } 648 delete event; 649} 650 651} // namespace android 652