2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "Input"
18 //#define LOG_NDEBUG 0
23 #include <input/Input.h>
24 #include <input/InputEventLabels.h>
27 #include <binder/Parcel.h>
34 void InputEvent::initialize(int32_t deviceId, int32_t source) {
39 void InputEvent::initialize(const InputEvent& from) {
40 mDeviceId = from.mDeviceId;
41 mSource = from.mSource;
46 const char* KeyEvent::getLabel(int32_t keyCode) {
47 return getLabelByKeyCode(keyCode);
50 int32_t KeyEvent::getKeyCodeFromLabel(const char* label) {
51 return getKeyCodeByLabel(label);
54 void KeyEvent::initialize(
65 InputEvent::initialize(deviceId, source);
70 mMetaState = metaState;
71 mRepeatCount = repeatCount;
73 mEventTime = eventTime;
76 void KeyEvent::initialize(const KeyEvent& from) {
77 InputEvent::initialize(from);
78 mAction = from.mAction;
80 mKeyCode = from.mKeyCode;
81 mScanCode = from.mScanCode;
82 mMetaState = from.mMetaState;
83 mRepeatCount = from.mRepeatCount;
84 mDownTime = from.mDownTime;
85 mEventTime = from.mEventTime;
89 // --- PointerCoords ---
91 float PointerCoords::getAxisValue(int32_t axis) const {
92 if (axis < 0 || axis > 63 || !BitSet64::hasBit(bits, axis)){
95 return values[BitSet64::getIndexOfBit(bits, axis)];
98 status_t PointerCoords::setAxisValue(int32_t axis, float value) {
99 if (axis < 0 || axis > 63) {
100 return NAME_NOT_FOUND;
103 uint32_t index = BitSet64::getIndexOfBit(bits, axis);
104 if (!BitSet64::hasBit(bits, axis)) {
106 return OK; // axes with value 0 do not need to be stored
109 uint32_t count = BitSet64::count(bits);
110 if (count >= MAX_AXES) {
114 BitSet64::markBit(bits, axis);
115 for (uint32_t i = count; i > index; i--) {
116 values[i] = values[i - 1];
120 values[index] = value;
124 static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) {
125 float value = c.getAxisValue(axis);
127 c.setAxisValue(axis, value * scaleFactor);
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);
142 void PointerCoords::applyOffset(float xOffset, float yOffset) {
143 setAxisValue(AMOTION_EVENT_AXIS_X, getX() + xOffset);
144 setAxisValue(AMOTION_EVENT_AXIS_Y, getY() + yOffset);
148 status_t PointerCoords::readFromParcel(Parcel* parcel) {
149 bits = parcel->readInt64();
151 uint32_t count = BitSet64::count(bits);
152 if (count > MAX_AXES) {
156 for (uint32_t i = 0; i < count; i++) {
157 values[i] = parcel->readFloat();
162 status_t PointerCoords::writeToParcel(Parcel* parcel) const {
163 parcel->writeInt64(bits);
165 uint32_t count = BitSet64::count(bits);
166 for (uint32_t i = 0; i < count; i++) {
167 parcel->writeFloat(values[i]);
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));
178 bool PointerCoords::operator==(const PointerCoords& other) const {
179 if (bits != other.bits) {
182 uint32_t count = BitSet64::count(bits);
183 for (uint32_t i = 0; i < count; i++) {
184 if (values[i] != other.values[i]) {
191 void PointerCoords::copyFrom(const PointerCoords& other) {
193 uint32_t count = BitSet64::count(bits);
194 for (uint32_t i = 0; i < count; i++) {
195 values[i] = other.values[i];
200 // --- PointerProperties ---
202 bool PointerProperties::operator==(const PointerProperties& other) const {
203 return id == other.id
204 && toolType == other.toolType;
207 void PointerProperties::copyFrom(const PointerProperties& other) {
209 toolType = other.toolType;
213 // --- MotionEvent ---
215 void MotionEvent::initialize(
219 int32_t actionButton,
231 const PointerProperties* pointerProperties,
232 const PointerCoords* pointerCoords) {
233 InputEvent::initialize(deviceId, source);
235 mActionButton = actionButton;
237 mEdgeFlags = edgeFlags;
238 mMetaState = metaState;
239 mButtonState = buttonState;
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);
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;
268 mSampleEventTimes = other->mSampleEventTimes;
269 mSamplePointerCoords = other->mSamplePointerCoords;
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);
281 void MotionEvent::addSample(
283 const PointerCoords* pointerCoords) {
284 mSampleEventTimes.push(eventTime);
285 mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
288 const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
289 return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
292 float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
293 return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
296 float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const {
297 float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis);
299 case AMOTION_EVENT_AXIS_X:
300 return value + mXOffset;
301 case AMOTION_EVENT_AXIS_Y:
302 return value + mYOffset;
307 const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
308 size_t pointerIndex, size_t historicalIndex) const {
309 return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
312 float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
313 size_t historicalIndex) const {
314 return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
317 float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
318 size_t historicalIndex) const {
319 float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
321 case AMOTION_EVENT_AXIS_X:
322 return value + mXOffset;
323 case AMOTION_EVENT_AXIS_Y:
324 return value + mYOffset;
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) {
339 void MotionEvent::offsetLocation(float xOffset, float yOffset) {
344 void MotionEvent::scale(float scaleFactor) {
345 mXOffset *= scaleFactor;
346 mYOffset *= scaleFactor;
347 mXPrecision *= scaleFactor;
348 mYPrecision *= scaleFactor;
350 size_t numSamples = mSamplePointerCoords.size();
351 for (size_t i = 0; i < numSamples; i++) {
352 mSamplePointerCoords.editItemAt(i).scale(scaleFactor);
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];
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);
378 // Derive the transformed vector's clockwise angle from vertical.
379 float result = atan2f(x, -y);
380 if (result < - M_PI_2) {
382 } else if (result > M_PI_2) {
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;
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;
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);
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);
417 float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
418 c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
419 transformAngle(matrix, orientation, originX, originY));
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 || sampleCount == 0) {
431 mDeviceId = parcel->readInt32();
432 mSource = parcel->readInt32();
433 mAction = parcel->readInt32();
434 mActionButton = parcel->readInt32();
435 mFlags = parcel->readInt32();
436 mEdgeFlags = parcel->readInt32();
437 mMetaState = parcel->readInt32();
438 mButtonState = parcel->readInt32();
439 mXOffset = parcel->readFloat();
440 mYOffset = parcel->readFloat();
441 mXPrecision = parcel->readFloat();
442 mYPrecision = parcel->readFloat();
443 mDownTime = parcel->readInt64();
445 mPointerProperties.clear();
446 mPointerProperties.setCapacity(pointerCount);
447 mSampleEventTimes.clear();
448 mSampleEventTimes.setCapacity(sampleCount);
449 mSamplePointerCoords.clear();
450 mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
452 for (size_t i = 0; i < pointerCount; i++) {
453 mPointerProperties.push();
454 PointerProperties& properties = mPointerProperties.editTop();
455 properties.id = parcel->readInt32();
456 properties.toolType = parcel->readInt32();
459 while (sampleCount > 0) {
461 mSampleEventTimes.push(parcel->readInt64());
462 for (size_t i = 0; i < pointerCount; i++) {
463 mSamplePointerCoords.push();
464 status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel);
473 status_t MotionEvent::writeToParcel(Parcel* parcel) const {
474 size_t pointerCount = mPointerProperties.size();
475 size_t sampleCount = mSampleEventTimes.size();
477 parcel->writeInt32(pointerCount);
478 parcel->writeInt32(sampleCount);
480 parcel->writeInt32(mDeviceId);
481 parcel->writeInt32(mSource);
482 parcel->writeInt32(mAction);
483 parcel->writeInt32(mActionButton);
484 parcel->writeInt32(mFlags);
485 parcel->writeInt32(mEdgeFlags);
486 parcel->writeInt32(mMetaState);
487 parcel->writeInt32(mButtonState);
488 parcel->writeFloat(mXOffset);
489 parcel->writeFloat(mYOffset);
490 parcel->writeFloat(mXPrecision);
491 parcel->writeFloat(mYPrecision);
492 parcel->writeInt64(mDownTime);
494 for (size_t i = 0; i < pointerCount; i++) {
495 const PointerProperties& properties = mPointerProperties.itemAt(i);
496 parcel->writeInt32(properties.id);
497 parcel->writeInt32(properties.toolType);
500 const PointerCoords* pc = mSamplePointerCoords.array();
501 for (size_t h = 0; h < sampleCount; h++) {
502 parcel->writeInt64(mSampleEventTimes.itemAt(h));
503 for (size_t i = 0; i < pointerCount; i++) {
504 status_t status = (pc++)->writeToParcel(parcel);
514 bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
515 if (source & AINPUT_SOURCE_CLASS_POINTER) {
516 // Specifically excludes HOVER_MOVE and SCROLL.
517 switch (action & AMOTION_EVENT_ACTION_MASK) {
518 case AMOTION_EVENT_ACTION_DOWN:
519 case AMOTION_EVENT_ACTION_MOVE:
520 case AMOTION_EVENT_ACTION_UP:
521 case AMOTION_EVENT_ACTION_POINTER_DOWN:
522 case AMOTION_EVENT_ACTION_POINTER_UP:
523 case AMOTION_EVENT_ACTION_CANCEL:
524 case AMOTION_EVENT_ACTION_OUTSIDE:
531 const char* MotionEvent::getLabel(int32_t axis) {
532 return getAxisLabel(axis);
535 int32_t MotionEvent::getAxisFromLabel(const char* label) {
536 return getAxisByLabel(label);
540 // --- PooledInputEventFactory ---
542 PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) :
543 mMaxPoolSize(maxPoolSize) {
546 PooledInputEventFactory::~PooledInputEventFactory() {
547 for (size_t i = 0; i < mKeyEventPool.size(); i++) {
548 delete mKeyEventPool.itemAt(i);
550 for (size_t i = 0; i < mMotionEventPool.size(); i++) {
551 delete mMotionEventPool.itemAt(i);
555 KeyEvent* PooledInputEventFactory::createKeyEvent() {
556 if (!mKeyEventPool.isEmpty()) {
557 KeyEvent* event = mKeyEventPool.top();
561 return new KeyEvent();
564 MotionEvent* PooledInputEventFactory::createMotionEvent() {
565 if (!mMotionEventPool.isEmpty()) {
566 MotionEvent* event = mMotionEventPool.top();
567 mMotionEventPool.pop();
570 return new MotionEvent();
573 void PooledInputEventFactory::recycle(InputEvent* event) {
574 switch (event->getType()) {
575 case AINPUT_EVENT_TYPE_KEY:
576 if (mKeyEventPool.size() < mMaxPoolSize) {
577 mKeyEventPool.push(static_cast<KeyEvent*>(event));
581 case AINPUT_EVENT_TYPE_MOTION:
582 if (mMotionEventPool.size() < mMaxPoolSize) {
583 mMotionEventPool.push(static_cast<MotionEvent*>(event));
591 } // namespace android