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