• 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 <input/Input.h>
24 
25 #ifdef HAVE_ANDROID_OS
26 #include <binder/Parcel.h>
27 #endif
28 
29 namespace android {
30 
31 // --- InputEvent ---
32 
initialize(int32_t deviceId,int32_t source)33 void InputEvent::initialize(int32_t deviceId, int32_t source) {
34     mDeviceId = deviceId;
35     mSource = source;
36 }
37 
initialize(const InputEvent & from)38 void InputEvent::initialize(const InputEvent& from) {
39     mDeviceId = from.mDeviceId;
40     mSource = from.mSource;
41 }
42 
43 // --- KeyEvent ---
44 
hasDefaultAction(int32_t keyCode)45 bool 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         case AKEYCODE_MEDIA_AUDIO_TRACK:
74             return true;
75     }
76 
77     return false;
78 }
79 
hasDefaultAction() const80 bool KeyEvent::hasDefaultAction() const {
81     return hasDefaultAction(getKeyCode());
82 }
83 
isSystemKey(int32_t keyCode)84 bool 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:
112         case AKEYCODE_MEDIA_AUDIO_TRACK:
113             return true;
114     }
115 
116     return false;
117 }
118 
isSystemKey() const119 bool KeyEvent::isSystemKey() const {
120     return isSystemKey(getKeyCode());
121 }
122 
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)123 void 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 
initialize(const KeyEvent & from)145 void 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 
getAxisValue(int32_t axis) const160 float 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 
setAxisValue(int32_t axis,float value)173 status_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 
scaleAxisValue(PointerCoords & c,int axis,float scaleFactor)198 static 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 
scale(float scaleFactor)205 void 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 
216 #ifdef HAVE_ANDROID_OS
readFromParcel(Parcel * parcel)217 status_t PointerCoords::readFromParcel(Parcel* parcel) {
218     bits = parcel->readInt64();
219 
220     uint32_t count = __builtin_popcountll(bits);
221     if (count > MAX_AXES) {
222         return BAD_VALUE;
223     }
224 
225     for (uint32_t i = 0; i < count; i++) {
226         values[i] = parcel->readFloat();
227     }
228     return OK;
229 }
230 
writeToParcel(Parcel * parcel) const231 status_t PointerCoords::writeToParcel(Parcel* parcel) const {
232     parcel->writeInt64(bits);
233 
234     uint32_t count = __builtin_popcountll(bits);
235     for (uint32_t i = 0; i < count; i++) {
236         parcel->writeFloat(values[i]);
237     }
238     return OK;
239 }
240 #endif
241 
tooManyAxes(int axis)242 void PointerCoords::tooManyAxes(int axis) {
243     ALOGW("Could not set value for axis %d because the PointerCoords structure is full and "
244             "cannot contain more than %d axis values.", axis, int(MAX_AXES));
245 }
246 
operator ==(const PointerCoords & other) const247 bool PointerCoords::operator==(const PointerCoords& other) const {
248     if (bits != other.bits) {
249         return false;
250     }
251     uint32_t count = __builtin_popcountll(bits);
252     for (uint32_t i = 0; i < count; i++) {
253         if (values[i] != other.values[i]) {
254             return false;
255         }
256     }
257     return true;
258 }
259 
copyFrom(const PointerCoords & other)260 void PointerCoords::copyFrom(const PointerCoords& other) {
261     bits = other.bits;
262     uint32_t count = __builtin_popcountll(bits);
263     for (uint32_t i = 0; i < count; i++) {
264         values[i] = other.values[i];
265     }
266 }
267 
268 
269 // --- PointerProperties ---
270 
operator ==(const PointerProperties & other) const271 bool PointerProperties::operator==(const PointerProperties& other) const {
272     return id == other.id
273             && toolType == other.toolType;
274 }
275 
copyFrom(const PointerProperties & other)276 void PointerProperties::copyFrom(const PointerProperties& other) {
277     id = other.id;
278     toolType = other.toolType;
279 }
280 
281 
282 // --- MotionEvent ---
283 
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)284 void MotionEvent::initialize(
285         int32_t deviceId,
286         int32_t source,
287         int32_t action,
288         int32_t flags,
289         int32_t edgeFlags,
290         int32_t metaState,
291         int32_t buttonState,
292         float xOffset,
293         float yOffset,
294         float xPrecision,
295         float yPrecision,
296         nsecs_t downTime,
297         nsecs_t eventTime,
298         size_t pointerCount,
299         const PointerProperties* pointerProperties,
300         const PointerCoords* pointerCoords) {
301     InputEvent::initialize(deviceId, source);
302     mAction = action;
303     mFlags = flags;
304     mEdgeFlags = edgeFlags;
305     mMetaState = metaState;
306     mButtonState = buttonState;
307     mXOffset = xOffset;
308     mYOffset = yOffset;
309     mXPrecision = xPrecision;
310     mYPrecision = yPrecision;
311     mDownTime = downTime;
312     mPointerProperties.clear();
313     mPointerProperties.appendArray(pointerProperties, pointerCount);
314     mSampleEventTimes.clear();
315     mSamplePointerCoords.clear();
316     addSample(eventTime, pointerCoords);
317 }
318 
copyFrom(const MotionEvent * other,bool keepHistory)319 void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
320     InputEvent::initialize(other->mDeviceId, other->mSource);
321     mAction = other->mAction;
322     mFlags = other->mFlags;
323     mEdgeFlags = other->mEdgeFlags;
324     mMetaState = other->mMetaState;
325     mButtonState = other->mButtonState;
326     mXOffset = other->mXOffset;
327     mYOffset = other->mYOffset;
328     mXPrecision = other->mXPrecision;
329     mYPrecision = other->mYPrecision;
330     mDownTime = other->mDownTime;
331     mPointerProperties = other->mPointerProperties;
332 
333     if (keepHistory) {
334         mSampleEventTimes = other->mSampleEventTimes;
335         mSamplePointerCoords = other->mSamplePointerCoords;
336     } else {
337         mSampleEventTimes.clear();
338         mSampleEventTimes.push(other->getEventTime());
339         mSamplePointerCoords.clear();
340         size_t pointerCount = other->getPointerCount();
341         size_t historySize = other->getHistorySize();
342         mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array()
343                 + (historySize * pointerCount), pointerCount);
344     }
345 }
346 
addSample(int64_t eventTime,const PointerCoords * pointerCoords)347 void MotionEvent::addSample(
348         int64_t eventTime,
349         const PointerCoords* pointerCoords) {
350     mSampleEventTimes.push(eventTime);
351     mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
352 }
353 
getRawPointerCoords(size_t pointerIndex) const354 const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
355     return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
356 }
357 
getRawAxisValue(int32_t axis,size_t pointerIndex) const358 float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
359     return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
360 }
361 
getAxisValue(int32_t axis,size_t pointerIndex) const362 float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const {
363     float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis);
364     switch (axis) {
365     case AMOTION_EVENT_AXIS_X:
366         return value + mXOffset;
367     case AMOTION_EVENT_AXIS_Y:
368         return value + mYOffset;
369     }
370     return value;
371 }
372 
getHistoricalRawPointerCoords(size_t pointerIndex,size_t historicalIndex) const373 const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
374         size_t pointerIndex, size_t historicalIndex) const {
375     return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
376 }
377 
getHistoricalRawAxisValue(int32_t axis,size_t pointerIndex,size_t historicalIndex) const378 float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
379         size_t historicalIndex) const {
380     return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
381 }
382 
getHistoricalAxisValue(int32_t axis,size_t pointerIndex,size_t historicalIndex) const383 float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
384         size_t historicalIndex) const {
385     float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
386     switch (axis) {
387     case AMOTION_EVENT_AXIS_X:
388         return value + mXOffset;
389     case AMOTION_EVENT_AXIS_Y:
390         return value + mYOffset;
391     }
392     return value;
393 }
394 
findPointerIndex(int32_t pointerId) const395 ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
396     size_t pointerCount = mPointerProperties.size();
397     for (size_t i = 0; i < pointerCount; i++) {
398         if (mPointerProperties.itemAt(i).id == pointerId) {
399             return i;
400         }
401     }
402     return -1;
403 }
404 
offsetLocation(float xOffset,float yOffset)405 void MotionEvent::offsetLocation(float xOffset, float yOffset) {
406     mXOffset += xOffset;
407     mYOffset += yOffset;
408 }
409 
scale(float scaleFactor)410 void MotionEvent::scale(float scaleFactor) {
411     mXOffset *= scaleFactor;
412     mYOffset *= scaleFactor;
413     mXPrecision *= scaleFactor;
414     mYPrecision *= scaleFactor;
415 
416     size_t numSamples = mSamplePointerCoords.size();
417     for (size_t i = 0; i < numSamples; i++) {
418         mSamplePointerCoords.editItemAt(i).scale(scaleFactor);
419     }
420 }
421 
transformPoint(const float matrix[9],float x,float y,float * outX,float * outY)422 static void transformPoint(const float matrix[9], float x, float y, float *outX, float *outY) {
423     // Apply perspective transform like Skia.
424     float newX = matrix[0] * x + matrix[1] * y + matrix[2];
425     float newY = matrix[3] * x + matrix[4] * y + matrix[5];
426     float newZ = matrix[6] * x + matrix[7] * y + matrix[8];
427     if (newZ) {
428         newZ = 1.0f / newZ;
429     }
430     *outX = newX * newZ;
431     *outY = newY * newZ;
432 }
433 
transformAngle(const float matrix[9],float angleRadians,float originX,float originY)434 static float transformAngle(const float matrix[9], float angleRadians,
435         float originX, float originY) {
436     // Construct and transform a vector oriented at the specified clockwise angle from vertical.
437     // Coordinate system: down is increasing Y, right is increasing X.
438     float x = sinf(angleRadians);
439     float y = -cosf(angleRadians);
440     transformPoint(matrix, x, y, &x, &y);
441     x -= originX;
442     y -= originY;
443 
444     // Derive the transformed vector's clockwise angle from vertical.
445     float result = atan2f(x, -y);
446     if (result < - M_PI_2) {
447         result += M_PI;
448     } else if (result > M_PI_2) {
449         result -= M_PI;
450     }
451     return result;
452 }
453 
transform(const float matrix[9])454 void MotionEvent::transform(const float matrix[9]) {
455     // The tricky part of this implementation is to preserve the value of
456     // rawX and rawY.  So we apply the transformation to the first point
457     // then derive an appropriate new X/Y offset that will preserve rawX
458      // and rawY for that point.
459     float oldXOffset = mXOffset;
460     float oldYOffset = mYOffset;
461     float newX, newY;
462     float rawX = getRawX(0);
463     float rawY = getRawY(0);
464     transformPoint(matrix, rawX + oldXOffset, rawY + oldYOffset, &newX, &newY);
465     mXOffset = newX - rawX;
466     mYOffset = newY - rawY;
467 
468     // Determine how the origin is transformed by the matrix so that we
469     // can transform orientation vectors.
470     float originX, originY;
471     transformPoint(matrix, 0, 0, &originX, &originY);
472 
473     // Apply the transformation to all samples.
474     size_t numSamples = mSamplePointerCoords.size();
475     for (size_t i = 0; i < numSamples; i++) {
476         PointerCoords& c = mSamplePointerCoords.editItemAt(i);
477         float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset;
478         float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset;
479         transformPoint(matrix, x, y, &x, &y);
480         c.setAxisValue(AMOTION_EVENT_AXIS_X, x - mXOffset);
481         c.setAxisValue(AMOTION_EVENT_AXIS_Y, y - mYOffset);
482 
483         float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
484         c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
485                 transformAngle(matrix, orientation, originX, originY));
486     }
487 }
488 
489 #ifdef HAVE_ANDROID_OS
readFromParcel(Parcel * parcel)490 status_t MotionEvent::readFromParcel(Parcel* parcel) {
491     size_t pointerCount = parcel->readInt32();
492     size_t sampleCount = parcel->readInt32();
493     if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) {
494         return BAD_VALUE;
495     }
496 
497     mDeviceId = parcel->readInt32();
498     mSource = parcel->readInt32();
499     mAction = parcel->readInt32();
500     mFlags = parcel->readInt32();
501     mEdgeFlags = parcel->readInt32();
502     mMetaState = parcel->readInt32();
503     mButtonState = parcel->readInt32();
504     mXOffset = parcel->readFloat();
505     mYOffset = parcel->readFloat();
506     mXPrecision = parcel->readFloat();
507     mYPrecision = parcel->readFloat();
508     mDownTime = parcel->readInt64();
509 
510     mPointerProperties.clear();
511     mPointerProperties.setCapacity(pointerCount);
512     mSampleEventTimes.clear();
513     mSampleEventTimes.setCapacity(sampleCount);
514     mSamplePointerCoords.clear();
515     mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
516 
517     for (size_t i = 0; i < pointerCount; i++) {
518         mPointerProperties.push();
519         PointerProperties& properties = mPointerProperties.editTop();
520         properties.id = parcel->readInt32();
521         properties.toolType = parcel->readInt32();
522     }
523 
524     while (sampleCount-- > 0) {
525         mSampleEventTimes.push(parcel->readInt64());
526         for (size_t i = 0; i < pointerCount; i++) {
527             mSamplePointerCoords.push();
528             status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel);
529             if (status) {
530                 return status;
531             }
532         }
533     }
534     return OK;
535 }
536 
writeToParcel(Parcel * parcel) const537 status_t MotionEvent::writeToParcel(Parcel* parcel) const {
538     size_t pointerCount = mPointerProperties.size();
539     size_t sampleCount = mSampleEventTimes.size();
540 
541     parcel->writeInt32(pointerCount);
542     parcel->writeInt32(sampleCount);
543 
544     parcel->writeInt32(mDeviceId);
545     parcel->writeInt32(mSource);
546     parcel->writeInt32(mAction);
547     parcel->writeInt32(mFlags);
548     parcel->writeInt32(mEdgeFlags);
549     parcel->writeInt32(mMetaState);
550     parcel->writeInt32(mButtonState);
551     parcel->writeFloat(mXOffset);
552     parcel->writeFloat(mYOffset);
553     parcel->writeFloat(mXPrecision);
554     parcel->writeFloat(mYPrecision);
555     parcel->writeInt64(mDownTime);
556 
557     for (size_t i = 0; i < pointerCount; i++) {
558         const PointerProperties& properties = mPointerProperties.itemAt(i);
559         parcel->writeInt32(properties.id);
560         parcel->writeInt32(properties.toolType);
561     }
562 
563     const PointerCoords* pc = mSamplePointerCoords.array();
564     for (size_t h = 0; h < sampleCount; h++) {
565         parcel->writeInt64(mSampleEventTimes.itemAt(h));
566         for (size_t i = 0; i < pointerCount; i++) {
567             status_t status = (pc++)->writeToParcel(parcel);
568             if (status) {
569                 return status;
570             }
571         }
572     }
573     return OK;
574 }
575 #endif
576 
isTouchEvent(int32_t source,int32_t action)577 bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
578     if (source & AINPUT_SOURCE_CLASS_POINTER) {
579         // Specifically excludes HOVER_MOVE and SCROLL.
580         switch (action & AMOTION_EVENT_ACTION_MASK) {
581         case AMOTION_EVENT_ACTION_DOWN:
582         case AMOTION_EVENT_ACTION_MOVE:
583         case AMOTION_EVENT_ACTION_UP:
584         case AMOTION_EVENT_ACTION_POINTER_DOWN:
585         case AMOTION_EVENT_ACTION_POINTER_UP:
586         case AMOTION_EVENT_ACTION_CANCEL:
587         case AMOTION_EVENT_ACTION_OUTSIDE:
588             return true;
589         }
590     }
591     return false;
592 }
593 
594 
595 // --- PooledInputEventFactory ---
596 
PooledInputEventFactory(size_t maxPoolSize)597 PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) :
598         mMaxPoolSize(maxPoolSize) {
599 }
600 
~PooledInputEventFactory()601 PooledInputEventFactory::~PooledInputEventFactory() {
602     for (size_t i = 0; i < mKeyEventPool.size(); i++) {
603         delete mKeyEventPool.itemAt(i);
604     }
605     for (size_t i = 0; i < mMotionEventPool.size(); i++) {
606         delete mMotionEventPool.itemAt(i);
607     }
608 }
609 
createKeyEvent()610 KeyEvent* PooledInputEventFactory::createKeyEvent() {
611     if (!mKeyEventPool.isEmpty()) {
612         KeyEvent* event = mKeyEventPool.top();
613         mKeyEventPool.pop();
614         return event;
615     }
616     return new KeyEvent();
617 }
618 
createMotionEvent()619 MotionEvent* PooledInputEventFactory::createMotionEvent() {
620     if (!mMotionEventPool.isEmpty()) {
621         MotionEvent* event = mMotionEventPool.top();
622         mMotionEventPool.pop();
623         return event;
624     }
625     return new MotionEvent();
626 }
627 
recycle(InputEvent * event)628 void PooledInputEventFactory::recycle(InputEvent* event) {
629     switch (event->getType()) {
630     case AINPUT_EVENT_TYPE_KEY:
631         if (mKeyEventPool.size() < mMaxPoolSize) {
632             mKeyEventPool.push(static_cast<KeyEvent*>(event));
633             return;
634         }
635         break;
636     case AINPUT_EVENT_TYPE_MOTION:
637         if (mMotionEventPool.size() < mMaxPoolSize) {
638             mMotionEventPool.push(static_cast<MotionEvent*>(event));
639             return;
640         }
641         break;
642     }
643     delete event;
644 }
645 
646 } // namespace android
647