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
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 HAVE_ANDROID_OS
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 flags,
220        int32_t edgeFlags,
221        int32_t metaState,
222        int32_t buttonState,
223        float xOffset,
224        float yOffset,
225        float xPrecision,
226        float yPrecision,
227        nsecs_t downTime,
228        nsecs_t eventTime,
229        size_t pointerCount,
230        const PointerProperties* pointerProperties,
231        const PointerCoords* pointerCoords) {
232    InputEvent::initialize(deviceId, source);
233    mAction = action;
234    mFlags = flags;
235    mEdgeFlags = edgeFlags;
236    mMetaState = metaState;
237    mButtonState = buttonState;
238    mXOffset = xOffset;
239    mYOffset = yOffset;
240    mXPrecision = xPrecision;
241    mYPrecision = yPrecision;
242    mDownTime = downTime;
243    mPointerProperties.clear();
244    mPointerProperties.appendArray(pointerProperties, pointerCount);
245    mSampleEventTimes.clear();
246    mSamplePointerCoords.clear();
247    addSample(eventTime, pointerCoords);
248}
249
250void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
251    InputEvent::initialize(other->mDeviceId, other->mSource);
252    mAction = other->mAction;
253    mFlags = other->mFlags;
254    mEdgeFlags = other->mEdgeFlags;
255    mMetaState = other->mMetaState;
256    mButtonState = other->mButtonState;
257    mXOffset = other->mXOffset;
258    mYOffset = other->mYOffset;
259    mXPrecision = other->mXPrecision;
260    mYPrecision = other->mYPrecision;
261    mDownTime = other->mDownTime;
262    mPointerProperties = other->mPointerProperties;
263
264    if (keepHistory) {
265        mSampleEventTimes = other->mSampleEventTimes;
266        mSamplePointerCoords = other->mSamplePointerCoords;
267    } else {
268        mSampleEventTimes.clear();
269        mSampleEventTimes.push(other->getEventTime());
270        mSamplePointerCoords.clear();
271        size_t pointerCount = other->getPointerCount();
272        size_t historySize = other->getHistorySize();
273        mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array()
274                + (historySize * pointerCount), pointerCount);
275    }
276}
277
278void MotionEvent::addSample(
279        int64_t eventTime,
280        const PointerCoords* pointerCoords) {
281    mSampleEventTimes.push(eventTime);
282    mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
283}
284
285const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
286    return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
287}
288
289float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
290    return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
291}
292
293float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const {
294    float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis);
295    switch (axis) {
296    case AMOTION_EVENT_AXIS_X:
297        return value + mXOffset;
298    case AMOTION_EVENT_AXIS_Y:
299        return value + mYOffset;
300    }
301    return value;
302}
303
304const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
305        size_t pointerIndex, size_t historicalIndex) const {
306    return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
307}
308
309float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
310        size_t historicalIndex) const {
311    return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
312}
313
314float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
315        size_t historicalIndex) const {
316    float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
317    switch (axis) {
318    case AMOTION_EVENT_AXIS_X:
319        return value + mXOffset;
320    case AMOTION_EVENT_AXIS_Y:
321        return value + mYOffset;
322    }
323    return value;
324}
325
326ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
327    size_t pointerCount = mPointerProperties.size();
328    for (size_t i = 0; i < pointerCount; i++) {
329        if (mPointerProperties.itemAt(i).id == pointerId) {
330            return i;
331        }
332    }
333    return -1;
334}
335
336void MotionEvent::offsetLocation(float xOffset, float yOffset) {
337    mXOffset += xOffset;
338    mYOffset += yOffset;
339}
340
341void MotionEvent::scale(float scaleFactor) {
342    mXOffset *= scaleFactor;
343    mYOffset *= scaleFactor;
344    mXPrecision *= scaleFactor;
345    mYPrecision *= scaleFactor;
346
347    size_t numSamples = mSamplePointerCoords.size();
348    for (size_t i = 0; i < numSamples; i++) {
349        mSamplePointerCoords.editItemAt(i).scale(scaleFactor);
350    }
351}
352
353static void transformPoint(const float matrix[9], float x, float y, float *outX, float *outY) {
354    // Apply perspective transform like Skia.
355    float newX = matrix[0] * x + matrix[1] * y + matrix[2];
356    float newY = matrix[3] * x + matrix[4] * y + matrix[5];
357    float newZ = matrix[6] * x + matrix[7] * y + matrix[8];
358    if (newZ) {
359        newZ = 1.0f / newZ;
360    }
361    *outX = newX * newZ;
362    *outY = newY * newZ;
363}
364
365static float transformAngle(const float matrix[9], float angleRadians,
366        float originX, float originY) {
367    // Construct and transform a vector oriented at the specified clockwise angle from vertical.
368    // Coordinate system: down is increasing Y, right is increasing X.
369    float x = sinf(angleRadians);
370    float y = -cosf(angleRadians);
371    transformPoint(matrix, x, y, &x, &y);
372    x -= originX;
373    y -= originY;
374
375    // Derive the transformed vector's clockwise angle from vertical.
376    float result = atan2f(x, -y);
377    if (result < - M_PI_2) {
378        result += M_PI;
379    } else if (result > M_PI_2) {
380        result -= M_PI;
381    }
382    return result;
383}
384
385void MotionEvent::transform(const float matrix[9]) {
386    // The tricky part of this implementation is to preserve the value of
387    // rawX and rawY.  So we apply the transformation to the first point
388    // then derive an appropriate new X/Y offset that will preserve rawX
389     // and rawY for that point.
390    float oldXOffset = mXOffset;
391    float oldYOffset = mYOffset;
392    float newX, newY;
393    float rawX = getRawX(0);
394    float rawY = getRawY(0);
395    transformPoint(matrix, rawX + oldXOffset, rawY + oldYOffset, &newX, &newY);
396    mXOffset = newX - rawX;
397    mYOffset = newY - rawY;
398
399    // Determine how the origin is transformed by the matrix so that we
400    // can transform orientation vectors.
401    float originX, originY;
402    transformPoint(matrix, 0, 0, &originX, &originY);
403
404    // Apply the transformation to all samples.
405    size_t numSamples = mSamplePointerCoords.size();
406    for (size_t i = 0; i < numSamples; i++) {
407        PointerCoords& c = mSamplePointerCoords.editItemAt(i);
408        float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset;
409        float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset;
410        transformPoint(matrix, x, y, &x, &y);
411        c.setAxisValue(AMOTION_EVENT_AXIS_X, x - mXOffset);
412        c.setAxisValue(AMOTION_EVENT_AXIS_Y, y - mYOffset);
413
414        float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
415        c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION,
416                transformAngle(matrix, orientation, originX, originY));
417    }
418}
419
420#ifdef HAVE_ANDROID_OS
421status_t MotionEvent::readFromParcel(Parcel* parcel) {
422    size_t pointerCount = parcel->readInt32();
423    size_t sampleCount = parcel->readInt32();
424    if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) {
425        return BAD_VALUE;
426    }
427
428    mDeviceId = parcel->readInt32();
429    mSource = parcel->readInt32();
430    mAction = parcel->readInt32();
431    mFlags = parcel->readInt32();
432    mEdgeFlags = parcel->readInt32();
433    mMetaState = parcel->readInt32();
434    mButtonState = parcel->readInt32();
435    mXOffset = parcel->readFloat();
436    mYOffset = parcel->readFloat();
437    mXPrecision = parcel->readFloat();
438    mYPrecision = parcel->readFloat();
439    mDownTime = parcel->readInt64();
440
441    mPointerProperties.clear();
442    mPointerProperties.setCapacity(pointerCount);
443    mSampleEventTimes.clear();
444    mSampleEventTimes.setCapacity(sampleCount);
445    mSamplePointerCoords.clear();
446    mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
447
448    for (size_t i = 0; i < pointerCount; i++) {
449        mPointerProperties.push();
450        PointerProperties& properties = mPointerProperties.editTop();
451        properties.id = parcel->readInt32();
452        properties.toolType = parcel->readInt32();
453    }
454
455    while (sampleCount-- > 0) {
456        mSampleEventTimes.push(parcel->readInt64());
457        for (size_t i = 0; i < pointerCount; i++) {
458            mSamplePointerCoords.push();
459            status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel);
460            if (status) {
461                return status;
462            }
463        }
464    }
465    return OK;
466}
467
468status_t MotionEvent::writeToParcel(Parcel* parcel) const {
469    size_t pointerCount = mPointerProperties.size();
470    size_t sampleCount = mSampleEventTimes.size();
471
472    parcel->writeInt32(pointerCount);
473    parcel->writeInt32(sampleCount);
474
475    parcel->writeInt32(mDeviceId);
476    parcel->writeInt32(mSource);
477    parcel->writeInt32(mAction);
478    parcel->writeInt32(mFlags);
479    parcel->writeInt32(mEdgeFlags);
480    parcel->writeInt32(mMetaState);
481    parcel->writeInt32(mButtonState);
482    parcel->writeFloat(mXOffset);
483    parcel->writeFloat(mYOffset);
484    parcel->writeFloat(mXPrecision);
485    parcel->writeFloat(mYPrecision);
486    parcel->writeInt64(mDownTime);
487
488    for (size_t i = 0; i < pointerCount; i++) {
489        const PointerProperties& properties = mPointerProperties.itemAt(i);
490        parcel->writeInt32(properties.id);
491        parcel->writeInt32(properties.toolType);
492    }
493
494    const PointerCoords* pc = mSamplePointerCoords.array();
495    for (size_t h = 0; h < sampleCount; h++) {
496        parcel->writeInt64(mSampleEventTimes.itemAt(h));
497        for (size_t i = 0; i < pointerCount; i++) {
498            status_t status = (pc++)->writeToParcel(parcel);
499            if (status) {
500                return status;
501            }
502        }
503    }
504    return OK;
505}
506#endif
507
508bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
509    if (source & AINPUT_SOURCE_CLASS_POINTER) {
510        // Specifically excludes HOVER_MOVE and SCROLL.
511        switch (action & AMOTION_EVENT_ACTION_MASK) {
512        case AMOTION_EVENT_ACTION_DOWN:
513        case AMOTION_EVENT_ACTION_MOVE:
514        case AMOTION_EVENT_ACTION_UP:
515        case AMOTION_EVENT_ACTION_POINTER_DOWN:
516        case AMOTION_EVENT_ACTION_POINTER_UP:
517        case AMOTION_EVENT_ACTION_CANCEL:
518        case AMOTION_EVENT_ACTION_OUTSIDE:
519            return true;
520        }
521    }
522    return false;
523}
524
525const char* MotionEvent::getLabel(int32_t axis) {
526    return getAxisLabel(axis);
527}
528
529int32_t MotionEvent::getAxisFromLabel(const char* label) {
530    return getAxisByLabel(label);
531}
532
533
534// --- PooledInputEventFactory ---
535
536PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) :
537        mMaxPoolSize(maxPoolSize) {
538}
539
540PooledInputEventFactory::~PooledInputEventFactory() {
541    for (size_t i = 0; i < mKeyEventPool.size(); i++) {
542        delete mKeyEventPool.itemAt(i);
543    }
544    for (size_t i = 0; i < mMotionEventPool.size(); i++) {
545        delete mMotionEventPool.itemAt(i);
546    }
547}
548
549KeyEvent* PooledInputEventFactory::createKeyEvent() {
550    if (!mKeyEventPool.isEmpty()) {
551        KeyEvent* event = mKeyEventPool.top();
552        mKeyEventPool.pop();
553        return event;
554    }
555    return new KeyEvent();
556}
557
558MotionEvent* PooledInputEventFactory::createMotionEvent() {
559    if (!mMotionEventPool.isEmpty()) {
560        MotionEvent* event = mMotionEventPool.top();
561        mMotionEventPool.pop();
562        return event;
563    }
564    return new MotionEvent();
565}
566
567void PooledInputEventFactory::recycle(InputEvent* event) {
568    switch (event->getType()) {
569    case AINPUT_EVENT_TYPE_KEY:
570        if (mKeyEventPool.size() < mMaxPoolSize) {
571            mKeyEventPool.push(static_cast<KeyEvent*>(event));
572            return;
573        }
574        break;
575    case AINPUT_EVENT_TYPE_MOTION:
576        if (mMotionEventPool.size() < mMaxPoolSize) {
577            mMotionEventPool.push(static_cast<MotionEvent*>(event));
578            return;
579        }
580        break;
581    }
582    delete event;
583}
584
585} // namespace android
586