Home | History | Annotate | Download | only in input
      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 
     33 void InputEvent::initialize(int32_t deviceId, int32_t source) {
     34     mDeviceId = deviceId;
     35     mSource = source;
     36 }
     37 
     38 void InputEvent::initialize(const InputEvent& from) {
     39     mDeviceId = from.mDeviceId;
     40     mSource = from.mSource;
     41 }
     42 
     43 // --- KeyEvent ---
     44 
     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 
     80 bool KeyEvent::hasDefaultAction() const {
     81     return hasDefaultAction(getKeyCode());
     82 }
     83 
     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 
    119 bool KeyEvent::isSystemKey() const {
    120     return isSystemKey(getKeyCode());
    121 }
    122 
    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 
    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 
    160 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 
    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 
    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 
    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
    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 
    231 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 
    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 
    247 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 
    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 
    271 bool PointerProperties::operator==(const PointerProperties& other) const {
    272     return id == other.id
    273             && toolType == other.toolType;
    274 }
    275 
    276 void PointerProperties::copyFrom(const PointerProperties& other) {
    277     id = other.id;
    278     toolType = other.toolType;
    279 }
    280 
    281 
    282 // --- MotionEvent ---
    283 
    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 
    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 
    347 void MotionEvent::addSample(
    348         int64_t eventTime,
    349         const PointerCoords* pointerCoords) {
    350     mSampleEventTimes.push(eventTime);
    351     mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
    352 }
    353 
    354 const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
    355     return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
    356 }
    357 
    358 float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
    359     return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
    360 }
    361 
    362 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 
    373 const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
    374         size_t pointerIndex, size_t historicalIndex) const {
    375     return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
    376 }
    377 
    378 float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
    379         size_t historicalIndex) const {
    380     return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
    381 }
    382 
    383 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 
    395 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 
    405 void MotionEvent::offsetLocation(float xOffset, float yOffset) {
    406     mXOffset += xOffset;
    407     mYOffset += yOffset;
    408 }
    409 
    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 
    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 
    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 
    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
    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 
    537 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 
    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 
    597 PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) :
    598         mMaxPoolSize(maxPoolSize) {
    599 }
    600 
    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 
    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 
    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 
    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