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 <androidfw/Input.h>
24
25#ifdef HAVE_ANDROID_OS
26#include <binder/Parcel.h>
27
28#include "SkPoint.h"
29#include "SkMatrix.h"
30#include "SkScalar.h"
31#endif
32
33namespace android {
34
35// --- InputEvent ---
36
37void InputEvent::initialize(int32_t deviceId, int32_t source) {
38    mDeviceId = deviceId;
39    mSource = source;
40}
41
42void InputEvent::initialize(const InputEvent& from) {
43    mDeviceId = from.mDeviceId;
44    mSource = from.mSource;
45}
46
47// --- KeyEvent ---
48
49bool KeyEvent::hasDefaultAction(int32_t keyCode) {
50    switch (keyCode) {
51        case AKEYCODE_HOME:
52        case AKEYCODE_BACK:
53        case AKEYCODE_CALL:
54        case AKEYCODE_ENDCALL:
55        case AKEYCODE_VOLUME_UP:
56        case AKEYCODE_VOLUME_DOWN:
57        case AKEYCODE_VOLUME_MUTE:
58        case AKEYCODE_POWER:
59        case AKEYCODE_CAMERA:
60        case AKEYCODE_HEADSETHOOK:
61        case AKEYCODE_MENU:
62        case AKEYCODE_NOTIFICATION:
63        case AKEYCODE_FOCUS:
64        case AKEYCODE_SEARCH:
65        case AKEYCODE_MEDIA_PLAY:
66        case AKEYCODE_MEDIA_PAUSE:
67        case AKEYCODE_MEDIA_PLAY_PAUSE:
68        case AKEYCODE_MEDIA_STOP:
69        case AKEYCODE_MEDIA_NEXT:
70        case AKEYCODE_MEDIA_PREVIOUS:
71        case AKEYCODE_MEDIA_REWIND:
72        case AKEYCODE_MEDIA_RECORD:
73        case AKEYCODE_MEDIA_FAST_FORWARD:
74        case AKEYCODE_MUTE:
75        case AKEYCODE_BRIGHTNESS_DOWN:
76        case AKEYCODE_BRIGHTNESS_UP:
77            return true;
78    }
79
80    return false;
81}
82
83bool KeyEvent::hasDefaultAction() const {
84    return hasDefaultAction(getKeyCode());
85}
86
87bool KeyEvent::isSystemKey(int32_t keyCode) {
88    switch (keyCode) {
89        case AKEYCODE_MENU:
90        case AKEYCODE_SOFT_RIGHT:
91        case AKEYCODE_HOME:
92        case AKEYCODE_BACK:
93        case AKEYCODE_CALL:
94        case AKEYCODE_ENDCALL:
95        case AKEYCODE_VOLUME_UP:
96        case AKEYCODE_VOLUME_DOWN:
97        case AKEYCODE_VOLUME_MUTE:
98        case AKEYCODE_MUTE:
99        case AKEYCODE_POWER:
100        case AKEYCODE_HEADSETHOOK:
101        case AKEYCODE_MEDIA_PLAY:
102        case AKEYCODE_MEDIA_PAUSE:
103        case AKEYCODE_MEDIA_PLAY_PAUSE:
104        case AKEYCODE_MEDIA_STOP:
105        case AKEYCODE_MEDIA_NEXT:
106        case AKEYCODE_MEDIA_PREVIOUS:
107        case AKEYCODE_MEDIA_REWIND:
108        case AKEYCODE_MEDIA_RECORD:
109        case AKEYCODE_MEDIA_FAST_FORWARD:
110        case AKEYCODE_CAMERA:
111        case AKEYCODE_FOCUS:
112        case AKEYCODE_SEARCH:
113        case AKEYCODE_BRIGHTNESS_DOWN:
114        case AKEYCODE_BRIGHTNESS_UP:
115            return true;
116    }
117
118    return false;
119}
120
121bool KeyEvent::isSystemKey() const {
122    return isSystemKey(getKeyCode());
123}
124
125void KeyEvent::initialize(
126        int32_t deviceId,
127        int32_t source,
128        int32_t action,
129        int32_t flags,
130        int32_t keyCode,
131        int32_t scanCode,
132        int32_t metaState,
133        int32_t repeatCount,
134        nsecs_t downTime,
135        nsecs_t eventTime) {
136    InputEvent::initialize(deviceId, source);
137    mAction = action;
138    mFlags = flags;
139    mKeyCode = keyCode;
140    mScanCode = scanCode;
141    mMetaState = metaState;
142    mRepeatCount = repeatCount;
143    mDownTime = downTime;
144    mEventTime = eventTime;
145}
146
147void KeyEvent::initialize(const KeyEvent& from) {
148    InputEvent::initialize(from);
149    mAction = from.mAction;
150    mFlags = from.mFlags;
151    mKeyCode = from.mKeyCode;
152    mScanCode = from.mScanCode;
153    mMetaState = from.mMetaState;
154    mRepeatCount = from.mRepeatCount;
155    mDownTime = from.mDownTime;
156    mEventTime = from.mEventTime;
157}
158
159
160// --- PointerCoords ---
161
162float PointerCoords::getAxisValue(int32_t axis) const {
163    if (axis < 0 || axis > 63) {
164        return 0;
165    }
166
167    uint64_t axisBit = 1LL << axis;
168    if (!(bits & axisBit)) {
169        return 0;
170    }
171    uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
172    return values[index];
173}
174
175status_t PointerCoords::setAxisValue(int32_t axis, float value) {
176    if (axis < 0 || axis > 63) {
177        return NAME_NOT_FOUND;
178    }
179
180    uint64_t axisBit = 1LL << axis;
181    uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
182    if (!(bits & axisBit)) {
183        if (value == 0) {
184            return OK; // axes with value 0 do not need to be stored
185        }
186        uint32_t count = __builtin_popcountll(bits);
187        if (count >= MAX_AXES) {
188            tooManyAxes(axis);
189            return NO_MEMORY;
190        }
191        bits |= axisBit;
192        for (uint32_t i = count; i > index; i--) {
193            values[i] = values[i - 1];
194        }
195    }
196    values[index] = value;
197    return OK;
198}
199
200static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) {
201    float value = c.getAxisValue(axis);
202    if (value != 0) {
203        c.setAxisValue(axis, value * scaleFactor);
204    }
205}
206
207void PointerCoords::scale(float scaleFactor) {
208    // No need to scale pressure or size since they are normalized.
209    // No need to scale orientation since it is meaningless to do so.
210    scaleAxisValue(*this, AMOTION_EVENT_AXIS_X, scaleFactor);
211    scaleAxisValue(*this, AMOTION_EVENT_AXIS_Y, scaleFactor);
212    scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MAJOR, scaleFactor);
213    scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MINOR, scaleFactor);
214    scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MAJOR, scaleFactor);
215    scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor);
216}
217
218#ifdef HAVE_ANDROID_OS
219status_t PointerCoords::readFromParcel(Parcel* parcel) {
220    bits = parcel->readInt64();
221
222    uint32_t count = __builtin_popcountll(bits);
223    if (count > MAX_AXES) {
224        return BAD_VALUE;
225    }
226
227    for (uint32_t i = 0; i < count; i++) {
228        values[i] = parcel->readFloat();
229    }
230    return OK;
231}
232
233status_t PointerCoords::writeToParcel(Parcel* parcel) const {
234    parcel->writeInt64(bits);
235
236    uint32_t count = __builtin_popcountll(bits);
237    for (uint32_t i = 0; i < count; i++) {
238        parcel->writeFloat(values[i]);
239    }
240    return OK;
241}
242#endif
243
244void PointerCoords::tooManyAxes(int axis) {
245    ALOGW("Could not set value for axis %d because the PointerCoords structure is full and "
246            "cannot contain more than %d axis values.", axis, int(MAX_AXES));
247}
248
249bool PointerCoords::operator==(const PointerCoords& other) const {
250    if (bits != other.bits) {
251        return false;
252    }
253    uint32_t count = __builtin_popcountll(bits);
254    for (uint32_t i = 0; i < count; i++) {
255        if (values[i] != other.values[i]) {
256            return false;
257        }
258    }
259    return true;
260}
261
262void PointerCoords::copyFrom(const PointerCoords& other) {
263    bits = other.bits;
264    uint32_t count = __builtin_popcountll(bits);
265    for (uint32_t i = 0; i < count; i++) {
266        values[i] = other.values[i];
267    }
268}
269
270
271// --- PointerProperties ---
272
273bool PointerProperties::operator==(const PointerProperties& other) const {
274    return id == other.id
275            && toolType == other.toolType;
276}
277
278void PointerProperties::copyFrom(const PointerProperties& other) {
279    id = other.id;
280    toolType = other.toolType;
281}
282
283
284// --- MotionEvent ---
285
286void MotionEvent::initialize(
287        int32_t deviceId,
288        int32_t source,
289        int32_t action,
290        int32_t flags,
291        int32_t edgeFlags,
292        int32_t metaState,
293        int32_t buttonState,
294        float xOffset,
295        float yOffset,
296        float xPrecision,
297        float yPrecision,
298        nsecs_t downTime,
299        nsecs_t eventTime,
300        size_t pointerCount,
301        const PointerProperties* pointerProperties,
302        const PointerCoords* pointerCoords) {
303    InputEvent::initialize(deviceId, source);
304    mAction = action;
305    mFlags = flags;
306    mEdgeFlags = edgeFlags;
307    mMetaState = metaState;
308    mButtonState = buttonState;
309    mXOffset = xOffset;
310    mYOffset = yOffset;
311    mXPrecision = xPrecision;
312    mYPrecision = yPrecision;
313    mDownTime = downTime;
314    mPointerProperties.clear();
315    mPointerProperties.appendArray(pointerProperties, pointerCount);
316    mSampleEventTimes.clear();
317    mSamplePointerCoords.clear();
318    addSample(eventTime, pointerCoords);
319}
320
321void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
322    InputEvent::initialize(other->mDeviceId, other->mSource);
323    mAction = other->mAction;
324    mFlags = other->mFlags;
325    mEdgeFlags = other->mEdgeFlags;
326    mMetaState = other->mMetaState;
327    mButtonState = other->mButtonState;
328    mXOffset = other->mXOffset;
329    mYOffset = other->mYOffset;
330    mXPrecision = other->mXPrecision;
331    mYPrecision = other->mYPrecision;
332    mDownTime = other->mDownTime;
333    mPointerProperties = other->mPointerProperties;
334
335    if (keepHistory) {
336        mSampleEventTimes = other->mSampleEventTimes;
337        mSamplePointerCoords = other->mSamplePointerCoords;
338    } else {
339        mSampleEventTimes.clear();
340        mSampleEventTimes.push(other->getEventTime());
341        mSamplePointerCoords.clear();
342        size_t pointerCount = other->getPointerCount();
343        size_t historySize = other->getHistorySize();
344        mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array()
345                + (historySize * pointerCount), pointerCount);
346    }
347}
348
349void MotionEvent::addSample(
350        int64_t eventTime,
351        const PointerCoords* pointerCoords) {
352    mSampleEventTimes.push(eventTime);
353    mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
354}
355
356const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
357    return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
358}
359
360float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
361    return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
362}
363
364float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const {
365    float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis);
366    switch (axis) {
367    case AMOTION_EVENT_AXIS_X:
368        return value + mXOffset;
369    case AMOTION_EVENT_AXIS_Y:
370        return value + mYOffset;
371    }
372    return value;
373}
374
375const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
376        size_t pointerIndex, size_t historicalIndex) const {
377    return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
378}
379
380float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
381        size_t historicalIndex) const {
382    return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
383}
384
385float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
386        size_t historicalIndex) const {
387    float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
388    switch (axis) {
389    case AMOTION_EVENT_AXIS_X:
390        return value + mXOffset;
391    case AMOTION_EVENT_AXIS_Y:
392        return value + mYOffset;
393    }
394    return value;
395}
396
397ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
398    size_t pointerCount = mPointerProperties.size();
399    for (size_t i = 0; i < pointerCount; i++) {
400        if (mPointerProperties.itemAt(i).id == pointerId) {
401            return i;
402        }
403    }
404    return -1;
405}
406
407void MotionEvent::offsetLocation(float xOffset, float yOffset) {
408    mXOffset += xOffset;
409    mYOffset += yOffset;
410}
411
412void MotionEvent::scale(float scaleFactor) {
413    mXOffset *= scaleFactor;
414    mYOffset *= scaleFactor;
415    mXPrecision *= scaleFactor;
416    mYPrecision *= scaleFactor;
417
418    size_t numSamples = mSamplePointerCoords.size();
419    for (size_t i = 0; i < numSamples; i++) {
420        mSamplePointerCoords.editItemAt(i).scale(scaleFactor);
421    }
422}
423
424#ifdef HAVE_ANDROID_OS
425static inline float transformAngle(const SkMatrix* matrix, float angleRadians) {
426    // Construct and transform a vector oriented at the specified clockwise angle from vertical.
427    // Coordinate system: down is increasing Y, right is increasing X.
428    SkPoint vector;
429    vector.fX = SkFloatToScalar(sinf(angleRadians));
430    vector.fY = SkFloatToScalar(-cosf(angleRadians));
431    matrix->mapVectors(& vector, 1);
432
433    // Derive the transformed vector's clockwise angle from vertical.
434    float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY));
435    if (result < - M_PI_2) {
436        result += M_PI;
437    } else if (result > M_PI_2) {
438        result -= M_PI;
439    }
440    return result;
441}
442
443void MotionEvent::transform(const SkMatrix* matrix) {
444    float oldXOffset = mXOffset;
445    float oldYOffset = mYOffset;
446
447    // The tricky part of this implementation is to preserve the value of
448    // rawX and rawY.  So we apply the transformation to the first point
449    // then derive an appropriate new X/Y offset that will preserve rawX and rawY.
450    SkPoint point;
451    float rawX = getRawX(0);
452    float rawY = getRawY(0);
453    matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset),
454            & point);
455    float newX = SkScalarToFloat(point.fX);
456    float newY = SkScalarToFloat(point.fY);
457    float newXOffset = newX - rawX;
458    float newYOffset = newY - rawY;
459
460    mXOffset = newXOffset;
461    mYOffset = newYOffset;
462
463    // Apply the transformation to all samples.
464    size_t numSamples = mSamplePointerCoords.size();
465    for (size_t i = 0; i < numSamples; i++) {
466        PointerCoords& c = mSamplePointerCoords.editItemAt(i);
467        float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset;
468        float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset;
469        matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), &point);
470        c.setAxisValue(AMOTION_EVENT_AXIS_X, SkScalarToFloat(point.fX) - newXOffset);
471        c.setAxisValue(AMOTION_EVENT_AXIS_Y, SkScalarToFloat(point.fY) - newYOffset);
472
473        float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
474        c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(matrix, orientation));
475    }
476}
477
478status_t MotionEvent::readFromParcel(Parcel* parcel) {
479    size_t pointerCount = parcel->readInt32();
480    size_t sampleCount = parcel->readInt32();
481    if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) {
482        return BAD_VALUE;
483    }
484
485    mDeviceId = parcel->readInt32();
486    mSource = parcel->readInt32();
487    mAction = parcel->readInt32();
488    mFlags = parcel->readInt32();
489    mEdgeFlags = parcel->readInt32();
490    mMetaState = parcel->readInt32();
491    mButtonState = parcel->readInt32();
492    mXOffset = parcel->readFloat();
493    mYOffset = parcel->readFloat();
494    mXPrecision = parcel->readFloat();
495    mYPrecision = parcel->readFloat();
496    mDownTime = parcel->readInt64();
497
498    mPointerProperties.clear();
499    mPointerProperties.setCapacity(pointerCount);
500    mSampleEventTimes.clear();
501    mSampleEventTimes.setCapacity(sampleCount);
502    mSamplePointerCoords.clear();
503    mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
504
505    for (size_t i = 0; i < pointerCount; i++) {
506        mPointerProperties.push();
507        PointerProperties& properties = mPointerProperties.editTop();
508        properties.id = parcel->readInt32();
509        properties.toolType = parcel->readInt32();
510    }
511
512    while (sampleCount-- > 0) {
513        mSampleEventTimes.push(parcel->readInt64());
514        for (size_t i = 0; i < pointerCount; i++) {
515            mSamplePointerCoords.push();
516            status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel);
517            if (status) {
518                return status;
519            }
520        }
521    }
522    return OK;
523}
524
525status_t MotionEvent::writeToParcel(Parcel* parcel) const {
526    size_t pointerCount = mPointerProperties.size();
527    size_t sampleCount = mSampleEventTimes.size();
528
529    parcel->writeInt32(pointerCount);
530    parcel->writeInt32(sampleCount);
531
532    parcel->writeInt32(mDeviceId);
533    parcel->writeInt32(mSource);
534    parcel->writeInt32(mAction);
535    parcel->writeInt32(mFlags);
536    parcel->writeInt32(mEdgeFlags);
537    parcel->writeInt32(mMetaState);
538    parcel->writeInt32(mButtonState);
539    parcel->writeFloat(mXOffset);
540    parcel->writeFloat(mYOffset);
541    parcel->writeFloat(mXPrecision);
542    parcel->writeFloat(mYPrecision);
543    parcel->writeInt64(mDownTime);
544
545    for (size_t i = 0; i < pointerCount; i++) {
546        const PointerProperties& properties = mPointerProperties.itemAt(i);
547        parcel->writeInt32(properties.id);
548        parcel->writeInt32(properties.toolType);
549    }
550
551    const PointerCoords* pc = mSamplePointerCoords.array();
552    for (size_t h = 0; h < sampleCount; h++) {
553        parcel->writeInt64(mSampleEventTimes.itemAt(h));
554        for (size_t i = 0; i < pointerCount; i++) {
555            status_t status = (pc++)->writeToParcel(parcel);
556            if (status) {
557                return status;
558            }
559        }
560    }
561    return OK;
562}
563#endif
564
565bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
566    if (source & AINPUT_SOURCE_CLASS_POINTER) {
567        // Specifically excludes HOVER_MOVE and SCROLL.
568        switch (action & AMOTION_EVENT_ACTION_MASK) {
569        case AMOTION_EVENT_ACTION_DOWN:
570        case AMOTION_EVENT_ACTION_MOVE:
571        case AMOTION_EVENT_ACTION_UP:
572        case AMOTION_EVENT_ACTION_POINTER_DOWN:
573        case AMOTION_EVENT_ACTION_POINTER_UP:
574        case AMOTION_EVENT_ACTION_CANCEL:
575        case AMOTION_EVENT_ACTION_OUTSIDE:
576            return true;
577        }
578    }
579    return false;
580}
581
582
583// --- PooledInputEventFactory ---
584
585PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) :
586        mMaxPoolSize(maxPoolSize) {
587}
588
589PooledInputEventFactory::~PooledInputEventFactory() {
590    for (size_t i = 0; i < mKeyEventPool.size(); i++) {
591        delete mKeyEventPool.itemAt(i);
592    }
593    for (size_t i = 0; i < mMotionEventPool.size(); i++) {
594        delete mMotionEventPool.itemAt(i);
595    }
596}
597
598KeyEvent* PooledInputEventFactory::createKeyEvent() {
599    if (!mKeyEventPool.isEmpty()) {
600        KeyEvent* event = mKeyEventPool.top();
601        mKeyEventPool.pop();
602        return event;
603    }
604    return new KeyEvent();
605}
606
607MotionEvent* PooledInputEventFactory::createMotionEvent() {
608    if (!mMotionEventPool.isEmpty()) {
609        MotionEvent* event = mMotionEventPool.top();
610        mMotionEventPool.pop();
611        return event;
612    }
613    return new MotionEvent();
614}
615
616void PooledInputEventFactory::recycle(InputEvent* event) {
617    switch (event->getType()) {
618    case AINPUT_EVENT_TYPE_KEY:
619        if (mKeyEventPool.size() < mMaxPoolSize) {
620            mKeyEventPool.push(static_cast<KeyEvent*>(event));
621            return;
622        }
623        break;
624    case AINPUT_EVENT_TYPE_MOTION:
625        if (mMotionEventPool.size() < mMaxPoolSize) {
626            mMotionEventPool.push(static_cast<MotionEvent*>(event));
627            return;
628        }
629        break;
630    }
631    delete event;
632}
633
634} // namespace android
635