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
30namespace android {
31
32// --- InputEvent ---
33
34void InputEvent::initialize(int32_t deviceId, int32_t source) {
35    mDeviceId = deviceId;
36    mSource = source;
37}
38
39void InputEvent::initialize(const InputEvent& from) {
40    mDeviceId = from.mDeviceId;
41    mSource = from.mSource;
42}
43
44// --- KeyEvent ---
45
46const char* KeyEvent::getLabel(int32_t keyCode) {
47    return getLabelByKeyCode(keyCode);
48}
49
50int32_t KeyEvent::getKeyCodeFromLabel(const char* label) {
51    return getKeyCodeByLabel(label);
52}
53
54void 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
76void 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
91float 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
98status_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
124static 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
131void 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
142void 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__
148status_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
162status_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
173void 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
178bool 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
191void 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
202bool PointerProperties::operator==(const PointerProperties& other) const {
203    return id == other.id
204            && toolType == other.toolType;
205}
206
207void PointerProperties::copyFrom(const PointerProperties& other) {
208    id = other.id;
209    toolType = other.toolType;
210}
211
212
213// --- MotionEvent ---
214
215void 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
252void 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
281void MotionEvent::addSample(
282        int64_t eventTime,
283        const PointerCoords* pointerCoords) {
284    mSampleEventTimes.push(eventTime);
285    mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
286}
287
288const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
289    return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
290}
291
292float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
293    return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
294}
295
296float 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
307const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
308        size_t pointerIndex, size_t historicalIndex) const {
309    return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
310}
311
312float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
313        size_t historicalIndex) const {
314    return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
315}
316
317float 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
329ssize_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
339void MotionEvent::offsetLocation(float xOffset, float yOffset) {
340    mXOffset += xOffset;
341    mYOffset += yOffset;
342}
343
344void 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
356static 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
368static 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
388void 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__
424status_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
474status_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
515bool 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
532const char* MotionEvent::getLabel(int32_t axis) {
533    return getAxisLabel(axis);
534}
535
536int32_t MotionEvent::getAxisFromLabel(const char* label) {
537    return getAxisByLabel(label);
538}
539
540
541// --- PooledInputEventFactory ---
542
543PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) :
544        mMaxPoolSize(maxPoolSize) {
545}
546
547PooledInputEventFactory::~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
556KeyEvent* PooledInputEventFactory::createKeyEvent() {
557    if (!mKeyEventPool.isEmpty()) {
558        KeyEvent* event = mKeyEventPool.top();
559        mKeyEventPool.pop();
560        return event;
561    }
562    return new KeyEvent();
563}
564
565MotionEvent* PooledInputEventFactory::createMotionEvent() {
566    if (!mMotionEventPool.isEmpty()) {
567        MotionEvent* event = mMotionEventPool.top();
568        mMotionEventPool.pop();
569        return event;
570    }
571    return new MotionEvent();
572}
573
574void 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