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 <input/Input.h>
24 #include <input/InputEventLabels.h>
25 
26 #ifdef __ANDROID__
27 #include <binder/Parcel.h>
28 #endif
29 
30 namespace android {
31 
motionClassificationToString(MotionClassification classification)32 const char* motionClassificationToString(MotionClassification classification) {
33     switch (classification) {
34         case MotionClassification::NONE:
35             return "NONE";
36         case MotionClassification::AMBIGUOUS_GESTURE:
37             return "AMBIGUOUS_GESTURE";
38         case MotionClassification::DEEP_PRESS:
39             return "DEEP_PRESS";
40     }
41 }
42 
43 // --- InputEvent ---
44 
initialize(int32_t deviceId,int32_t source,int32_t displayId)45 void InputEvent::initialize(int32_t deviceId, int32_t source, int32_t displayId) {
46     mDeviceId = deviceId;
47     mSource = source;
48     mDisplayId = displayId;
49 }
50 
initialize(const InputEvent & from)51 void InputEvent::initialize(const InputEvent& from) {
52     mDeviceId = from.mDeviceId;
53     mSource = from.mSource;
54     mDisplayId = from.mDisplayId;
55 }
56 
57 // --- KeyEvent ---
58 
getLabel(int32_t keyCode)59 const char* KeyEvent::getLabel(int32_t keyCode) {
60     return getLabelByKeyCode(keyCode);
61 }
62 
getKeyCodeFromLabel(const char * label)63 int32_t KeyEvent::getKeyCodeFromLabel(const char* label) {
64     return getKeyCodeByLabel(label);
65 }
66 
initialize(int32_t deviceId,int32_t source,int32_t displayId,int32_t action,int32_t flags,int32_t keyCode,int32_t scanCode,int32_t metaState,int32_t repeatCount,nsecs_t downTime,nsecs_t eventTime)67 void KeyEvent::initialize(
68         int32_t deviceId,
69         int32_t source,
70         int32_t displayId,
71         int32_t action,
72         int32_t flags,
73         int32_t keyCode,
74         int32_t scanCode,
75         int32_t metaState,
76         int32_t repeatCount,
77         nsecs_t downTime,
78         nsecs_t eventTime) {
79     InputEvent::initialize(deviceId, source, displayId);
80     mAction = action;
81     mFlags = flags;
82     mKeyCode = keyCode;
83     mScanCode = scanCode;
84     mMetaState = metaState;
85     mRepeatCount = repeatCount;
86     mDownTime = downTime;
87     mEventTime = eventTime;
88 }
89 
initialize(const KeyEvent & from)90 void KeyEvent::initialize(const KeyEvent& from) {
91     InputEvent::initialize(from);
92     mAction = from.mAction;
93     mFlags = from.mFlags;
94     mKeyCode = from.mKeyCode;
95     mScanCode = from.mScanCode;
96     mMetaState = from.mMetaState;
97     mRepeatCount = from.mRepeatCount;
98     mDownTime = from.mDownTime;
99     mEventTime = from.mEventTime;
100 }
101 
102 
103 // --- PointerCoords ---
104 
getAxisValue(int32_t axis) const105 float PointerCoords::getAxisValue(int32_t axis) const {
106     if (axis < 0 || axis > 63 || !BitSet64::hasBit(bits, axis)){
107         return 0;
108     }
109     return values[BitSet64::getIndexOfBit(bits, axis)];
110 }
111 
setAxisValue(int32_t axis,float value)112 status_t PointerCoords::setAxisValue(int32_t axis, float value) {
113     if (axis < 0 || axis > 63) {
114         return NAME_NOT_FOUND;
115     }
116 
117     uint32_t index = BitSet64::getIndexOfBit(bits, axis);
118     if (!BitSet64::hasBit(bits, axis)) {
119         if (value == 0) {
120             return OK; // axes with value 0 do not need to be stored
121         }
122 
123         uint32_t count = BitSet64::count(bits);
124         if (count >= MAX_AXES) {
125             tooManyAxes(axis);
126             return NO_MEMORY;
127         }
128         BitSet64::markBit(bits, axis);
129         for (uint32_t i = count; i > index; i--) {
130             values[i] = values[i - 1];
131         }
132     }
133 
134     values[index] = value;
135     return OK;
136 }
137 
scaleAxisValue(PointerCoords & c,int axis,float scaleFactor)138 static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) {
139     float value = c.getAxisValue(axis);
140     if (value != 0) {
141         c.setAxisValue(axis, value * scaleFactor);
142     }
143 }
144 
scale(float globalScaleFactor,float windowXScale,float windowYScale)145 void PointerCoords::scale(float globalScaleFactor, float windowXScale, float windowYScale) {
146     // No need to scale pressure or size since they are normalized.
147     // No need to scale orientation since it is meaningless to do so.
148 
149     // If there is a global scale factor, it is included in the windowX/YScale
150     // so we don't need to apply it twice to the X/Y axes.
151     // However we don't want to apply any windowXYScale not included in the global scale
152     // to the TOUCH_MAJOR/MINOR coordinates.
153     scaleAxisValue(*this, AMOTION_EVENT_AXIS_X, windowXScale);
154     scaleAxisValue(*this, AMOTION_EVENT_AXIS_Y, windowYScale);
155     scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MAJOR, globalScaleFactor);
156     scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MINOR, globalScaleFactor);
157     scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MAJOR, globalScaleFactor);
158     scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, globalScaleFactor);
159 }
160 
scale(float globalScaleFactor)161 void PointerCoords::scale(float globalScaleFactor) {
162     scale(globalScaleFactor, globalScaleFactor, globalScaleFactor);
163 }
164 
applyOffset(float xOffset,float yOffset)165 void PointerCoords::applyOffset(float xOffset, float yOffset) {
166     setAxisValue(AMOTION_EVENT_AXIS_X, getX() + xOffset);
167     setAxisValue(AMOTION_EVENT_AXIS_Y, getY() + yOffset);
168 }
169 
170 #ifdef __ANDROID__
readFromParcel(Parcel * parcel)171 status_t PointerCoords::readFromParcel(Parcel* parcel) {
172     bits = parcel->readInt64();
173 
174     uint32_t count = BitSet64::count(bits);
175     if (count > MAX_AXES) {
176         return BAD_VALUE;
177     }
178 
179     for (uint32_t i = 0; i < count; i++) {
180         values[i] = parcel->readFloat();
181     }
182     return OK;
183 }
184 
writeToParcel(Parcel * parcel) const185 status_t PointerCoords::writeToParcel(Parcel* parcel) const {
186     parcel->writeInt64(bits);
187 
188     uint32_t count = BitSet64::count(bits);
189     for (uint32_t i = 0; i < count; i++) {
190         parcel->writeFloat(values[i]);
191     }
192     return OK;
193 }
194 #endif
195 
tooManyAxes(int axis)196 void PointerCoords::tooManyAxes(int axis) {
197     ALOGW("Could not set value for axis %d because the PointerCoords structure is full and "
198             "cannot contain more than %d axis values.", axis, int(MAX_AXES));
199 }
200 
operator ==(const PointerCoords & other) const201 bool PointerCoords::operator==(const PointerCoords& other) const {
202     if (bits != other.bits) {
203         return false;
204     }
205     uint32_t count = BitSet64::count(bits);
206     for (uint32_t i = 0; i < count; i++) {
207         if (values[i] != other.values[i]) {
208             return false;
209         }
210     }
211     return true;
212 }
213 
copyFrom(const PointerCoords & other)214 void PointerCoords::copyFrom(const PointerCoords& other) {
215     bits = other.bits;
216     uint32_t count = BitSet64::count(bits);
217     for (uint32_t i = 0; i < count; i++) {
218         values[i] = other.values[i];
219     }
220 }
221 
222 
223 // --- PointerProperties ---
224 
operator ==(const PointerProperties & other) const225 bool PointerProperties::operator==(const PointerProperties& other) const {
226     return id == other.id
227             && toolType == other.toolType;
228 }
229 
copyFrom(const PointerProperties & other)230 void PointerProperties::copyFrom(const PointerProperties& other) {
231     id = other.id;
232     toolType = other.toolType;
233 }
234 
235 
236 // --- MotionEvent ---
237 
initialize(int32_t deviceId,int32_t source,int32_t displayId,int32_t action,int32_t actionButton,int32_t flags,int32_t edgeFlags,int32_t metaState,int32_t buttonState,MotionClassification classification,float xOffset,float yOffset,float xPrecision,float yPrecision,nsecs_t downTime,nsecs_t eventTime,size_t pointerCount,const PointerProperties * pointerProperties,const PointerCoords * pointerCoords)238 void MotionEvent::initialize(
239         int32_t deviceId,
240         int32_t source,
241         int32_t displayId,
242         int32_t action,
243         int32_t actionButton,
244         int32_t flags,
245         int32_t edgeFlags,
246         int32_t metaState,
247         int32_t buttonState,
248         MotionClassification classification,
249         float xOffset,
250         float yOffset,
251         float xPrecision,
252         float yPrecision,
253         nsecs_t downTime,
254         nsecs_t eventTime,
255         size_t pointerCount,
256         const PointerProperties* pointerProperties,
257         const PointerCoords* pointerCoords) {
258     InputEvent::initialize(deviceId, source, displayId);
259     mAction = action;
260     mActionButton = actionButton;
261     mFlags = flags;
262     mEdgeFlags = edgeFlags;
263     mMetaState = metaState;
264     mButtonState = buttonState;
265     mClassification = classification;
266     mXOffset = xOffset;
267     mYOffset = yOffset;
268     mXPrecision = xPrecision;
269     mYPrecision = yPrecision;
270     mDownTime = downTime;
271     mPointerProperties.clear();
272     mPointerProperties.appendArray(pointerProperties, pointerCount);
273     mSampleEventTimes.clear();
274     mSamplePointerCoords.clear();
275     addSample(eventTime, pointerCoords);
276 }
277 
copyFrom(const MotionEvent * other,bool keepHistory)278 void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
279     InputEvent::initialize(other->mDeviceId, other->mSource, other->mDisplayId);
280     mAction = other->mAction;
281     mActionButton = other->mActionButton;
282     mFlags = other->mFlags;
283     mEdgeFlags = other->mEdgeFlags;
284     mMetaState = other->mMetaState;
285     mButtonState = other->mButtonState;
286     mClassification = other->mClassification;
287     mXOffset = other->mXOffset;
288     mYOffset = other->mYOffset;
289     mXPrecision = other->mXPrecision;
290     mYPrecision = other->mYPrecision;
291     mDownTime = other->mDownTime;
292     mPointerProperties = other->mPointerProperties;
293 
294     if (keepHistory) {
295         mSampleEventTimes = other->mSampleEventTimes;
296         mSamplePointerCoords = other->mSamplePointerCoords;
297     } else {
298         mSampleEventTimes.clear();
299         mSampleEventTimes.push(other->getEventTime());
300         mSamplePointerCoords.clear();
301         size_t pointerCount = other->getPointerCount();
302         size_t historySize = other->getHistorySize();
303         mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array()
304                 + (historySize * pointerCount), pointerCount);
305     }
306 }
307 
addSample(int64_t eventTime,const PointerCoords * pointerCoords)308 void MotionEvent::addSample(
309         int64_t eventTime,
310         const PointerCoords* pointerCoords) {
311     mSampleEventTimes.push(eventTime);
312     mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
313 }
314 
getRawPointerCoords(size_t pointerIndex) const315 const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
316     return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
317 }
318 
getRawAxisValue(int32_t axis,size_t pointerIndex) const319 float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
320     return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
321 }
322 
getAxisValue(int32_t axis,size_t pointerIndex) const323 float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const {
324     float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis);
325     switch (axis) {
326     case AMOTION_EVENT_AXIS_X:
327         return value + mXOffset;
328     case AMOTION_EVENT_AXIS_Y:
329         return value + mYOffset;
330     }
331     return value;
332 }
333 
getHistoricalRawPointerCoords(size_t pointerIndex,size_t historicalIndex) const334 const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
335         size_t pointerIndex, size_t historicalIndex) const {
336     return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
337 }
338 
getHistoricalRawAxisValue(int32_t axis,size_t pointerIndex,size_t historicalIndex) const339 float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
340         size_t historicalIndex) const {
341     return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
342 }
343 
getHistoricalAxisValue(int32_t axis,size_t pointerIndex,size_t historicalIndex) const344 float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
345         size_t historicalIndex) const {
346     float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
347     switch (axis) {
348     case AMOTION_EVENT_AXIS_X:
349         return value + mXOffset;
350     case AMOTION_EVENT_AXIS_Y:
351         return value + mYOffset;
352     }
353     return value;
354 }
355 
findPointerIndex(int32_t pointerId) const356 ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
357     size_t pointerCount = mPointerProperties.size();
358     for (size_t i = 0; i < pointerCount; i++) {
359         if (mPointerProperties.itemAt(i).id == pointerId) {
360             return i;
361         }
362     }
363     return -1;
364 }
365 
offsetLocation(float xOffset,float yOffset)366 void MotionEvent::offsetLocation(float xOffset, float yOffset) {
367     mXOffset += xOffset;
368     mYOffset += yOffset;
369 }
370 
scale(float globalScaleFactor)371 void MotionEvent::scale(float globalScaleFactor) {
372     mXOffset *= globalScaleFactor;
373     mYOffset *= globalScaleFactor;
374     mXPrecision *= globalScaleFactor;
375     mYPrecision *= globalScaleFactor;
376 
377     size_t numSamples = mSamplePointerCoords.size();
378     for (size_t i = 0; i < numSamples; i++) {
379         mSamplePointerCoords.editItemAt(i).scale(globalScaleFactor);
380     }
381 }
382 
transformPoint(const float matrix[9],float x,float y,float * outX,float * outY)383 static void transformPoint(const float matrix[9], float x, float y, float *outX, float *outY) {
384     // Apply perspective transform like Skia.
385     float newX = matrix[0] * x + matrix[1] * y + matrix[2];
386     float newY = matrix[3] * x + matrix[4] * y + matrix[5];
387     float newZ = matrix[6] * x + matrix[7] * y + matrix[8];
388     if (newZ) {
389         newZ = 1.0f / newZ;
390     }
391     *outX = newX * newZ;
392     *outY = newY * newZ;
393 }
394 
transformAngle(const float matrix[9],float angleRadians,float originX,float originY)395 static float transformAngle(const float matrix[9], float angleRadians,
396         float originX, float originY) {
397     // Construct and transform a vector oriented at the specified clockwise angle from vertical.
398     // Coordinate system: down is increasing Y, right is increasing X.
399     float x = sinf(angleRadians);
400     float y = -cosf(angleRadians);
401     transformPoint(matrix, x, y, &x, &y);
402     x -= originX;
403     y -= originY;
404 
405     // Derive the transformed vector's clockwise angle from vertical.
406     float result = atan2f(x, -y);
407     if (result < - M_PI_2) {
408         result += M_PI;
409     } else if (result > M_PI_2) {
410         result -= M_PI;
411     }
412     return result;
413 }
414 
transform(const float matrix[9])415 void MotionEvent::transform(const float matrix[9]) {
416     // The tricky part of this implementation is to preserve the value of
417     // rawX and rawY.  So we apply the transformation to the first point
418     // then derive an appropriate new X/Y offset that will preserve rawX
419      // and rawY for that point.
420     float oldXOffset = mXOffset;
421     float oldYOffset = mYOffset;
422     float newX, newY;
423     float rawX = getRawX(0);
424     float rawY = getRawY(0);
425     transformPoint(matrix, rawX + oldXOffset, rawY + oldYOffset, &newX, &newY);
426     mXOffset = newX - rawX;
427     mYOffset = newY - rawY;
428 
429     // Determine how the origin is transformed by the matrix so that we
430     // can transform orientation vectors.
431     float originX, originY;
432     transformPoint(matrix, 0, 0, &originX, &originY);
433 
434     // Apply the transformation to all samples.
435     size_t numSamples = mSamplePointerCoords.size();
436     for (size_t i = 0; i < numSamples; i++) {
437         PointerCoords& c = mSamplePointerCoords.editItemAt(i);
438         float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset;
439         float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset;
440         transformPoint(matrix, x, y, &x, &y);
441         c.setAxisValue(AMOTION_EVENT_AXIS_X, x - mXOffset);
442         c.setAxisValue(AMOTION_EVENT_AXIS_Y, y - mYOffset);
443 
444         float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
445         c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
446                 transformAngle(matrix, orientation, originX, originY));
447     }
448 }
449 
450 #ifdef __ANDROID__
readFromParcel(Parcel * parcel)451 status_t MotionEvent::readFromParcel(Parcel* parcel) {
452     size_t pointerCount = parcel->readInt32();
453     size_t sampleCount = parcel->readInt32();
454     if (pointerCount == 0 || pointerCount > MAX_POINTERS ||
455             sampleCount == 0 || sampleCount > MAX_SAMPLES) {
456         return BAD_VALUE;
457     }
458 
459     mDeviceId = parcel->readInt32();
460     mSource = parcel->readInt32();
461     mDisplayId = parcel->readInt32();
462     mAction = parcel->readInt32();
463     mActionButton = parcel->readInt32();
464     mFlags = parcel->readInt32();
465     mEdgeFlags = parcel->readInt32();
466     mMetaState = parcel->readInt32();
467     mButtonState = parcel->readInt32();
468     mClassification = static_cast<MotionClassification>(parcel->readByte());
469     mXOffset = parcel->readFloat();
470     mYOffset = parcel->readFloat();
471     mXPrecision = parcel->readFloat();
472     mYPrecision = parcel->readFloat();
473     mDownTime = parcel->readInt64();
474 
475     mPointerProperties.clear();
476     mPointerProperties.setCapacity(pointerCount);
477     mSampleEventTimes.clear();
478     mSampleEventTimes.setCapacity(sampleCount);
479     mSamplePointerCoords.clear();
480     mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
481 
482     for (size_t i = 0; i < pointerCount; i++) {
483         mPointerProperties.push();
484         PointerProperties& properties = mPointerProperties.editTop();
485         properties.id = parcel->readInt32();
486         properties.toolType = parcel->readInt32();
487     }
488 
489     while (sampleCount > 0) {
490         sampleCount--;
491         mSampleEventTimes.push(parcel->readInt64());
492         for (size_t i = 0; i < pointerCount; i++) {
493             mSamplePointerCoords.push();
494             status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel);
495             if (status) {
496                 return status;
497             }
498         }
499     }
500     return OK;
501 }
502 
writeToParcel(Parcel * parcel) const503 status_t MotionEvent::writeToParcel(Parcel* parcel) const {
504     size_t pointerCount = mPointerProperties.size();
505     size_t sampleCount = mSampleEventTimes.size();
506 
507     parcel->writeInt32(pointerCount);
508     parcel->writeInt32(sampleCount);
509 
510     parcel->writeInt32(mDeviceId);
511     parcel->writeInt32(mSource);
512     parcel->writeInt32(mDisplayId);
513     parcel->writeInt32(mAction);
514     parcel->writeInt32(mActionButton);
515     parcel->writeInt32(mFlags);
516     parcel->writeInt32(mEdgeFlags);
517     parcel->writeInt32(mMetaState);
518     parcel->writeInt32(mButtonState);
519     parcel->writeByte(static_cast<int8_t>(mClassification));
520     parcel->writeFloat(mXOffset);
521     parcel->writeFloat(mYOffset);
522     parcel->writeFloat(mXPrecision);
523     parcel->writeFloat(mYPrecision);
524     parcel->writeInt64(mDownTime);
525 
526     for (size_t i = 0; i < pointerCount; i++) {
527         const PointerProperties& properties = mPointerProperties.itemAt(i);
528         parcel->writeInt32(properties.id);
529         parcel->writeInt32(properties.toolType);
530     }
531 
532     const PointerCoords* pc = mSamplePointerCoords.array();
533     for (size_t h = 0; h < sampleCount; h++) {
534         parcel->writeInt64(mSampleEventTimes.itemAt(h));
535         for (size_t i = 0; i < pointerCount; i++) {
536             status_t status = (pc++)->writeToParcel(parcel);
537             if (status) {
538                 return status;
539             }
540         }
541     }
542     return OK;
543 }
544 #endif
545 
isTouchEvent(int32_t source,int32_t action)546 bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
547     if (source & AINPUT_SOURCE_CLASS_POINTER) {
548         // Specifically excludes HOVER_MOVE and SCROLL.
549         switch (action & AMOTION_EVENT_ACTION_MASK) {
550         case AMOTION_EVENT_ACTION_DOWN:
551         case AMOTION_EVENT_ACTION_MOVE:
552         case AMOTION_EVENT_ACTION_UP:
553         case AMOTION_EVENT_ACTION_POINTER_DOWN:
554         case AMOTION_EVENT_ACTION_POINTER_UP:
555         case AMOTION_EVENT_ACTION_CANCEL:
556         case AMOTION_EVENT_ACTION_OUTSIDE:
557             return true;
558         }
559     }
560     return false;
561 }
562 
getLabel(int32_t axis)563 const char* MotionEvent::getLabel(int32_t axis) {
564     return getAxisLabel(axis);
565 }
566 
getAxisFromLabel(const char * label)567 int32_t MotionEvent::getAxisFromLabel(const char* label) {
568     return getAxisByLabel(label);
569 }
570 
571 
572 // --- PooledInputEventFactory ---
573 
PooledInputEventFactory(size_t maxPoolSize)574 PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) :
575         mMaxPoolSize(maxPoolSize) {
576 }
577 
~PooledInputEventFactory()578 PooledInputEventFactory::~PooledInputEventFactory() {
579     for (size_t i = 0; i < mKeyEventPool.size(); i++) {
580         delete mKeyEventPool.itemAt(i);
581     }
582     for (size_t i = 0; i < mMotionEventPool.size(); i++) {
583         delete mMotionEventPool.itemAt(i);
584     }
585 }
586 
createKeyEvent()587 KeyEvent* PooledInputEventFactory::createKeyEvent() {
588     if (!mKeyEventPool.isEmpty()) {
589         KeyEvent* event = mKeyEventPool.top();
590         mKeyEventPool.pop();
591         return event;
592     }
593     return new KeyEvent();
594 }
595 
createMotionEvent()596 MotionEvent* PooledInputEventFactory::createMotionEvent() {
597     if (!mMotionEventPool.isEmpty()) {
598         MotionEvent* event = mMotionEventPool.top();
599         mMotionEventPool.pop();
600         return event;
601     }
602     return new MotionEvent();
603 }
604 
recycle(InputEvent * event)605 void PooledInputEventFactory::recycle(InputEvent* event) {
606     switch (event->getType()) {
607     case AINPUT_EVENT_TYPE_KEY:
608         if (mKeyEventPool.size() < mMaxPoolSize) {
609             mKeyEventPool.push(static_cast<KeyEvent*>(event));
610             return;
611         }
612         break;
613     case AINPUT_EVENT_TYPE_MOTION:
614         if (mMotionEventPool.size() < mMaxPoolSize) {
615             mMotionEventPool.push(static_cast<MotionEvent*>(event));
616             return;
617         }
618         break;
619     }
620     delete event;
621 }
622 
623 } // namespace android
624