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