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