blob: ccbf52b8891baa88e2f45570ae589e54d1a0efa7 [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 {
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
Jeff Brownf086ddb2014-02-11 14:28:48 -0800216void PointerCoords::applyOffset(float xOffset, float yOffset) {
217 setAxisValue(AMOTION_EVENT_AXIS_X, getX() + xOffset);
218 setAxisValue(AMOTION_EVENT_AXIS_Y, getY() + yOffset);
219}
220
Jeff Brown5912f952013-07-01 19:10:31 -0700221#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
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700427static 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) {
Jeff Brown5912f952013-07-01 19:10:31 -0700441 // Construct and transform a vector oriented at the specified clockwise angle from vertical.
442 // Coordinate system: down is increasing Y, right is increasing X.
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700443 float x = sinf(angleRadians);
444 float y = -cosf(angleRadians);
445 transformPoint(matrix, x, y, &x, &y);
446 x -= originX;
447 y -= originY;
Jeff Brown5912f952013-07-01 19:10:31 -0700448
449 // Derive the transformed vector's clockwise angle from vertical.
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700450 float result = atan2f(x, -y);
Jeff Brown5912f952013-07-01 19:10:31 -0700451 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
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700459void MotionEvent::transform(const float matrix[9]) {
Jeff Brown5912f952013-07-01 19:10:31 -0700460 // 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
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700462 // 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;
Jeff Brown5912f952013-07-01 19:10:31 -0700467 float rawX = getRawX(0);
468 float rawY = getRawY(0);
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700469 transformPoint(matrix, rawX + oldXOffset, rawY + oldYOffset, &newX, &newY);
470 mXOffset = newX - rawX;
471 mYOffset = newY - rawY;
Jeff Brown5912f952013-07-01 19:10:31 -0700472
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700473 // 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);
Jeff Brown5912f952013-07-01 19:10:31 -0700477
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;
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700484 transformPoint(matrix, x, y, &x, &y);
485 c.setAxisValue(AMOTION_EVENT_AXIS_X, x - mXOffset);
486 c.setAxisValue(AMOTION_EVENT_AXIS_Y, y - mYOffset);
Jeff Brown5912f952013-07-01 19:10:31 -0700487
488 float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700489 c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
490 transformAngle(matrix, orientation, originX, originY));
Jeff Brown5912f952013-07-01 19:10:31 -0700491 }
492}
493
Jeff Brown5a2f68e2013-07-15 17:28:19 -0700494#ifdef HAVE_ANDROID_OS
Jeff Brown5912f952013-07-01 19:10:31 -0700495status_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