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 HAVE_ANDROID_OS
27 #include <binder/Parcel.h>
28 #endif
29
30 namespace android {
31
32 // --- InputEvent ---
33
initialize(int32_t deviceId,int32_t source)34 void InputEvent::initialize(int32_t deviceId, int32_t source) {
35 mDeviceId = deviceId;
36 mSource = source;
37 }
38
initialize(const InputEvent & from)39 void InputEvent::initialize(const InputEvent& from) {
40 mDeviceId = from.mDeviceId;
41 mSource = from.mSource;
42 }
43
44 // --- KeyEvent ---
45
getLabel(int32_t keyCode)46 const char* KeyEvent::getLabel(int32_t keyCode) {
47 return getLabelByKeyCode(keyCode);
48 }
49
getKeyCodeFromLabel(const char * label)50 int32_t KeyEvent::getKeyCodeFromLabel(const char* label) {
51 return getKeyCodeByLabel(label);
52 }
53
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)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
initialize(const KeyEvent & from)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
getAxisValue(int32_t axis) const91 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
setAxisValue(int32_t axis,float value)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
scaleAxisValue(PointerCoords & c,int axis,float scaleFactor)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
scale(float 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);
140 }
141
applyOffset(float xOffset,float yOffset)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 HAVE_ANDROID_OS
readFromParcel(Parcel * parcel)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
writeToParcel(Parcel * parcel) const162 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
tooManyAxes(int axis)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
operator ==(const PointerCoords & other) const178 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
copyFrom(const PointerCoords & other)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
operator ==(const PointerProperties & other) const202 bool PointerProperties::operator==(const PointerProperties& other) const {
203 return id == other.id
204 && toolType == other.toolType;
205 }
206
copyFrom(const PointerProperties & other)207 void PointerProperties::copyFrom(const PointerProperties& other) {
208 id = other.id;
209 toolType = other.toolType;
210 }
211
212
213 // --- MotionEvent ---
214
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)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
copyFrom(const MotionEvent * other,bool keepHistory)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
addSample(int64_t eventTime,const PointerCoords * pointerCoords)281 void MotionEvent::addSample(
282 int64_t eventTime,
283 const PointerCoords* pointerCoords) {
284 mSampleEventTimes.push(eventTime);
285 mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
286 }
287
getRawPointerCoords(size_t pointerIndex) const288 const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
289 return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
290 }
291
getRawAxisValue(int32_t axis,size_t pointerIndex) const292 float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
293 return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
294 }
295
getAxisValue(int32_t axis,size_t pointerIndex) const296 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
getHistoricalRawPointerCoords(size_t pointerIndex,size_t historicalIndex) const307 const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
308 size_t pointerIndex, size_t historicalIndex) const {
309 return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
310 }
311
getHistoricalRawAxisValue(int32_t axis,size_t pointerIndex,size_t historicalIndex) const312 float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
313 size_t historicalIndex) const {
314 return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
315 }
316
getHistoricalAxisValue(int32_t axis,size_t pointerIndex,size_t historicalIndex) const317 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
findPointerIndex(int32_t pointerId) const329 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
offsetLocation(float xOffset,float yOffset)339 void MotionEvent::offsetLocation(float xOffset, float yOffset) {
340 mXOffset += xOffset;
341 mYOffset += yOffset;
342 }
343
scale(float scaleFactor)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
transformPoint(const float matrix[9],float x,float y,float * outX,float * outY)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
transformAngle(const float matrix[9],float angleRadians,float originX,float originY)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
transform(const float matrix[9])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 HAVE_ANDROID_OS
readFromParcel(Parcel * parcel)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) {
428 return BAD_VALUE;
429 }
430
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();
444
445 mPointerProperties.clear();
446 mPointerProperties.setCapacity(pointerCount);
447 mSampleEventTimes.clear();
448 mSampleEventTimes.setCapacity(sampleCount);
449 mSamplePointerCoords.clear();
450 mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
451
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();
457 }
458
459 while (sampleCount-- > 0) {
460 mSampleEventTimes.push(parcel->readInt64());
461 for (size_t i = 0; i < pointerCount; i++) {
462 mSamplePointerCoords.push();
463 status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel);
464 if (status) {
465 return status;
466 }
467 }
468 }
469 return OK;
470 }
471
writeToParcel(Parcel * parcel) const472 status_t MotionEvent::writeToParcel(Parcel* parcel) const {
473 size_t pointerCount = mPointerProperties.size();
474 size_t sampleCount = mSampleEventTimes.size();
475
476 parcel->writeInt32(pointerCount);
477 parcel->writeInt32(sampleCount);
478
479 parcel->writeInt32(mDeviceId);
480 parcel->writeInt32(mSource);
481 parcel->writeInt32(mAction);
482 parcel->writeInt32(mActionButton);
483 parcel->writeInt32(mFlags);
484 parcel->writeInt32(mEdgeFlags);
485 parcel->writeInt32(mMetaState);
486 parcel->writeInt32(mButtonState);
487 parcel->writeFloat(mXOffset);
488 parcel->writeFloat(mYOffset);
489 parcel->writeFloat(mXPrecision);
490 parcel->writeFloat(mYPrecision);
491 parcel->writeInt64(mDownTime);
492
493 for (size_t i = 0; i < pointerCount; i++) {
494 const PointerProperties& properties = mPointerProperties.itemAt(i);
495 parcel->writeInt32(properties.id);
496 parcel->writeInt32(properties.toolType);
497 }
498
499 const PointerCoords* pc = mSamplePointerCoords.array();
500 for (size_t h = 0; h < sampleCount; h++) {
501 parcel->writeInt64(mSampleEventTimes.itemAt(h));
502 for (size_t i = 0; i < pointerCount; i++) {
503 status_t status = (pc++)->writeToParcel(parcel);
504 if (status) {
505 return status;
506 }
507 }
508 }
509 return OK;
510 }
511 #endif
512
isTouchEvent(int32_t source,int32_t action)513 bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
514 if (source & AINPUT_SOURCE_CLASS_POINTER) {
515 // Specifically excludes HOVER_MOVE and SCROLL.
516 switch (action & AMOTION_EVENT_ACTION_MASK) {
517 case AMOTION_EVENT_ACTION_DOWN:
518 case AMOTION_EVENT_ACTION_MOVE:
519 case AMOTION_EVENT_ACTION_UP:
520 case AMOTION_EVENT_ACTION_POINTER_DOWN:
521 case AMOTION_EVENT_ACTION_POINTER_UP:
522 case AMOTION_EVENT_ACTION_CANCEL:
523 case AMOTION_EVENT_ACTION_OUTSIDE:
524 return true;
525 }
526 }
527 return false;
528 }
529
getLabel(int32_t axis)530 const char* MotionEvent::getLabel(int32_t axis) {
531 return getAxisLabel(axis);
532 }
533
getAxisFromLabel(const char * label)534 int32_t MotionEvent::getAxisFromLabel(const char* label) {
535 return getAxisByLabel(label);
536 }
537
538
539 // --- PooledInputEventFactory ---
540
PooledInputEventFactory(size_t maxPoolSize)541 PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) :
542 mMaxPoolSize(maxPoolSize) {
543 }
544
~PooledInputEventFactory()545 PooledInputEventFactory::~PooledInputEventFactory() {
546 for (size_t i = 0; i < mKeyEventPool.size(); i++) {
547 delete mKeyEventPool.itemAt(i);
548 }
549 for (size_t i = 0; i < mMotionEventPool.size(); i++) {
550 delete mMotionEventPool.itemAt(i);
551 }
552 }
553
createKeyEvent()554 KeyEvent* PooledInputEventFactory::createKeyEvent() {
555 if (!mKeyEventPool.isEmpty()) {
556 KeyEvent* event = mKeyEventPool.top();
557 mKeyEventPool.pop();
558 return event;
559 }
560 return new KeyEvent();
561 }
562
createMotionEvent()563 MotionEvent* PooledInputEventFactory::createMotionEvent() {
564 if (!mMotionEventPool.isEmpty()) {
565 MotionEvent* event = mMotionEventPool.top();
566 mMotionEventPool.pop();
567 return event;
568 }
569 return new MotionEvent();
570 }
571
recycle(InputEvent * event)572 void PooledInputEventFactory::recycle(InputEvent* event) {
573 switch (event->getType()) {
574 case AINPUT_EVENT_TYPE_KEY:
575 if (mKeyEventPool.size() < mMaxPoolSize) {
576 mKeyEventPool.push(static_cast<KeyEvent*>(event));
577 return;
578 }
579 break;
580 case AINPUT_EVENT_TYPE_MOTION:
581 if (mMotionEventPool.size() < mMaxPoolSize) {
582 mMotionEventPool.push(static_cast<MotionEvent*>(event));
583 return;
584 }
585 break;
586 }
587 delete event;
588 }
589
590 } // namespace android
591