123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592 |
- /*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #define LOG_TAG "Input"
- //#define LOG_NDEBUG 0
- #include <math.h>
- #include <limits.h>
- #include <input/Input.h>
- #include <input/InputEventLabels.h>
- #ifdef HAVE_ANDROID_OS
- #include <binder/Parcel.h>
- #endif
- namespace android {
- // --- InputEvent ---
- void InputEvent::initialize(int32_t deviceId, int32_t source) {
- mDeviceId = deviceId;
- mSource = source;
- }
- void InputEvent::initialize(const InputEvent& from) {
- mDeviceId = from.mDeviceId;
- mSource = from.mSource;
- }
- // --- KeyEvent ---
- const char* KeyEvent::getLabel(int32_t keyCode) {
- return getLabelByKeyCode(keyCode);
- }
- int32_t KeyEvent::getKeyCodeFromLabel(const char* label) {
- return getKeyCodeByLabel(label);
- }
- void KeyEvent::initialize(
- int32_t deviceId,
- int32_t source,
- int32_t action,
- int32_t flags,
- int32_t keyCode,
- int32_t scanCode,
- int32_t metaState,
- int32_t repeatCount,
- nsecs_t downTime,
- nsecs_t eventTime) {
- InputEvent::initialize(deviceId, source);
- mAction = action;
- mFlags = flags;
- mKeyCode = keyCode;
- mScanCode = scanCode;
- mMetaState = metaState;
- mRepeatCount = repeatCount;
- mDownTime = downTime;
- mEventTime = eventTime;
- }
- void KeyEvent::initialize(const KeyEvent& from) {
- InputEvent::initialize(from);
- mAction = from.mAction;
- mFlags = from.mFlags;
- mKeyCode = from.mKeyCode;
- mScanCode = from.mScanCode;
- mMetaState = from.mMetaState;
- mRepeatCount = from.mRepeatCount;
- mDownTime = from.mDownTime;
- mEventTime = from.mEventTime;
- }
- // --- PointerCoords ---
- float PointerCoords::getAxisValue(int32_t axis) const {
- if (axis < 0 || axis > 63 || !BitSet64::hasBit(bits, axis)){
- return 0;
- }
- return values[BitSet64::getIndexOfBit(bits, axis)];
- }
- status_t PointerCoords::setAxisValue(int32_t axis, float value) {
- if (axis < 0 || axis > 63) {
- return NAME_NOT_FOUND;
- }
- uint32_t index = BitSet64::getIndexOfBit(bits, axis);
- if (!BitSet64::hasBit(bits, axis)) {
- if (value == 0) {
- return OK; // axes with value 0 do not need to be stored
- }
- uint32_t count = BitSet64::count(bits);
- if (count >= MAX_AXES) {
- tooManyAxes(axis);
- return NO_MEMORY;
- }
- BitSet64::markBit(bits, axis);
- for (uint32_t i = count; i > index; i--) {
- values[i] = values[i - 1];
- }
- }
- values[index] = value;
- return OK;
- }
- static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) {
- float value = c.getAxisValue(axis);
- if (value != 0) {
- c.setAxisValue(axis, value * scaleFactor);
- }
- }
- void PointerCoords::scale(float scaleFactor) {
- // No need to scale pressure or size since they are normalized.
- // No need to scale orientation since it is meaningless to do so.
- scaleAxisValue(*this, AMOTION_EVENT_AXIS_X, scaleFactor);
- scaleAxisValue(*this, AMOTION_EVENT_AXIS_Y, scaleFactor);
- scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MAJOR, scaleFactor);
- scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MINOR, scaleFactor);
- scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MAJOR, scaleFactor);
- scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor);
- }
- void PointerCoords::applyOffset(float xOffset, float yOffset) {
- setAxisValue(AMOTION_EVENT_AXIS_X, getX() + xOffset);
- setAxisValue(AMOTION_EVENT_AXIS_Y, getY() + yOffset);
- }
- #ifdef HAVE_ANDROID_OS
- status_t PointerCoords::readFromParcel(Parcel* parcel) {
- bits = parcel->readInt64();
- uint32_t count = BitSet64::count(bits);
- if (count > MAX_AXES) {
- return BAD_VALUE;
- }
- for (uint32_t i = 0; i < count; i++) {
- values[i] = parcel->readFloat();
- }
- return OK;
- }
- status_t PointerCoords::writeToParcel(Parcel* parcel) const {
- parcel->writeInt64(bits);
- uint32_t count = BitSet64::count(bits);
- for (uint32_t i = 0; i < count; i++) {
- parcel->writeFloat(values[i]);
- }
- return OK;
- }
- #endif
- void PointerCoords::tooManyAxes(int axis) {
- ALOGW("Could not set value for axis %d because the PointerCoords structure is full and "
- "cannot contain more than %d axis values.", axis, int(MAX_AXES));
- }
- bool PointerCoords::operator==(const PointerCoords& other) const {
- if (bits != other.bits) {
- return false;
- }
- uint32_t count = BitSet64::count(bits);
- for (uint32_t i = 0; i < count; i++) {
- if (values[i] != other.values[i]) {
- return false;
- }
- }
- return true;
- }
- void PointerCoords::copyFrom(const PointerCoords& other) {
- bits = other.bits;
- uint32_t count = BitSet64::count(bits);
- for (uint32_t i = 0; i < count; i++) {
- values[i] = other.values[i];
- }
- }
- // --- PointerProperties ---
- bool PointerProperties::operator==(const PointerProperties& other) const {
- return id == other.id
- && toolType == other.toolType;
- }
- void PointerProperties::copyFrom(const PointerProperties& other) {
- id = other.id;
- toolType = other.toolType;
- }
- // --- MotionEvent ---
- void MotionEvent::initialize(
- int32_t deviceId,
- int32_t source,
- int32_t action,
- int32_t actionButton,
- int32_t flags,
- int32_t edgeFlags,
- int32_t metaState,
- int32_t buttonState,
- float xOffset,
- float yOffset,
- float xPrecision,
- float yPrecision,
- nsecs_t downTime,
- nsecs_t eventTime,
- size_t pointerCount,
- const PointerProperties* pointerProperties,
- const PointerCoords* pointerCoords) {
- InputEvent::initialize(deviceId, source);
- mAction = action;
- mActionButton = actionButton;
- mFlags = flags;
- mEdgeFlags = edgeFlags;
- mMetaState = metaState;
- mButtonState = buttonState;
- mXOffset = xOffset;
- mYOffset = yOffset;
- mXPrecision = xPrecision;
- mYPrecision = yPrecision;
- mDownTime = downTime;
- mPointerProperties.clear();
- mPointerProperties.appendArray(pointerProperties, pointerCount);
- mSampleEventTimes.clear();
- mSamplePointerCoords.clear();
- addSample(eventTime, pointerCoords);
- }
- void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
- InputEvent::initialize(other->mDeviceId, other->mSource);
- mAction = other->mAction;
- mActionButton = other->mActionButton;
- mFlags = other->mFlags;
- mEdgeFlags = other->mEdgeFlags;
- mMetaState = other->mMetaState;
- mButtonState = other->mButtonState;
- mXOffset = other->mXOffset;
- mYOffset = other->mYOffset;
- mXPrecision = other->mXPrecision;
- mYPrecision = other->mYPrecision;
- mDownTime = other->mDownTime;
- mPointerProperties = other->mPointerProperties;
- if (keepHistory) {
- mSampleEventTimes = other->mSampleEventTimes;
- mSamplePointerCoords = other->mSamplePointerCoords;
- } else {
- mSampleEventTimes.clear();
- mSampleEventTimes.push(other->getEventTime());
- mSamplePointerCoords.clear();
- size_t pointerCount = other->getPointerCount();
- size_t historySize = other->getHistorySize();
- mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array()
- + (historySize * pointerCount), pointerCount);
- }
- }
- void MotionEvent::addSample(
- int64_t eventTime,
- const PointerCoords* pointerCoords) {
- mSampleEventTimes.push(eventTime);
- mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
- }
- const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
- return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
- }
- float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
- return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
- }
- float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const {
- float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis);
- switch (axis) {
- case AMOTION_EVENT_AXIS_X:
- return value + mXOffset;
- case AMOTION_EVENT_AXIS_Y:
- return value + mYOffset;
- }
- return value;
- }
- const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
- size_t pointerIndex, size_t historicalIndex) const {
- return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
- }
- float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
- size_t historicalIndex) const {
- return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
- }
- float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
- size_t historicalIndex) const {
- float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
- switch (axis) {
- case AMOTION_EVENT_AXIS_X:
- return value + mXOffset;
- case AMOTION_EVENT_AXIS_Y:
- return value + mYOffset;
- }
- return value;
- }
- ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
- size_t pointerCount = mPointerProperties.size();
- for (size_t i = 0; i < pointerCount; i++) {
- if (mPointerProperties.itemAt(i).id == pointerId) {
- return i;
- }
- }
- return -1;
- }
- void MotionEvent::offsetLocation(float xOffset, float yOffset) {
- mXOffset += xOffset;
- mYOffset += yOffset;
- }
- void MotionEvent::scale(float scaleFactor) {
- mXOffset *= scaleFactor;
- mYOffset *= scaleFactor;
- mXPrecision *= scaleFactor;
- mYPrecision *= scaleFactor;
- size_t numSamples = mSamplePointerCoords.size();
- for (size_t i = 0; i < numSamples; i++) {
- mSamplePointerCoords.editItemAt(i).scale(scaleFactor);
- }
- }
- static void transformPoint(const float matrix[9], float x, float y, float *outX, float *outY) {
- // Apply perspective transform like Skia.
- float newX = matrix[0] * x + matrix[1] * y + matrix[2];
- float newY = matrix[3] * x + matrix[4] * y + matrix[5];
- float newZ = matrix[6] * x + matrix[7] * y + matrix[8];
- if (newZ) {
- newZ = 1.0f / newZ;
- }
- *outX = newX * newZ;
- *outY = newY * newZ;
- }
- static float transformAngle(const float matrix[9], float angleRadians,
- float originX, float originY) {
- // Construct and transform a vector oriented at the specified clockwise angle from vertical.
- // Coordinate system: down is increasing Y, right is increasing X.
- float x = sinf(angleRadians);
- float y = -cosf(angleRadians);
- transformPoint(matrix, x, y, &x, &y);
- x -= originX;
- y -= originY;
- // Derive the transformed vector's clockwise angle from vertical.
- float result = atan2f(x, -y);
- if (result < - M_PI_2) {
- result += M_PI;
- } else if (result > M_PI_2) {
- result -= M_PI;
- }
- return result;
- }
- void MotionEvent::transform(const float matrix[9]) {
- // The tricky part of this implementation is to preserve the value of
- // rawX and rawY. So we apply the transformation to the first point
- // then derive an appropriate new X/Y offset that will preserve rawX
- // and rawY for that point.
- float oldXOffset = mXOffset;
- float oldYOffset = mYOffset;
- float newX, newY;
- float rawX = getRawX(0);
- float rawY = getRawY(0);
- transformPoint(matrix, rawX + oldXOffset, rawY + oldYOffset, &newX, &newY);
- mXOffset = newX - rawX;
- mYOffset = newY - rawY;
- // Determine how the origin is transformed by the matrix so that we
- // can transform orientation vectors.
- float originX, originY;
- transformPoint(matrix, 0, 0, &originX, &originY);
- // Apply the transformation to all samples.
- size_t numSamples = mSamplePointerCoords.size();
- for (size_t i = 0; i < numSamples; i++) {
- PointerCoords& c = mSamplePointerCoords.editItemAt(i);
- float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset;
- float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset;
- transformPoint(matrix, x, y, &x, &y);
- c.setAxisValue(AMOTION_EVENT_AXIS_X, x - mXOffset);
- c.setAxisValue(AMOTION_EVENT_AXIS_Y, y - mYOffset);
- float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
- c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
- transformAngle(matrix, orientation, originX, originY));
- }
- }
- #ifdef HAVE_ANDROID_OS
- status_t MotionEvent::readFromParcel(Parcel* parcel) {
- size_t pointerCount = parcel->readInt32();
- size_t sampleCount = parcel->readInt32();
- if (pointerCount == 0 || pointerCount > MAX_POINTERS ||
- sampleCount == 0 || sampleCount > MAX_SAMPLES) {
- return BAD_VALUE;
- }
- mDeviceId = parcel->readInt32();
- mSource = parcel->readInt32();
- mAction = parcel->readInt32();
- mActionButton = parcel->readInt32();
- mFlags = parcel->readInt32();
- mEdgeFlags = parcel->readInt32();
- mMetaState = parcel->readInt32();
- mButtonState = parcel->readInt32();
- mXOffset = parcel->readFloat();
- mYOffset = parcel->readFloat();
- mXPrecision = parcel->readFloat();
- mYPrecision = parcel->readFloat();
- mDownTime = parcel->readInt64();
- mPointerProperties.clear();
- mPointerProperties.setCapacity(pointerCount);
- mSampleEventTimes.clear();
- mSampleEventTimes.setCapacity(sampleCount);
- mSamplePointerCoords.clear();
- mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
- for (size_t i = 0; i < pointerCount; i++) {
- mPointerProperties.push();
- PointerProperties& properties = mPointerProperties.editTop();
- properties.id = parcel->readInt32();
- properties.toolType = parcel->readInt32();
- }
- while (sampleCount-- > 0) {
- mSampleEventTimes.push(parcel->readInt64());
- for (size_t i = 0; i < pointerCount; i++) {
- mSamplePointerCoords.push();
- status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel);
- if (status) {
- return status;
- }
- }
- }
- return OK;
- }
- status_t MotionEvent::writeToParcel(Parcel* parcel) const {
- size_t pointerCount = mPointerProperties.size();
- size_t sampleCount = mSampleEventTimes.size();
- parcel->writeInt32(pointerCount);
- parcel->writeInt32(sampleCount);
- parcel->writeInt32(mDeviceId);
- parcel->writeInt32(mSource);
- parcel->writeInt32(mAction);
- parcel->writeInt32(mActionButton);
- parcel->writeInt32(mFlags);
- parcel->writeInt32(mEdgeFlags);
- parcel->writeInt32(mMetaState);
- parcel->writeInt32(mButtonState);
- parcel->writeFloat(mXOffset);
- parcel->writeFloat(mYOffset);
- parcel->writeFloat(mXPrecision);
- parcel->writeFloat(mYPrecision);
- parcel->writeInt64(mDownTime);
- for (size_t i = 0; i < pointerCount; i++) {
- const PointerProperties& properties = mPointerProperties.itemAt(i);
- parcel->writeInt32(properties.id);
- parcel->writeInt32(properties.toolType);
- }
- const PointerCoords* pc = mSamplePointerCoords.array();
- for (size_t h = 0; h < sampleCount; h++) {
- parcel->writeInt64(mSampleEventTimes.itemAt(h));
- for (size_t i = 0; i < pointerCount; i++) {
- status_t status = (pc++)->writeToParcel(parcel);
- if (status) {
- return status;
- }
- }
- }
- return OK;
- }
- #endif
- bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
- if (source & AINPUT_SOURCE_CLASS_POINTER) {
- // Specifically excludes HOVER_MOVE and SCROLL.
- switch (action & AMOTION_EVENT_ACTION_MASK) {
- case AMOTION_EVENT_ACTION_DOWN:
- case AMOTION_EVENT_ACTION_MOVE:
- case AMOTION_EVENT_ACTION_UP:
- case AMOTION_EVENT_ACTION_POINTER_DOWN:
- case AMOTION_EVENT_ACTION_POINTER_UP:
- case AMOTION_EVENT_ACTION_CANCEL:
- case AMOTION_EVENT_ACTION_OUTSIDE:
- return true;
- }
- }
- return false;
- }
- const char* MotionEvent::getLabel(int32_t axis) {
- return getAxisLabel(axis);
- }
- int32_t MotionEvent::getAxisFromLabel(const char* label) {
- return getAxisByLabel(label);
- }
- // --- PooledInputEventFactory ---
- PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) :
- mMaxPoolSize(maxPoolSize) {
- }
- PooledInputEventFactory::~PooledInputEventFactory() {
- for (size_t i = 0; i < mKeyEventPool.size(); i++) {
- delete mKeyEventPool.itemAt(i);
- }
- for (size_t i = 0; i < mMotionEventPool.size(); i++) {
- delete mMotionEventPool.itemAt(i);
- }
- }
- KeyEvent* PooledInputEventFactory::createKeyEvent() {
- if (!mKeyEventPool.isEmpty()) {
- KeyEvent* event = mKeyEventPool.top();
- mKeyEventPool.pop();
- return event;
- }
- return new KeyEvent();
- }
- MotionEvent* PooledInputEventFactory::createMotionEvent() {
- if (!mMotionEventPool.isEmpty()) {
- MotionEvent* event = mMotionEventPool.top();
- mMotionEventPool.pop();
- return event;
- }
- return new MotionEvent();
- }
- void PooledInputEventFactory::recycle(InputEvent* event) {
- switch (event->getType()) {
- case AINPUT_EVENT_TYPE_KEY:
- if (mKeyEventPool.size() < mMaxPoolSize) {
- mKeyEventPool.push(static_cast<KeyEvent*>(event));
- return;
- }
- break;
- case AINPUT_EVENT_TYPE_MOTION:
- if (mMotionEventPool.size() < mMaxPoolSize) {
- mMotionEventPool.push(static_cast<MotionEvent*>(event));
- return;
- }
- break;
- }
- delete event;
- }
- } // namespace android
|