blob: d9f22e9d5e7d8fd8b719093e5a0ffb1a656f00e5 [file] [log] [blame]
Jeff Brown5912f952013-07-01 19:10:31 -07001/*
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>
Jeff Brown5912f952013-07-01 19:10:31 -070027#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:
Jaekyun Seok8d06dcf2013-07-08 13:56:02 +090073 case AKEYCODE_MEDIA_AUDIO_TRACK:
Jeff Brown5912f952013-07-01 19:10:31 -070074 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:
Jaekyun Seok8d06dcf2013-07-08 13:56:02 +0900112 case AKEYCODE_MEDIA_AUDIO_TRACK:
Jeff Brown5912f952013-07-01 19:10:31 -0700113 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 {
Michael Wright38dcdff2014-03-19 12:06:10 -0700161 if (axis < 0 || axis > 63 || !BitSet64::hasBit(bits, axis)){
Jeff Brown5912f952013-07-01 19:10:31 -0700162 return 0;
163 }
Michael Wright38dcdff2014-03-19 12:06:10 -0700164 return values[BitSet64::getIndexOfBit(bits, axis)];
Jeff Brown5912f952013-07-01 19:10:31 -0700165}
166
167status_t PointerCoords::setAxisValue(int32_t axis, float value) {
168 if (axis < 0 || axis > 63) {
169 return NAME_NOT_FOUND;
170 }
171
Michael Wright38dcdff2014-03-19 12:06:10 -0700172 uint32_t index = BitSet64::getIndexOfBit(bits, axis);
173 if (!BitSet64::hasBit(bits, axis)) {
Jeff Brown5912f952013-07-01 19:10:31 -0700174 if (value == 0) {
175 return OK; // axes with value 0 do not need to be stored
176 }
Michael Wright38dcdff2014-03-19 12:06:10 -0700177
178 uint32_t count = BitSet64::count(bits);
Jeff Brown5912f952013-07-01 19:10:31 -0700179 if (count >= MAX_AXES) {
180 tooManyAxes(axis);
181 return NO_MEMORY;
182 }
Michael Wright38dcdff2014-03-19 12:06:10 -0700183 BitSet64::markBit(bits, axis);
Jeff Brown5912f952013-07-01 19:10:31 -0700184 for (uint32_t i = count; i > index; i--) {
185 values[i] = values[i - 1];
186 }
187 }
Michael Wright38dcdff2014-03-19 12:06:10 -0700188
Jeff Brown5912f952013-07-01 19:10:31 -0700189 values[index] = value;
190 return OK;
191}
192
193static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) {
194 float value = c.getAxisValue(axis);
195 if (value != 0) {
196 c.setAxisValue(axis, value * scaleFactor);
197 }
198}
199
200void PointerCoords::scale(float scaleFactor) {
201 // No need to scale pressure or size since they are normalized.
202 // No need to scale orientation since it is meaningless to do so.
203 scaleAxisValue(*this, AMOTION_EVENT_AXIS_X, scaleFactor);
204 scaleAxisValue(*this, AMOTION_EVENT_AXIS_Y, scaleFactor);
205 scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MAJOR, scaleFactor);
206 scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MINOR, scaleFactor);
207 scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MAJOR, scaleFactor);
208 scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor);
209}
210
Jeff Brownf086ddb2014-02-11 14:28:48 -0800211void PointerCoords::applyOffset(float xOffset, float yOffset) {
212 setAxisValue(AMOTION_EVENT_AXIS_X, getX() + xOffset);
213 setAxisValue(AMOTION_EVENT_AXIS_Y, getY() + yOffset);
214}
215
Jeff Brown5912f952013-07-01 19:10:31 -0700216#ifdef HAVE_ANDROID_OS
217status_t PointerCoords::readFromParcel(Parcel* parcel) {
218 bits = parcel->readInt64();
219
Michael Wright38dcdff2014-03-19 12:06:10 -0700220 uint32_t count = BitSet64::count(bits);
Jeff Brown5912f952013-07-01 19:10:31 -0700221 if (count > MAX_AXES) {
222 return BAD_VALUE;
223 }
224
225 for (uint32_t i = 0; i < count; i++) {
226 values[i] = parcel->readFloat();
227 }
228 return OK;
229}
230
231status_t PointerCoords::writeToParcel(Parcel* parcel) const {
232 parcel->writeInt64(bits);
233
Michael Wright38dcdff2014-03-19 12:06:10 -0700234 uint32_t count = BitSet64::count(bits);
Jeff Brown5912f952013-07-01 19:10:31 -0700235 for (uint32_t i = 0; i < count; i++) {
236 parcel->writeFloat(values[i]);
237 }
238 return OK;
239}
240#endif
241
242void PointerCoords::tooManyAxes(int axis) {
243 ALOGW("Could not set value for axis %d because the PointerCoords structure is full and "
244 "cannot contain more than %d axis values.", axis, int(MAX_AXES));
245}
246
247bool PointerCoords::operator==(const PointerCoords& other) const {
248 if (bits != other.bits) {
249 return false;
250 }
Michael Wright38dcdff2014-03-19 12:06:10 -0700251 uint32_t count = BitSet64::count(bits);
Jeff Brown5912f952013-07-01 19:10:31 -0700252 for (uint32_t i = 0; i < count; i++) {
253 if (values[i] != other.values[i]) {
254 return false;
255 }
256 }
257 return true;
258}
259
260void PointerCoords::copyFrom(const PointerCoords& other) {
261 bits = other.bits;
Michael Wright38dcdff2014-03-19 12:06:10 -0700262 uint32_t count = BitSet64::count(bits);
Jeff Brown5912f952013-07-01 19:10:31 -0700263 for (uint32_t i = 0; i < count; i++) {
264 values[i] = other.values[i];
265 }
266}
267
268
269// --- PointerProperties ---
270
271bool PointerProperties::operator==(const PointerProperties& other) const {
272 return id == other.id
273 && toolType == other.toolType;
274}
275
276void PointerProperties::copyFrom(const PointerProperties& other) {
277 id = other.id;
278 toolType = other.toolType;
279}
280
281
282// --- MotionEvent ---
283
284void MotionEvent::initialize(
285 int32_t deviceId,
286 int32_t source,
287 int32_t action,
288 int32_t flags,
289 int32_t edgeFlags,
290 int32_t metaState,
291 int32_t buttonState,
292 float xOffset,
293 float yOffset,
294 float xPrecision,
295 float yPrecision,
296 nsecs_t downTime,
297 nsecs_t eventTime,
298 size_t pointerCount,
299 const PointerProperties* pointerProperties,
300 const PointerCoords* pointerCoords) {
301 InputEvent::initialize(deviceId, source);
302 mAction = action;
303 mFlags = flags;
304 mEdgeFlags = edgeFlags;
305 mMetaState = metaState;
306 mButtonState = buttonState;
307 mXOffset = xOffset;
308 mYOffset = yOffset;
309 mXPrecision = xPrecision;
310 mYPrecision = yPrecision;
311 mDownTime = downTime;
312 mPointerProperties.clear();
313 mPointerProperties.appendArray(pointerProperties, pointerCount);
314 mSampleEventTimes.clear();
315 mSamplePointerCoords.clear();
316 addSample(eventTime, pointerCoords);
317}
318
319void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
320 InputEvent::initialize(other->mDeviceId, other->mSource);
321 mAction = other->mAction;
322 mFlags = other->mFlags;
323 mEdgeFlags = other->mEdgeFlags;
324 mMetaState = other->mMetaState;
325 mButtonState = other->mButtonState;
326 mXOffset = other->mXOffset;
327 mYOffset = other->mYOffset;
328 mXPrecision = other->mXPrecision;
329 mYPrecision = other->mYPrecision;
330 mDownTime = other->mDownTime;
331 mPointerProperties = other->mPointerProperties;
332
333 if (keepHistory) {
334 mSampleEventTimes = other->mSampleEventTimes;
335 mSamplePointerCoords = other->mSamplePointerCoords;
336 } else {
337 mSampleEventTimes.clear();
338 mSampleEventTimes.push(other->getEventTime());
339 mSamplePointerCoords.clear();
340 size_t pointerCount = other->getPointerCount();
341 size_t historySize = other->getHistorySize();
342 mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array()
343 + (historySize * pointerCount), pointerCount);
344 }
345}
346
347void MotionEvent::addSample(
348 int64_t eventTime,
349 const PointerCoords* pointerCoords) {
350 mSampleEventTimes.push(eventTime);
351 mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
352}
353
354const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
355 return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
356}
357
358float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
359 return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
360}
361
362float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const {
363 float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis);
364 switch (axis) {
365 case AMOTION_EVENT_AXIS_X:
366 return value + mXOffset;
367 case AMOTION_EVENT_AXIS_Y:
368 return value + mYOffset;
369 }
370 return value;
371}
372
373const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
374 size_t pointerIndex, size_t historicalIndex) const {
375 return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
376}
377
378float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
379 size_t historicalIndex) const {
380 return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
381}
382
383float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
384 size_t historicalIndex) const {
385 float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
386 switch (axis) {
387 case AMOTION_EVENT_AXIS_X:
388 return value + mXOffset;
389 case AMOTION_EVENT_AXIS_Y:
390 return value + mYOffset;
391 }
392 return value;
393}
394
395ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
396 size_t pointerCount = mPointerProperties.size();
397 for (size_t i = 0; i < pointerCount; i++) {
398 if (mPointerProperties.itemAt(i).id == pointerId) {
399 return i;
400 }
401 }
402 return -1;
403}
404
405void MotionEvent::offsetLocation(float xOffset, float yOffset) {
406 mXOffset += xOffset;
407 mYOffset += yOffset;
408}
409
410void MotionEvent::scale(float scaleFactor) {
411 mXOffset *= scaleFactor;
412 mYOffset *= scaleFactor;
413 mXPrecision *= scaleFactor;
414 mYPrecision *= scaleFactor;
415
416 size_t numSamples = mSamplePointerCoords.size();
417 for (size_t i = 0; i < numSamples; i++) {
418 mSamplePointerCoords.editItemAt(i).scale(scaleFactor);
419 }
420}
421
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700422static void transformPoint(const float matrix[9], float x, float y, float *outX, float *outY) {
423 // Apply perspective transform like Skia.
424 float newX = matrix[0] * x + matrix[1] * y + matrix[2];
425 float newY = matrix[3] * x + matrix[4] * y + matrix[5];
426 float newZ = matrix[6] * x + matrix[7] * y + matrix[8];
427 if (newZ) {
428 newZ = 1.0f / newZ;
429 }
430 *outX = newX * newZ;
431 *outY = newY * newZ;
432}
433
434static float transformAngle(const float matrix[9], float angleRadians,
435 float originX, float originY) {
Jeff Brown5912f952013-07-01 19:10:31 -0700436 // Construct and transform a vector oriented at the specified clockwise angle from vertical.
437 // Coordinate system: down is increasing Y, right is increasing X.
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700438 float x = sinf(angleRadians);
439 float y = -cosf(angleRadians);
440 transformPoint(matrix, x, y, &x, &y);
441 x -= originX;
442 y -= originY;
Jeff Brown5912f952013-07-01 19:10:31 -0700443
444 // Derive the transformed vector's clockwise angle from vertical.
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700445 float result = atan2f(x, -y);
Jeff Brown5912f952013-07-01 19:10:31 -0700446 if (result < - M_PI_2) {
447 result += M_PI;
448 } else if (result > M_PI_2) {
449 result -= M_PI;
450 }
451 return result;
452}
453
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700454void MotionEvent::transform(const float matrix[9]) {
Jeff Brown5912f952013-07-01 19:10:31 -0700455 // The tricky part of this implementation is to preserve the value of
456 // rawX and rawY. So we apply the transformation to the first point
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700457 // then derive an appropriate new X/Y offset that will preserve rawX
458 // and rawY for that point.
459 float oldXOffset = mXOffset;
460 float oldYOffset = mYOffset;
461 float newX, newY;
Jeff Brown5912f952013-07-01 19:10:31 -0700462 float rawX = getRawX(0);
463 float rawY = getRawY(0);
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700464 transformPoint(matrix, rawX + oldXOffset, rawY + oldYOffset, &newX, &newY);
465 mXOffset = newX - rawX;
466 mYOffset = newY - rawY;
Jeff Brown5912f952013-07-01 19:10:31 -0700467
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700468 // Determine how the origin is transformed by the matrix so that we
469 // can transform orientation vectors.
470 float originX, originY;
471 transformPoint(matrix, 0, 0, &originX, &originY);
Jeff Brown5912f952013-07-01 19:10:31 -0700472
473 // Apply the transformation to all samples.
474 size_t numSamples = mSamplePointerCoords.size();
475 for (size_t i = 0; i < numSamples; i++) {
476 PointerCoords& c = mSamplePointerCoords.editItemAt(i);
477 float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset;
478 float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset;
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700479 transformPoint(matrix, x, y, &x, &y);
480 c.setAxisValue(AMOTION_EVENT_AXIS_X, x - mXOffset);
481 c.setAxisValue(AMOTION_EVENT_AXIS_Y, y - mYOffset);
Jeff Brown5912f952013-07-01 19:10:31 -0700482
483 float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700484 c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
485 transformAngle(matrix, orientation, originX, originY));
Jeff Brown5912f952013-07-01 19:10:31 -0700486 }
487}
488
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700489#ifdef HAVE_ANDROID_OS
Jeff Brown5912f952013-07-01 19:10:31 -0700490status_t MotionEvent::readFromParcel(Parcel* parcel) {
491 size_t pointerCount = parcel->readInt32();
492 size_t sampleCount = parcel->readInt32();
493 if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) {
494 return BAD_VALUE;
495 }
496
497 mDeviceId = parcel->readInt32();
498 mSource = parcel->readInt32();
499 mAction = parcel->readInt32();
500 mFlags = parcel->readInt32();
501 mEdgeFlags = parcel->readInt32();
502 mMetaState = parcel->readInt32();
503 mButtonState = parcel->readInt32();
504 mXOffset = parcel->readFloat();
505 mYOffset = parcel->readFloat();
506 mXPrecision = parcel->readFloat();
507 mYPrecision = parcel->readFloat();
508 mDownTime = parcel->readInt64();
509
510 mPointerProperties.clear();
511 mPointerProperties.setCapacity(pointerCount);
512 mSampleEventTimes.clear();
513 mSampleEventTimes.setCapacity(sampleCount);
514 mSamplePointerCoords.clear();
515 mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
516
517 for (size_t i = 0; i < pointerCount; i++) {
518 mPointerProperties.push();
519 PointerProperties& properties = mPointerProperties.editTop();
520 properties.id = parcel->readInt32();
521 properties.toolType = parcel->readInt32();
522 }
523
524 while (sampleCount-- > 0) {
525 mSampleEventTimes.push(parcel->readInt64());
526 for (size_t i = 0; i < pointerCount; i++) {
527 mSamplePointerCoords.push();
528 status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel);
529 if (status) {
530 return status;
531 }
532 }
533 }
534 return OK;
535}
536
537status_t MotionEvent::writeToParcel(Parcel* parcel) const {
538 size_t pointerCount = mPointerProperties.size();
539 size_t sampleCount = mSampleEventTimes.size();
540
541 parcel->writeInt32(pointerCount);
542 parcel->writeInt32(sampleCount);
543
544 parcel->writeInt32(mDeviceId);
545 parcel->writeInt32(mSource);
546 parcel->writeInt32(mAction);
547 parcel->writeInt32(mFlags);
548 parcel->writeInt32(mEdgeFlags);
549 parcel->writeInt32(mMetaState);
550 parcel->writeInt32(mButtonState);
551 parcel->writeFloat(mXOffset);
552 parcel->writeFloat(mYOffset);
553 parcel->writeFloat(mXPrecision);
554 parcel->writeFloat(mYPrecision);
555 parcel->writeInt64(mDownTime);
556
557 for (size_t i = 0; i < pointerCount; i++) {
558 const PointerProperties& properties = mPointerProperties.itemAt(i);
559 parcel->writeInt32(properties.id);
560 parcel->writeInt32(properties.toolType);
561 }
562
563 const PointerCoords* pc = mSamplePointerCoords.array();
564 for (size_t h = 0; h < sampleCount; h++) {
565 parcel->writeInt64(mSampleEventTimes.itemAt(h));
566 for (size_t i = 0; i < pointerCount; i++) {
567 status_t status = (pc++)->writeToParcel(parcel);
568 if (status) {
569 return status;
570 }
571 }
572 }
573 return OK;
574}
575#endif
576
577bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
578 if (source & AINPUT_SOURCE_CLASS_POINTER) {
579 // Specifically excludes HOVER_MOVE and SCROLL.
580 switch (action & AMOTION_EVENT_ACTION_MASK) {
581 case AMOTION_EVENT_ACTION_DOWN:
582 case AMOTION_EVENT_ACTION_MOVE:
583 case AMOTION_EVENT_ACTION_UP:
584 case AMOTION_EVENT_ACTION_POINTER_DOWN:
585 case AMOTION_EVENT_ACTION_POINTER_UP:
586 case AMOTION_EVENT_ACTION_CANCEL:
587 case AMOTION_EVENT_ACTION_OUTSIDE:
588 return true;
589 }
590 }
591 return false;
592}
593
594
595// --- PooledInputEventFactory ---
596
597PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) :
598 mMaxPoolSize(maxPoolSize) {
599}
600
601PooledInputEventFactory::~PooledInputEventFactory() {
602 for (size_t i = 0; i < mKeyEventPool.size(); i++) {
603 delete mKeyEventPool.itemAt(i);
604 }
605 for (size_t i = 0; i < mMotionEventPool.size(); i++) {
606 delete mMotionEventPool.itemAt(i);
607 }
608}
609
610KeyEvent* PooledInputEventFactory::createKeyEvent() {
611 if (!mKeyEventPool.isEmpty()) {
612 KeyEvent* event = mKeyEventPool.top();
613 mKeyEventPool.pop();
614 return event;
615 }
616 return new KeyEvent();
617}
618
619MotionEvent* PooledInputEventFactory::createMotionEvent() {
620 if (!mMotionEventPool.isEmpty()) {
621 MotionEvent* event = mMotionEventPool.top();
622 mMotionEventPool.pop();
623 return event;
624 }
625 return new MotionEvent();
626}
627
628void PooledInputEventFactory::recycle(InputEvent* event) {
629 switch (event->getType()) {
630 case AINPUT_EVENT_TYPE_KEY:
631 if (mKeyEventPool.size() < mMaxPoolSize) {
632 mKeyEventPool.push(static_cast<KeyEvent*>(event));
633 return;
634 }
635 break;
636 case AINPUT_EVENT_TYPE_MOTION:
637 if (mMotionEventPool.size() < mMaxPoolSize) {
638 mMotionEventPool.push(static_cast<MotionEvent*>(event));
639 return;
640 }
641 break;
642 }
643 delete event;
644}
645
646} // namespace android