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