Input.cpp revision 2ed2462aa29c564f5231f317c27b3188da875e52
1//
2// Copyright 2010 The Android Open Source Project
3//
4// Provides a pipe-based transport for native events in the NDK.
5//
6#define LOG_TAG "Input"
7
8//#define LOG_NDEBUG 0
9
10// Log debug messages about keymap probing.
11#define DEBUG_PROBE 0
12
13// Log debug messages about velocity tracking.
14#define DEBUG_VELOCITY 0
15
16#include <stdlib.h>
17#include <unistd.h>
18#include <ctype.h>
19
20#include <ui/Input.h>
21
22#include <math.h>
23
24#ifdef HAVE_ANDROID_OS
25#include <binder/Parcel.h>
26
27#include "SkPoint.h"
28#include "SkMatrix.h"
29#include "SkScalar.h"
30#endif
31
32namespace android {
33
34static const char* CONFIGURATION_FILE_DIR[] = {
35        "idc/",
36        "keylayout/",
37        "keychars/",
38};
39
40static const char* CONFIGURATION_FILE_EXTENSION[] = {
41        ".idc",
42        ".kl",
43        ".kcm",
44};
45
46static bool isValidNameChar(char ch) {
47    return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_');
48}
49
50static void appendInputDeviceConfigurationFileRelativePath(String8& path,
51        const String8& name, InputDeviceConfigurationFileType type) {
52    path.append(CONFIGURATION_FILE_DIR[type]);
53    for (size_t i = 0; i < name.length(); i++) {
54        char ch = name[i];
55        if (!isValidNameChar(ch)) {
56            ch = '_';
57        }
58        path.append(&ch, 1);
59    }
60    path.append(CONFIGURATION_FILE_EXTENSION[type]);
61}
62
63String8 getInputDeviceConfigurationFilePathByDeviceIdentifier(
64        const InputDeviceIdentifier& deviceIdentifier,
65        InputDeviceConfigurationFileType type) {
66    if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
67        if (deviceIdentifier.version != 0) {
68            // Try vendor product version.
69            String8 versionPath(getInputDeviceConfigurationFilePathByName(
70                    String8::format("Vendor_%04x_Product_%04x_Version_%04x",
71                            deviceIdentifier.vendor, deviceIdentifier.product,
72                            deviceIdentifier.version),
73                    type));
74            if (!versionPath.isEmpty()) {
75                return versionPath;
76            }
77        }
78
79        // Try vendor product.
80        String8 productPath(getInputDeviceConfigurationFilePathByName(
81                String8::format("Vendor_%04x_Product_%04x",
82                        deviceIdentifier.vendor, deviceIdentifier.product),
83                type));
84        if (!productPath.isEmpty()) {
85            return productPath;
86        }
87    }
88
89    // Try device name.
90    return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type);
91}
92
93String8 getInputDeviceConfigurationFilePathByName(
94        const String8& name, InputDeviceConfigurationFileType type) {
95    // Search system repository.
96    String8 path;
97    path.setTo(getenv("ANDROID_ROOT"));
98    path.append("/usr/");
99    appendInputDeviceConfigurationFileRelativePath(path, name, type);
100#if DEBUG_PROBE
101    LOGD("Probing for system provided input device configuration file: path='%s'", path.string());
102#endif
103    if (!access(path.string(), R_OK)) {
104#if DEBUG_PROBE
105        LOGD("Found");
106#endif
107        return path;
108    }
109
110    // Search user repository.
111    // TODO Should only look here if not in safe mode.
112    path.setTo(getenv("ANDROID_DATA"));
113    path.append("/system/devices/");
114    appendInputDeviceConfigurationFileRelativePath(path, name, type);
115#if DEBUG_PROBE
116    LOGD("Probing for system user input device configuration file: path='%s'", path.string());
117#endif
118    if (!access(path.string(), R_OK)) {
119#if DEBUG_PROBE
120        LOGD("Found");
121#endif
122        return path;
123    }
124
125    // Not found.
126#if DEBUG_PROBE
127    LOGD("Probe failed to find input device configuration file: name='%s', type=%d",
128            name.string(), type);
129#endif
130    return String8();
131}
132
133
134// --- InputEvent ---
135
136void InputEvent::initialize(int32_t deviceId, int32_t source) {
137    mDeviceId = deviceId;
138    mSource = source;
139}
140
141void InputEvent::initialize(const InputEvent& from) {
142    mDeviceId = from.mDeviceId;
143    mSource = from.mSource;
144}
145
146// --- KeyEvent ---
147
148bool KeyEvent::hasDefaultAction(int32_t keyCode) {
149    switch (keyCode) {
150        case AKEYCODE_HOME:
151        case AKEYCODE_BACK:
152        case AKEYCODE_CALL:
153        case AKEYCODE_ENDCALL:
154        case AKEYCODE_VOLUME_UP:
155        case AKEYCODE_VOLUME_DOWN:
156        case AKEYCODE_VOLUME_MUTE:
157        case AKEYCODE_POWER:
158        case AKEYCODE_CAMERA:
159        case AKEYCODE_HEADSETHOOK:
160        case AKEYCODE_MENU:
161        case AKEYCODE_NOTIFICATION:
162        case AKEYCODE_FOCUS:
163        case AKEYCODE_SEARCH:
164        case AKEYCODE_MEDIA_PLAY:
165        case AKEYCODE_MEDIA_PAUSE:
166        case AKEYCODE_MEDIA_PLAY_PAUSE:
167        case AKEYCODE_MEDIA_STOP:
168        case AKEYCODE_MEDIA_NEXT:
169        case AKEYCODE_MEDIA_PREVIOUS:
170        case AKEYCODE_MEDIA_REWIND:
171        case AKEYCODE_MEDIA_RECORD:
172        case AKEYCODE_MEDIA_FAST_FORWARD:
173        case AKEYCODE_MUTE:
174            return true;
175    }
176
177    return false;
178}
179
180bool KeyEvent::hasDefaultAction() const {
181    return hasDefaultAction(getKeyCode());
182}
183
184bool KeyEvent::isSystemKey(int32_t keyCode) {
185    switch (keyCode) {
186        case AKEYCODE_MENU:
187        case AKEYCODE_SOFT_RIGHT:
188        case AKEYCODE_HOME:
189        case AKEYCODE_BACK:
190        case AKEYCODE_CALL:
191        case AKEYCODE_ENDCALL:
192        case AKEYCODE_VOLUME_UP:
193        case AKEYCODE_VOLUME_DOWN:
194        case AKEYCODE_VOLUME_MUTE:
195        case AKEYCODE_MUTE:
196        case AKEYCODE_POWER:
197        case AKEYCODE_HEADSETHOOK:
198        case AKEYCODE_MEDIA_PLAY:
199        case AKEYCODE_MEDIA_PAUSE:
200        case AKEYCODE_MEDIA_PLAY_PAUSE:
201        case AKEYCODE_MEDIA_STOP:
202        case AKEYCODE_MEDIA_NEXT:
203        case AKEYCODE_MEDIA_PREVIOUS:
204        case AKEYCODE_MEDIA_REWIND:
205        case AKEYCODE_MEDIA_RECORD:
206        case AKEYCODE_MEDIA_FAST_FORWARD:
207        case AKEYCODE_CAMERA:
208        case AKEYCODE_FOCUS:
209        case AKEYCODE_SEARCH:
210            return true;
211    }
212
213    return false;
214}
215
216bool KeyEvent::isSystemKey() const {
217    return isSystemKey(getKeyCode());
218}
219
220void KeyEvent::initialize(
221        int32_t deviceId,
222        int32_t source,
223        int32_t action,
224        int32_t flags,
225        int32_t keyCode,
226        int32_t scanCode,
227        int32_t metaState,
228        int32_t repeatCount,
229        nsecs_t downTime,
230        nsecs_t eventTime) {
231    InputEvent::initialize(deviceId, source);
232    mAction = action;
233    mFlags = flags;
234    mKeyCode = keyCode;
235    mScanCode = scanCode;
236    mMetaState = metaState;
237    mRepeatCount = repeatCount;
238    mDownTime = downTime;
239    mEventTime = eventTime;
240}
241
242void KeyEvent::initialize(const KeyEvent& from) {
243    InputEvent::initialize(from);
244    mAction = from.mAction;
245    mFlags = from.mFlags;
246    mKeyCode = from.mKeyCode;
247    mScanCode = from.mScanCode;
248    mMetaState = from.mMetaState;
249    mRepeatCount = from.mRepeatCount;
250    mDownTime = from.mDownTime;
251    mEventTime = from.mEventTime;
252}
253
254
255// --- PointerCoords ---
256
257float PointerCoords::getAxisValue(int32_t axis) const {
258    if (axis < 0 || axis > 63) {
259        return 0;
260    }
261
262    uint64_t axisBit = 1LL << axis;
263    if (!(bits & axisBit)) {
264        return 0;
265    }
266    uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
267    return values[index];
268}
269
270status_t PointerCoords::setAxisValue(int32_t axis, float value) {
271    if (axis < 0 || axis > 63) {
272        return NAME_NOT_FOUND;
273    }
274
275    uint64_t axisBit = 1LL << axis;
276    uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
277    if (!(bits & axisBit)) {
278        uint32_t count = __builtin_popcountll(bits);
279        if (count >= MAX_AXES) {
280            tooManyAxes(axis);
281            return NO_MEMORY;
282        }
283        bits |= axisBit;
284        for (uint32_t i = count; i > index; i--) {
285            values[i] = values[i - 1];
286        }
287    }
288    values[index] = value;
289    return OK;
290}
291
292float* PointerCoords::editAxisValue(int32_t axis) {
293    if (axis < 0 || axis > 63) {
294        return NULL;
295    }
296
297    uint64_t axisBit = 1LL << axis;
298    if (!(bits & axisBit)) {
299        return NULL;
300    }
301    uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
302    return &values[index];
303}
304
305#ifdef HAVE_ANDROID_OS
306status_t PointerCoords::readFromParcel(Parcel* parcel) {
307    bits = parcel->readInt64();
308
309    uint32_t count = __builtin_popcountll(bits);
310    if (count > MAX_AXES) {
311        return BAD_VALUE;
312    }
313
314    for (uint32_t i = 0; i < count; i++) {
315        values[i] = parcel->readInt32();
316    }
317    return OK;
318}
319
320status_t PointerCoords::writeToParcel(Parcel* parcel) const {
321    parcel->writeInt64(bits);
322
323    uint32_t count = __builtin_popcountll(bits);
324    for (uint32_t i = 0; i < count; i++) {
325        parcel->writeInt32(values[i]);
326    }
327    return OK;
328}
329#endif
330
331void PointerCoords::tooManyAxes(int axis) {
332    LOGW("Could not set value for axis %d because the PointerCoords structure is full and "
333            "cannot contain more than %d axis values.", axis, int(MAX_AXES));
334}
335
336bool PointerCoords::operator==(const PointerCoords& other) const {
337    if (bits != other.bits) {
338        return false;
339    }
340    uint32_t count = __builtin_popcountll(bits);
341    for (uint32_t i = 0; i < count; i++) {
342        if (values[i] != other.values[i]) {
343            return false;
344        }
345    }
346    return true;
347}
348
349void PointerCoords::copyFrom(const PointerCoords& other) {
350    bits = other.bits;
351    uint32_t count = __builtin_popcountll(bits);
352    for (uint32_t i = 0; i < count; i++) {
353        values[i] = other.values[i];
354    }
355}
356
357
358// --- MotionEvent ---
359
360void MotionEvent::initialize(
361        int32_t deviceId,
362        int32_t source,
363        int32_t action,
364        int32_t flags,
365        int32_t edgeFlags,
366        int32_t metaState,
367        float xOffset,
368        float yOffset,
369        float xPrecision,
370        float yPrecision,
371        nsecs_t downTime,
372        nsecs_t eventTime,
373        size_t pointerCount,
374        const int32_t* pointerIds,
375        const PointerCoords* pointerCoords) {
376    InputEvent::initialize(deviceId, source);
377    mAction = action;
378    mFlags = flags;
379    mEdgeFlags = edgeFlags;
380    mMetaState = metaState;
381    mXOffset = xOffset;
382    mYOffset = yOffset;
383    mXPrecision = xPrecision;
384    mYPrecision = yPrecision;
385    mDownTime = downTime;
386    mPointerIds.clear();
387    mPointerIds.appendArray(pointerIds, pointerCount);
388    mSampleEventTimes.clear();
389    mSamplePointerCoords.clear();
390    addSample(eventTime, pointerCoords);
391}
392
393void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
394    InputEvent::initialize(other->mDeviceId, other->mSource);
395    mAction = other->mAction;
396    mFlags = other->mFlags;
397    mEdgeFlags = other->mEdgeFlags;
398    mMetaState = other->mMetaState;
399    mXOffset = other->mXOffset;
400    mYOffset = other->mYOffset;
401    mXPrecision = other->mXPrecision;
402    mYPrecision = other->mYPrecision;
403    mDownTime = other->mDownTime;
404    mPointerIds = other->mPointerIds;
405
406    if (keepHistory) {
407        mSampleEventTimes = other->mSampleEventTimes;
408        mSamplePointerCoords = other->mSamplePointerCoords;
409    } else {
410        mSampleEventTimes.clear();
411        mSampleEventTimes.push(other->getEventTime());
412        mSamplePointerCoords.clear();
413        size_t pointerCount = other->getPointerCount();
414        size_t historySize = other->getHistorySize();
415        mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array()
416                + (historySize * pointerCount), pointerCount);
417    }
418}
419
420void MotionEvent::addSample(
421        int64_t eventTime,
422        const PointerCoords* pointerCoords) {
423    mSampleEventTimes.push(eventTime);
424    mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
425}
426
427const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
428    return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
429}
430
431float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
432    return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
433}
434
435float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const {
436    float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis);
437    switch (axis) {
438    case AMOTION_EVENT_AXIS_X:
439        value += mXOffset;
440        break;
441    case AMOTION_EVENT_AXIS_Y:
442        value += mYOffset;
443        break;
444    }
445    return value;
446}
447
448const PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
449        size_t pointerIndex, size_t historicalIndex) const {
450    return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
451}
452
453float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
454        size_t historicalIndex) const {
455    return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
456}
457
458float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
459        size_t historicalIndex) const {
460    float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
461    switch (axis) {
462    case AMOTION_EVENT_AXIS_X:
463        value += mXOffset;
464        break;
465    case AMOTION_EVENT_AXIS_Y:
466        value += mYOffset;
467        break;
468    }
469    return value;
470}
471
472ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
473    size_t pointerCount = mPointerIds.size();
474    for (size_t i = 0; i < pointerCount; i++) {
475        if (mPointerIds.itemAt(i) == pointerId) {
476            return i;
477        }
478    }
479    return -1;
480}
481
482void MotionEvent::offsetLocation(float xOffset, float yOffset) {
483    mXOffset += xOffset;
484    mYOffset += yOffset;
485}
486
487static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) {
488    float* value = c.editAxisValue(axis);
489    if (value) {
490        *value *= scaleFactor;
491    }
492}
493
494void MotionEvent::scale(float scaleFactor) {
495    mXOffset *= scaleFactor;
496    mYOffset *= scaleFactor;
497    mXPrecision *= scaleFactor;
498    mYPrecision *= scaleFactor;
499
500    size_t numSamples = mSamplePointerCoords.size();
501    for (size_t i = 0; i < numSamples; i++) {
502        PointerCoords& c = mSamplePointerCoords.editItemAt(i);
503        // No need to scale pressure or size since they are normalized.
504        // No need to scale orientation since it is meaningless to do so.
505        scaleAxisValue(c, AMOTION_EVENT_AXIS_X, scaleFactor);
506        scaleAxisValue(c, AMOTION_EVENT_AXIS_Y, scaleFactor);
507        scaleAxisValue(c, AMOTION_EVENT_AXIS_TOUCH_MAJOR, scaleFactor);
508        scaleAxisValue(c, AMOTION_EVENT_AXIS_TOUCH_MINOR, scaleFactor);
509        scaleAxisValue(c, AMOTION_EVENT_AXIS_TOOL_MAJOR, scaleFactor);
510        scaleAxisValue(c, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor);
511    }
512}
513
514#ifdef HAVE_ANDROID_OS
515static inline float transformAngle(const SkMatrix* matrix, float angleRadians) {
516    // Construct and transform a vector oriented at the specified clockwise angle from vertical.
517    // Coordinate system: down is increasing Y, right is increasing X.
518    SkPoint vector;
519    vector.fX = SkFloatToScalar(sinf(angleRadians));
520    vector.fY = SkFloatToScalar(-cosf(angleRadians));
521    matrix->mapVectors(& vector, 1);
522
523    // Derive the transformed vector's clockwise angle from vertical.
524    float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY));
525    if (result < - M_PI_2) {
526        result += M_PI;
527    } else if (result > M_PI_2) {
528        result -= M_PI;
529    }
530    return result;
531}
532
533void MotionEvent::transform(const SkMatrix* matrix) {
534    float oldXOffset = mXOffset;
535    float oldYOffset = mYOffset;
536
537    // The tricky part of this implementation is to preserve the value of
538    // rawX and rawY.  So we apply the transformation to the first point
539    // then derive an appropriate new X/Y offset that will preserve rawX and rawY.
540    SkPoint point;
541    float rawX = getRawX(0);
542    float rawY = getRawY(0);
543    matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset),
544            & point);
545    float newX = SkScalarToFloat(point.fX);
546    float newY = SkScalarToFloat(point.fY);
547    float newXOffset = newX - rawX;
548    float newYOffset = newY - rawY;
549
550    mXOffset = newXOffset;
551    mYOffset = newYOffset;
552
553    // Apply the transformation to all samples.
554    size_t numSamples = mSamplePointerCoords.size();
555    for (size_t i = 0; i < numSamples; i++) {
556        PointerCoords& c = mSamplePointerCoords.editItemAt(i);
557        float* xPtr = c.editAxisValue(AMOTION_EVENT_AXIS_X);
558        float* yPtr = c.editAxisValue(AMOTION_EVENT_AXIS_Y);
559        if (xPtr && yPtr) {
560            float x = *xPtr + oldXOffset;
561            float y = *yPtr + oldYOffset;
562            matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), & point);
563            *xPtr = SkScalarToFloat(point.fX) - newXOffset;
564            *yPtr = SkScalarToFloat(point.fY) - newYOffset;
565        }
566
567        float* orientationPtr = c.editAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
568        if (orientationPtr) {
569            *orientationPtr = transformAngle(matrix, *orientationPtr);
570        }
571    }
572}
573
574status_t MotionEvent::readFromParcel(Parcel* parcel) {
575    size_t pointerCount = parcel->readInt32();
576    size_t sampleCount = parcel->readInt32();
577    if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) {
578        return BAD_VALUE;
579    }
580
581    mDeviceId = parcel->readInt32();
582    mSource = parcel->readInt32();
583    mAction = parcel->readInt32();
584    mFlags = parcel->readInt32();
585    mEdgeFlags = parcel->readInt32();
586    mMetaState = parcel->readInt32();
587    mXOffset = parcel->readFloat();
588    mYOffset = parcel->readFloat();
589    mXPrecision = parcel->readFloat();
590    mYPrecision = parcel->readFloat();
591    mDownTime = parcel->readInt64();
592
593    mPointerIds.clear();
594    mPointerIds.setCapacity(pointerCount);
595    mSampleEventTimes.clear();
596    mSampleEventTimes.setCapacity(sampleCount);
597    mSamplePointerCoords.clear();
598    mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
599
600    for (size_t i = 0; i < pointerCount; i++) {
601        mPointerIds.push(parcel->readInt32());
602    }
603
604    while (sampleCount-- > 0) {
605        mSampleEventTimes.push(parcel->readInt64());
606        for (size_t i = 0; i < pointerCount; i++) {
607            mSamplePointerCoords.push();
608            status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel);
609            if (status) {
610                return status;
611            }
612        }
613    }
614    return OK;
615}
616
617status_t MotionEvent::writeToParcel(Parcel* parcel) const {
618    size_t pointerCount = mPointerIds.size();
619    size_t sampleCount = mSampleEventTimes.size();
620
621    parcel->writeInt32(pointerCount);
622    parcel->writeInt32(sampleCount);
623
624    parcel->writeInt32(mDeviceId);
625    parcel->writeInt32(mSource);
626    parcel->writeInt32(mAction);
627    parcel->writeInt32(mFlags);
628    parcel->writeInt32(mEdgeFlags);
629    parcel->writeInt32(mMetaState);
630    parcel->writeFloat(mXOffset);
631    parcel->writeFloat(mYOffset);
632    parcel->writeFloat(mXPrecision);
633    parcel->writeFloat(mYPrecision);
634    parcel->writeInt64(mDownTime);
635
636    for (size_t i = 0; i < pointerCount; i++) {
637        parcel->writeInt32(mPointerIds.itemAt(i));
638    }
639
640    const PointerCoords* pc = mSamplePointerCoords.array();
641    for (size_t h = 0; h < sampleCount; h++) {
642        parcel->writeInt64(mSampleEventTimes.itemAt(h));
643        for (size_t i = 0; i < pointerCount; i++) {
644            status_t status = (pc++)->writeToParcel(parcel);
645            if (status) {
646                return status;
647            }
648        }
649    }
650    return OK;
651}
652#endif
653
654bool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
655    if (source & AINPUT_SOURCE_CLASS_POINTER) {
656        // Specifically excludes HOVER_MOVE and SCROLL.
657        switch (action & AMOTION_EVENT_ACTION_MASK) {
658        case AMOTION_EVENT_ACTION_DOWN:
659        case AMOTION_EVENT_ACTION_MOVE:
660        case AMOTION_EVENT_ACTION_UP:
661        case AMOTION_EVENT_ACTION_POINTER_DOWN:
662        case AMOTION_EVENT_ACTION_POINTER_UP:
663        case AMOTION_EVENT_ACTION_CANCEL:
664        case AMOTION_EVENT_ACTION_OUTSIDE:
665            return true;
666        }
667    }
668    return false;
669}
670
671
672// --- VelocityTracker ---
673
674VelocityTracker::VelocityTracker() {
675    clear();
676}
677
678void VelocityTracker::clear() {
679    mIndex = 0;
680    mMovements[0].idBits.clear();
681    mActivePointerId = -1;
682}
683
684void VelocityTracker::clearPointers(BitSet32 idBits) {
685    BitSet32 remainingIdBits(mMovements[mIndex].idBits.value & ~idBits.value);
686    mMovements[mIndex].idBits = remainingIdBits;
687
688    if (mActivePointerId >= 0 && idBits.hasBit(mActivePointerId)) {
689        mActivePointerId = !remainingIdBits.isEmpty() ? remainingIdBits.firstMarkedBit() : -1;
690    }
691}
692
693void VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions) {
694    if (++mIndex == HISTORY_SIZE) {
695        mIndex = 0;
696    }
697
698    while (idBits.count() > MAX_POINTERS) {
699        idBits.clearBit(idBits.lastMarkedBit());
700    }
701
702    Movement& movement = mMovements[mIndex];
703    movement.eventTime = eventTime;
704    movement.idBits = idBits;
705    uint32_t count = idBits.count();
706    for (uint32_t i = 0; i < count; i++) {
707        movement.positions[i] = positions[i];
708    }
709
710    if (mActivePointerId < 0 || !idBits.hasBit(mActivePointerId)) {
711        mActivePointerId = count != 0 ? idBits.firstMarkedBit() : -1;
712    }
713
714#if DEBUG_VELOCITY
715    LOGD("VelocityTracker: addMovement eventTime=%lld, idBits=0x%08x, activePointerId=%d",
716            eventTime, idBits.value, mActivePointerId);
717    for (BitSet32 iterBits(idBits); !iterBits.isEmpty(); ) {
718        uint32_t id = iterBits.firstMarkedBit();
719        uint32_t index = idBits.getIndexOfBit(id);
720        iterBits.clearBit(id);
721        float vx, vy;
722        bool available = getVelocity(id, &vx, &vy);
723        if (available) {
724            LOGD("  %d: position (%0.3f, %0.3f), vx=%0.3f, vy=%0.3f, speed=%0.3f",
725                    id, positions[index].x, positions[index].y, vx, vy, sqrtf(vx * vx + vy * vy));
726        } else {
727            assert(vx == 0 && vy == 0);
728            LOGD("  %d: position (%0.3f, %0.3f), velocity not available",
729                    id, positions[index].x, positions[index].y);
730        }
731    }
732#endif
733}
734
735void VelocityTracker::addMovement(const MotionEvent* event) {
736    int32_t actionMasked = event->getActionMasked();
737
738    switch (actionMasked) {
739    case AMOTION_EVENT_ACTION_DOWN:
740        // Clear all pointers on down before adding the new movement.
741        clear();
742        break;
743    case AMOTION_EVENT_ACTION_POINTER_DOWN: {
744        // Start a new movement trace for a pointer that just went down.
745        // We do this on down instead of on up because the client may want to query the
746        // final velocity for a pointer that just went up.
747        BitSet32 downIdBits;
748        downIdBits.markBit(event->getActionIndex());
749        clearPointers(downIdBits);
750        break;
751    }
752    case AMOTION_EVENT_ACTION_OUTSIDE:
753    case AMOTION_EVENT_ACTION_CANCEL:
754    case AMOTION_EVENT_ACTION_SCROLL:
755    case AMOTION_EVENT_ACTION_UP:
756    case AMOTION_EVENT_ACTION_POINTER_UP:
757        // Ignore these actions because they do not convey any new information about
758        // pointer movement.  We also want to preserve the last known velocity of the pointers.
759        // Note that ACTION_UP and ACTION_POINTER_UP always report the last known position
760        // of the pointers that went up.  ACTION_POINTER_UP does include the new position of
761        // pointers that remained down but we will also receive an ACTION_MOVE with this
762        // information if any of them actually moved.  Since we don't know how many pointers
763        // will be going up at once it makes sense to just wait for the following ACTION_MOVE
764        // before adding the movement.
765        return;
766    }
767
768    size_t pointerCount = event->getPointerCount();
769    if (pointerCount > MAX_POINTERS) {
770        pointerCount = MAX_POINTERS;
771    }
772
773    BitSet32 idBits;
774    for (size_t i = 0; i < pointerCount; i++) {
775        idBits.markBit(event->getPointerId(i));
776    }
777
778    nsecs_t eventTime;
779    Position positions[pointerCount];
780
781    size_t historySize = event->getHistorySize();
782    for (size_t h = 0; h < historySize; h++) {
783        eventTime = event->getHistoricalEventTime(h);
784        for (size_t i = 0; i < pointerCount; i++) {
785            positions[i].x = event->getHistoricalX(i, h);
786            positions[i].y = event->getHistoricalY(i, h);
787        }
788        addMovement(eventTime, idBits, positions);
789    }
790
791    eventTime = event->getEventTime();
792    for (size_t i = 0; i < pointerCount; i++) {
793        positions[i].x = event->getX(i);
794        positions[i].y = event->getY(i);
795    }
796    addMovement(eventTime, idBits, positions);
797}
798
799bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const {
800    const Movement& newestMovement = mMovements[mIndex];
801    if (newestMovement.idBits.hasBit(id)) {
802        // Find the oldest sample that contains the pointer and that is not older than MAX_AGE.
803        nsecs_t minTime = newestMovement.eventTime - MAX_AGE;
804        uint32_t oldestIndex = mIndex;
805        uint32_t numTouches = 1;
806        do {
807            uint32_t nextOldestIndex = (oldestIndex == 0 ? HISTORY_SIZE : oldestIndex) - 1;
808            const Movement& nextOldestMovement = mMovements[nextOldestIndex];
809            if (!nextOldestMovement.idBits.hasBit(id)
810                    || nextOldestMovement.eventTime < minTime) {
811                break;
812            }
813            oldestIndex = nextOldestIndex;
814        } while (++numTouches < HISTORY_SIZE);
815
816        // Calculate an exponentially weighted moving average of the velocity estimate
817        // at different points in time measured relative to the oldest sample.
818        // This is essentially an IIR filter.  Newer samples are weighted more heavily
819        // than older samples.  Samples at equal time points are weighted more or less
820        // equally.
821        //
822        // One tricky problem is that the sample data may be poorly conditioned.
823        // Sometimes samples arrive very close together in time which can cause us to
824        // overestimate the velocity at that time point.  Most samples might be measured
825        // 16ms apart but some consecutive samples could be only 0.5sm apart because
826        // the hardware or driver reports them irregularly or in bursts.
827        float accumVx = 0;
828        float accumVy = 0;
829        uint32_t index = oldestIndex;
830        uint32_t samplesUsed = 0;
831        const Movement& oldestMovement = mMovements[oldestIndex];
832        const Position& oldestPosition =
833                oldestMovement.positions[oldestMovement.idBits.getIndexOfBit(id)];
834        nsecs_t lastDuration = 0;
835        while (numTouches-- > 1) {
836            if (++index == HISTORY_SIZE) {
837                index = 0;
838            }
839            const Movement& movement = mMovements[index];
840            nsecs_t duration = movement.eventTime - oldestMovement.eventTime;
841
842            // If the duration between samples is small, we may significantly overestimate
843            // the velocity.  Consequently, we impose a minimum duration constraint on the
844            // samples that we include in the calculation.
845            if (duration >= MIN_DURATION) {
846                const Position& position = movement.positions[movement.idBits.getIndexOfBit(id)];
847                float scale = 1000000000.0f / duration; // one over time delta in seconds
848                float vx = (position.x - oldestPosition.x) * scale;
849                float vy = (position.y - oldestPosition.y) * scale;
850
851                accumVx = (accumVx * lastDuration + vx * duration) / (duration + lastDuration);
852                accumVy = (accumVy * lastDuration + vy * duration) / (duration + lastDuration);
853
854                lastDuration = duration;
855                samplesUsed += 1;
856            }
857        }
858
859        // Make sure we used at least one sample.
860        if (samplesUsed != 0) {
861            *outVx = accumVx;
862            *outVy = accumVy;
863            return true;
864        }
865    }
866
867    // No data available for this pointer.
868    *outVx = 0;
869    *outVy = 0;
870    return false;
871}
872
873
874// --- InputDeviceInfo ---
875
876InputDeviceInfo::InputDeviceInfo() {
877    initialize(-1, String8("uninitialized device info"));
878}
879
880InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
881        mId(other.mId), mName(other.mName), mSources(other.mSources),
882        mKeyboardType(other.mKeyboardType),
883        mMotionRanges(other.mMotionRanges) {
884}
885
886InputDeviceInfo::~InputDeviceInfo() {
887}
888
889void InputDeviceInfo::initialize(int32_t id, const String8& name) {
890    mId = id;
891    mName = name;
892    mSources = 0;
893    mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
894    mMotionRanges.clear();
895}
896
897const InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(
898        int32_t axis, uint32_t source) const {
899    size_t numRanges = mMotionRanges.size();
900    for (size_t i = 0; i < numRanges; i++) {
901        const MotionRange& range = mMotionRanges.itemAt(i);
902        if (range.axis == axis && range.source == source) {
903            return &range;
904        }
905    }
906    return NULL;
907}
908
909void InputDeviceInfo::addSource(uint32_t source) {
910    mSources |= source;
911}
912
913void InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max,
914        float flat, float fuzz) {
915    MotionRange range = { axis, source, min, max, flat, fuzz };
916    mMotionRanges.add(range);
917}
918
919void InputDeviceInfo::addMotionRange(const MotionRange& range) {
920    mMotionRanges.add(range);
921}
922
923} // namespace android
924