• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <androidfw/Input.h>
24 
25 #ifdef HAVE_ANDROID_OS
26 #include <binder/Parcel.h>
27 
28 #include "SkPoint.h"
29 #include "SkMatrix.h"
30 #include "SkScalar.h"
31 #endif
32 
33 namespace android {
34 
35 // --- InputEvent ---
36 
initialize(int32_t deviceId,int32_t source)37 void InputEvent::initialize(int32_t deviceId, int32_t source) {
38     mDeviceId = deviceId;
39     mSource = source;
40 }
41 
initialize(const InputEvent & from)42 void InputEvent::initialize(const InputEvent& from) {
43     mDeviceId = from.mDeviceId;
44     mSource = from.mSource;
45 }
46 
47 // --- KeyEvent ---
48 
hasDefaultAction(int32_t keyCode)49 bool KeyEvent::hasDefaultAction(int32_t keyCode) {
50     switch (keyCode) {
51         case AKEYCODE_HOME:
52         case AKEYCODE_BACK:
53         case AKEYCODE_CALL:
54         case AKEYCODE_ENDCALL:
55         case AKEYCODE_VOLUME_UP:
56         case AKEYCODE_VOLUME_DOWN:
57         case AKEYCODE_VOLUME_MUTE:
58         case AKEYCODE_POWER:
59         case AKEYCODE_CAMERA:
60         case AKEYCODE_HEADSETHOOK:
61         case AKEYCODE_MENU:
62         case AKEYCODE_NOTIFICATION:
63         case AKEYCODE_FOCUS:
64         case AKEYCODE_SEARCH:
65         case AKEYCODE_MEDIA_PLAY:
66         case AKEYCODE_MEDIA_PAUSE:
67         case AKEYCODE_MEDIA_PLAY_PAUSE:
68         case AKEYCODE_MEDIA_STOP:
69         case AKEYCODE_MEDIA_NEXT:
70         case AKEYCODE_MEDIA_PREVIOUS:
71         case AKEYCODE_MEDIA_REWIND:
72         case AKEYCODE_MEDIA_RECORD:
73         case AKEYCODE_MEDIA_FAST_FORWARD:
74         case AKEYCODE_MUTE:
75             return true;
76     }
77 
78     return false;
79 }
80 
hasDefaultAction() const81 bool KeyEvent::hasDefaultAction() const {
82     return hasDefaultAction(getKeyCode());
83 }
84 
isSystemKey(int32_t keyCode)85 bool KeyEvent::isSystemKey(int32_t keyCode) {
86     switch (keyCode) {
87         case AKEYCODE_MENU:
88         case AKEYCODE_SOFT_RIGHT:
89         case AKEYCODE_HOME:
90         case AKEYCODE_BACK:
91         case AKEYCODE_CALL:
92         case AKEYCODE_ENDCALL:
93         case AKEYCODE_VOLUME_UP:
94         case AKEYCODE_VOLUME_DOWN:
95         case AKEYCODE_VOLUME_MUTE:
96         case AKEYCODE_MUTE:
97         case AKEYCODE_POWER:
98         case AKEYCODE_HEADSETHOOK:
99         case AKEYCODE_MEDIA_PLAY:
100         case AKEYCODE_MEDIA_PAUSE:
101         case AKEYCODE_MEDIA_PLAY_PAUSE:
102         case AKEYCODE_MEDIA_STOP:
103         case AKEYCODE_MEDIA_NEXT:
104         case AKEYCODE_MEDIA_PREVIOUS:
105         case AKEYCODE_MEDIA_REWIND:
106         case AKEYCODE_MEDIA_RECORD:
107         case AKEYCODE_MEDIA_FAST_FORWARD:
108         case AKEYCODE_CAMERA:
109         case AKEYCODE_FOCUS:
110         case AKEYCODE_SEARCH:
111             return true;
112     }
113 
114     return false;
115 }
116 
isSystemKey() const117 bool KeyEvent::isSystemKey() const {
118     return isSystemKey(getKeyCode());
119 }
120 
initialize(int32_t deviceId,int32_t source,int32_t action,int32_t flags,int32_t keyCode,int32_t scanCode,int32_t metaState,int32_t repeatCount,nsecs_t downTime,nsecs_t eventTime)121 void 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 
initialize(const KeyEvent & from)143 void 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 
getAxisValue(int32_t axis) const158 float 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 
setAxisValue(int32_t axis,float value)171 status_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 
scaleAxisValue(PointerCoords & c,int axis,float scaleFactor)196 static 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 
scale(float scaleFactor)203 void 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
readFromParcel(Parcel * parcel)215 status_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->readInt32();
225     }
226     return OK;
227 }
228 
writeToParcel(Parcel * parcel) const229 status_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->writeInt32(values[i]);
235     }
236     return OK;
237 }
238 #endif
239 
tooManyAxes(int axis)240 void 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 
operator ==(const PointerCoords & other) const245 bool 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 
copyFrom(const PointerCoords & other)258 void 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 
operator ==(const PointerProperties & other) const269 bool PointerProperties::operator==(const PointerProperties& other) const {
270     return id == other.id
271             && toolType == other.toolType;
272 }
273 
copyFrom(const PointerProperties & other)274 void PointerProperties::copyFrom(const PointerProperties& other) {
275     id = other.id;
276     toolType = other.toolType;
277 }
278 
279 
280 // --- MotionEvent ---
281 
initialize(int32_t deviceId,int32_t source,int32_t action,int32_t flags,int32_t edgeFlags,int32_t metaState,int32_t buttonState,float xOffset,float yOffset,float xPrecision,float yPrecision,nsecs_t downTime,nsecs_t eventTime,size_t pointerCount,const PointerProperties * pointerProperties,const PointerCoords * pointerCoords)282 void 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 
copyFrom(const MotionEvent * other,bool keepHistory)317 void 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 
addSample(int64_t eventTime,const PointerCoords * pointerCoords)345 void MotionEvent::addSample(
346         int64_t eventTime,
347         const PointerCoords* pointerCoords) {
348     mSampleEventTimes.push(eventTime);
349     mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
350 }
351 
getRawPointerCoords(size_t pointerIndex) const352 const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
353     return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
354 }
355 
getRawAxisValue(int32_t axis,size_t pointerIndex) const356 float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
357     return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
358 }
359 
getAxisValue(int32_t axis,size_t pointerIndex) const360 float 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 
getHistoricalRawPointerCoords(size_t pointerIndex,size_t historicalIndex) const371 const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
372         size_t pointerIndex, size_t historicalIndex) const {
373     return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
374 }
375 
getHistoricalRawAxisValue(int32_t axis,size_t pointerIndex,size_t historicalIndex) const376 float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
377         size_t historicalIndex) const {
378     return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
379 }
380 
getHistoricalAxisValue(int32_t axis,size_t pointerIndex,size_t historicalIndex) const381 float 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 
findPointerIndex(int32_t pointerId) const393 ssize_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 
offsetLocation(float xOffset,float yOffset)403 void MotionEvent::offsetLocation(float xOffset, float yOffset) {
404     mXOffset += xOffset;
405     mYOffset += yOffset;
406 }
407 
scale(float scaleFactor)408 void 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 
420 #ifdef HAVE_ANDROID_OS
transformAngle(const SkMatrix * matrix,float angleRadians)421 static inline float transformAngle(const SkMatrix* matrix, float angleRadians) {
422     // Construct and transform a vector oriented at the specified clockwise angle from vertical.
423     // Coordinate system: down is increasing Y, right is increasing X.
424     SkPoint vector;
425     vector.fX = SkFloatToScalar(sinf(angleRadians));
426     vector.fY = SkFloatToScalar(-cosf(angleRadians));
427     matrix->mapVectors(& vector, 1);
428 
429     // Derive the transformed vector's clockwise angle from vertical.
430     float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY));
431     if (result < - M_PI_2) {
432         result += M_PI;
433     } else if (result > M_PI_2) {
434         result -= M_PI;
435     }
436     return result;
437 }
438 
transform(const SkMatrix * matrix)439 void MotionEvent::transform(const SkMatrix* matrix) {
440     float oldXOffset = mXOffset;
441     float oldYOffset = mYOffset;
442 
443     // The tricky part of this implementation is to preserve the value of
444     // rawX and rawY.  So we apply the transformation to the first point
445     // then derive an appropriate new X/Y offset that will preserve rawX and rawY.
446     SkPoint point;
447     float rawX = getRawX(0);
448     float rawY = getRawY(0);
449     matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset),
450             & point);
451     float newX = SkScalarToFloat(point.fX);
452     float newY = SkScalarToFloat(point.fY);
453     float newXOffset = newX - rawX;
454     float newYOffset = newY - rawY;
455 
456     mXOffset = newXOffset;
457     mYOffset = newYOffset;
458 
459     // Apply the transformation to all samples.
460     size_t numSamples = mSamplePointerCoords.size();
461     for (size_t i = 0; i < numSamples; i++) {
462         PointerCoords& c = mSamplePointerCoords.editItemAt(i);
463         float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset;
464         float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset;
465         matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), &point);
466         c.setAxisValue(AMOTION_EVENT_AXIS_X, SkScalarToFloat(point.fX) - newXOffset);
467         c.setAxisValue(AMOTION_EVENT_AXIS_Y, SkScalarToFloat(point.fY) - newYOffset);
468 
469         float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
470         c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(matrix, orientation));
471     }
472 }
473 
readFromParcel(Parcel * parcel)474 status_t MotionEvent::readFromParcel(Parcel* parcel) {
475     size_t pointerCount = parcel->readInt32();
476     size_t sampleCount = parcel->readInt32();
477     if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) {
478         return BAD_VALUE;
479     }
480 
481     mDeviceId = parcel->readInt32();
482     mSource = parcel->readInt32();
483     mAction = parcel->readInt32();
484     mFlags = parcel->readInt32();
485     mEdgeFlags = parcel->readInt32();
486     mMetaState = parcel->readInt32();
487     mButtonState = parcel->readInt32();
488     mXOffset = parcel->readFloat();
489     mYOffset = parcel->readFloat();
490     mXPrecision = parcel->readFloat();
491     mYPrecision = parcel->readFloat();
492     mDownTime = parcel->readInt64();
493 
494     mPointerProperties.clear();
495     mPointerProperties.setCapacity(pointerCount);
496     mSampleEventTimes.clear();
497     mSampleEventTimes.setCapacity(sampleCount);
498     mSamplePointerCoords.clear();
499     mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
500 
501     for (size_t i = 0; i < pointerCount; i++) {
502         mPointerProperties.push();
503         PointerProperties& properties = mPointerProperties.editTop();
504         properties.id = parcel->readInt32();
505         properties.toolType = parcel->readInt32();
506     }
507 
508     while (sampleCount-- > 0) {
509         mSampleEventTimes.push(parcel->readInt64());
510         for (size_t i = 0; i < pointerCount; i++) {
511             mSamplePointerCoords.push();
512             status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel);
513             if (status) {
514                 return status;
515             }
516         }
517     }
518     return OK;
519 }
520 
writeToParcel(Parcel * parcel) const521 status_t MotionEvent::writeToParcel(Parcel* parcel) const {
522     size_t pointerCount = mPointerProperties.size();
523     size_t sampleCount = mSampleEventTimes.size();
524 
525     parcel->writeInt32(pointerCount);
526     parcel->writeInt32(sampleCount);
527 
528     parcel->writeInt32(mDeviceId);
529     parcel->writeInt32(mSource);
530     parcel->writeInt32(mAction);
531     parcel->writeInt32(mFlags);
532     parcel->writeInt32(mEdgeFlags);
533     parcel->writeInt32(mMetaState);
534     parcel->writeInt32(mButtonState);
535     parcel->writeFloat(mXOffset);
536     parcel->writeFloat(mYOffset);
537     parcel->writeFloat(mXPrecision);
538     parcel->writeFloat(mYPrecision);
539     parcel->writeInt64(mDownTime);
540 
541     for (size_t i = 0; i < pointerCount; i++) {
542         const PointerProperties& properties = mPointerProperties.itemAt(i);
543         parcel->writeInt32(properties.id);
544         parcel->writeInt32(properties.toolType);
545     }
546 
547     const PointerCoords* pc = mSamplePointerCoords.array();
548     for (size_t h = 0; h < sampleCount; h++) {
549         parcel->writeInt64(mSampleEventTimes.itemAt(h));
550         for (size_t i = 0; i < pointerCount; i++) {
551             status_t status = (pc++)->writeToParcel(parcel);
552             if (status) {
553                 return status;
554             }
555         }
556     }
557     return OK;
558 }
559 #endif
560 
isTouchEvent(int32_t source,int32_t action)561 bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
562     if (source & AINPUT_SOURCE_CLASS_POINTER) {
563         // Specifically excludes HOVER_MOVE and SCROLL.
564         switch (action & AMOTION_EVENT_ACTION_MASK) {
565         case AMOTION_EVENT_ACTION_DOWN:
566         case AMOTION_EVENT_ACTION_MOVE:
567         case AMOTION_EVENT_ACTION_UP:
568         case AMOTION_EVENT_ACTION_POINTER_DOWN:
569         case AMOTION_EVENT_ACTION_POINTER_UP:
570         case AMOTION_EVENT_ACTION_CANCEL:
571         case AMOTION_EVENT_ACTION_OUTSIDE:
572             return true;
573         }
574     }
575     return false;
576 }
577 
578 
579 // --- PooledInputEventFactory ---
580 
PooledInputEventFactory(size_t maxPoolSize)581 PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) :
582         mMaxPoolSize(maxPoolSize) {
583 }
584 
~PooledInputEventFactory()585 PooledInputEventFactory::~PooledInputEventFactory() {
586     for (size_t i = 0; i < mKeyEventPool.size(); i++) {
587         delete mKeyEventPool.itemAt(i);
588     }
589     for (size_t i = 0; i < mMotionEventPool.size(); i++) {
590         delete mMotionEventPool.itemAt(i);
591     }
592 }
593 
createKeyEvent()594 KeyEvent* PooledInputEventFactory::createKeyEvent() {
595     if (!mKeyEventPool.isEmpty()) {
596         KeyEvent* event = mKeyEventPool.top();
597         mKeyEventPool.pop();
598         return event;
599     }
600     return new KeyEvent();
601 }
602 
createMotionEvent()603 MotionEvent* PooledInputEventFactory::createMotionEvent() {
604     if (!mMotionEventPool.isEmpty()) {
605         MotionEvent* event = mMotionEventPool.top();
606         mMotionEventPool.pop();
607         return event;
608     }
609     return new MotionEvent();
610 }
611 
recycle(InputEvent * event)612 void PooledInputEventFactory::recycle(InputEvent* event) {
613     switch (event->getType()) {
614     case AINPUT_EVENT_TYPE_KEY:
615         if (mKeyEventPool.size() < mMaxPoolSize) {
616             mKeyEventPool.push(static_cast<KeyEvent*>(event));
617             return;
618         }
619         break;
620     case AINPUT_EVENT_TYPE_MOTION:
621         if (mMotionEventPool.size() < mMaxPoolSize) {
622             mMotionEventPool.push(static_cast<MotionEvent*>(event));
623             return;
624         }
625         break;
626     }
627     delete event;
628 }
629 
630 } // namespace android
631