widget/gonk/libui/Input.cpp

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial