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