• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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 __ANDROID__
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 __ANDROID__
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 ||
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 
writeToParcel(Parcel * parcel) const474 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 
isTouchEvent(int32_t source,int32_t action)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 
getLabel(int32_t axis)532 const char* MotionEvent::getLabel(int32_t axis) {
533     return getAxisLabel(axis);
534 }
535 
getAxisFromLabel(const char * label)536 int32_t MotionEvent::getAxisFromLabel(const char* label) {
537     return getAxisByLabel(label);
538 }
539 
540 
541 // --- PooledInputEventFactory ---
542 
PooledInputEventFactory(size_t maxPoolSize)543 PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) :
544         mMaxPoolSize(maxPoolSize) {
545 }
546 
~PooledInputEventFactory()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 
createKeyEvent()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 
createMotionEvent()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 
recycle(InputEvent * event)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