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