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