Input.cpp revision be1aa8250cee7819c49741e819e81659d1d03823
146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown//
246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// Copyright 2010 The Android Open Source Project
346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown//
446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown// Provides a pipe-based transport for native events in the NDK.
546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown//
646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#define LOG_TAG "Input"
746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown//#define LOG_NDEBUG 0
946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
10ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown// Log debug messages about keymap probing.
1147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#define DEBUG_PROBE 0
1247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
13ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown// Log debug messages about velocity tracking.
14ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown#define DEBUG_VELOCITY 0
15ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
1619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown// Log debug messages about acceleration.
1719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#define DEBUG_ACCELERATION 0
1819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
1919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
2047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#include <stdlib.h>
2147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#include <unistd.h>
229065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#include <ctype.h>
2347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
2446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include <ui/Input.h>
2546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
2691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#include <math.h>
2719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#include <limits.h>
2891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
2991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#ifdef HAVE_ANDROID_OS
3091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#include <binder/Parcel.h>
3191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
3291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#include "SkPoint.h"
3391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#include "SkMatrix.h"
3491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#include "SkScalar.h"
3591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#endif
3691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
3746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownnamespace android {
3846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
3947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownstatic const char* CONFIGURATION_FILE_DIR[] = {
4047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        "idc/",
4147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        "keylayout/",
4247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        "keychars/",
4347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown};
4447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
4547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownstatic const char* CONFIGURATION_FILE_EXTENSION[] = {
4647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        ".idc",
4747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        ".kl",
4847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        ".kcm",
4947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown};
5047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
519065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brownstatic bool isValidNameChar(char ch) {
529065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown    return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_');
539065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown}
549065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown
5547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownstatic void appendInputDeviceConfigurationFileRelativePath(String8& path,
5647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        const String8& name, InputDeviceConfigurationFileType type) {
5747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    path.append(CONFIGURATION_FILE_DIR[type]);
5847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    for (size_t i = 0; i < name.length(); i++) {
5947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        char ch = name[i];
609065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        if (!isValidNameChar(ch)) {
6147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown            ch = '_';
6247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        }
6347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        path.append(&ch, 1);
6447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    }
6547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    path.append(CONFIGURATION_FILE_EXTENSION[type]);
6647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown}
6747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
689065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff BrownString8 getInputDeviceConfigurationFilePathByDeviceIdentifier(
699065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        const InputDeviceIdentifier& deviceIdentifier,
709065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        InputDeviceConfigurationFileType type) {
719065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown    if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
729065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        if (deviceIdentifier.version != 0) {
739065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown            // Try vendor product version.
749065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown            String8 versionPath(getInputDeviceConfigurationFilePathByName(
759065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                    String8::format("Vendor_%04x_Product_%04x_Version_%04x",
769065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                            deviceIdentifier.vendor, deviceIdentifier.product,
779065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                            deviceIdentifier.version),
789065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                    type));
799065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown            if (!versionPath.isEmpty()) {
809065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                return versionPath;
819065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown            }
829065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        }
839065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown
849065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        // Try vendor product.
859065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        String8 productPath(getInputDeviceConfigurationFilePathByName(
869065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                String8::format("Vendor_%04x_Product_%04x",
879065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                        deviceIdentifier.vendor, deviceIdentifier.product),
889065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                type));
899065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        if (!productPath.isEmpty()) {
909065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown            return productPath;
919065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        }
929065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown    }
939065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown
949065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown    // Try device name.
959065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown    return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type);
969065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown}
979065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown
989065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff BrownString8 getInputDeviceConfigurationFilePathByName(
9947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        const String8& name, InputDeviceConfigurationFileType type) {
10047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    // Search system repository.
10147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    String8 path;
10247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    path.setTo(getenv("ANDROID_ROOT"));
10347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    path.append("/usr/");
10447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    appendInputDeviceConfigurationFileRelativePath(path, name, type);
10547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#if DEBUG_PROBE
10647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    LOGD("Probing for system provided input device configuration file: path='%s'", path.string());
10747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#endif
10847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    if (!access(path.string(), R_OK)) {
10947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#if DEBUG_PROBE
11047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        LOGD("Found");
11147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#endif
11247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        return path;
11347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    }
11447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
11547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    // Search user repository.
11647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    // TODO Should only look here if not in safe mode.
11747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    path.setTo(getenv("ANDROID_DATA"));
11847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    path.append("/system/devices/");
11947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    appendInputDeviceConfigurationFileRelativePath(path, name, type);
12047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#if DEBUG_PROBE
12147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    LOGD("Probing for system user input device configuration file: path='%s'", path.string());
12247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#endif
12347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    if (!access(path.string(), R_OK)) {
12447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#if DEBUG_PROBE
12547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        LOGD("Found");
12647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#endif
12747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        return path;
12847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    }
12947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
13047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    // Not found.
13147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#if DEBUG_PROBE
13247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    LOGD("Probe failed to find input device configuration file: name='%s', type=%d",
13347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown            name.string(), type);
13447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#endif
13547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    return String8();
13647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown}
13747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
13847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
13947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown// --- InputEvent ---
14046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
141c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brownvoid InputEvent::initialize(int32_t deviceId, int32_t source) {
14246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mDeviceId = deviceId;
143c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    mSource = source;
14446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
14546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
1462c6081ce3593712f30dacd990a97209c791d6cedDianne Hackbornvoid InputEvent::initialize(const InputEvent& from) {
1472c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mDeviceId = from.mDeviceId;
1482c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mSource = from.mSource;
1492c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn}
1502c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn
15147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown// --- KeyEvent ---
15246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
1533c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackbornbool KeyEvent::hasDefaultAction(int32_t keyCode) {
1543c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    switch (keyCode) {
155fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_HOME:
156fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_BACK:
157fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_CALL:
158fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_ENDCALL:
159fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_VOLUME_UP:
160fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_VOLUME_DOWN:
161b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_VOLUME_MUTE:
162fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_POWER:
163fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_CAMERA:
164fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_HEADSETHOOK:
165fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MENU:
166fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_NOTIFICATION:
167fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_FOCUS:
168fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_SEARCH:
169b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_MEDIA_PLAY:
170b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_MEDIA_PAUSE:
171fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_PLAY_PAUSE:
172fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_STOP:
173fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_NEXT:
174fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_PREVIOUS:
175fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_REWIND:
176b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_MEDIA_RECORD:
177fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_FAST_FORWARD:
178fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MUTE:
1793c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn            return true;
1803c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    }
1813c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
1823c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    return false;
1833c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn}
1843c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
1853c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackbornbool KeyEvent::hasDefaultAction() const {
1863c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    return hasDefaultAction(getKeyCode());
1873c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn}
1883c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
1893c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackbornbool KeyEvent::isSystemKey(int32_t keyCode) {
1903c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    switch (keyCode) {
191fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MENU:
192fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_SOFT_RIGHT:
193fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_HOME:
194fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_BACK:
195fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_CALL:
196fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_ENDCALL:
197fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_VOLUME_UP:
198fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_VOLUME_DOWN:
199b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_VOLUME_MUTE:
200fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MUTE:
201fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_POWER:
202fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_HEADSETHOOK:
203b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_MEDIA_PLAY:
204b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_MEDIA_PAUSE:
205fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_PLAY_PAUSE:
206fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_STOP:
207fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_NEXT:
208fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_PREVIOUS:
209fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_REWIND:
210b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_MEDIA_RECORD:
211fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_FAST_FORWARD:
212fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_CAMERA:
213fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_FOCUS:
214fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_SEARCH:
2153c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn            return true;
2163c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    }
2173c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
2183c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    return false;
2193c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn}
2203c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
2213c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackbornbool KeyEvent::isSystemKey() const {
2223c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    return isSystemKey(getKeyCode());
2233c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn}
2243c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
22546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownvoid KeyEvent::initialize(
22646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t deviceId,
227c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown        int32_t source,
22846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t action,
22946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t flags,
23046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t keyCode,
23146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t scanCode,
23246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t metaState,
23346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t repeatCount,
23446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        nsecs_t downTime,
23546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        nsecs_t eventTime) {
236c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    InputEvent::initialize(deviceId, source);
23746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mAction = action;
23846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mFlags = flags;
23946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mKeyCode = keyCode;
24046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mScanCode = scanCode;
24146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mMetaState = metaState;
24246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mRepeatCount = repeatCount;
24346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mDownTime = downTime;
24446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mEventTime = eventTime;
24546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
24646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
2472c6081ce3593712f30dacd990a97209c791d6cedDianne Hackbornvoid KeyEvent::initialize(const KeyEvent& from) {
2482c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    InputEvent::initialize(from);
2492c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mAction = from.mAction;
2502c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mFlags = from.mFlags;
2512c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mKeyCode = from.mKeyCode;
2522c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mScanCode = from.mScanCode;
2532c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mMetaState = from.mMetaState;
2542c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mRepeatCount = from.mRepeatCount;
2552c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mDownTime = from.mDownTime;
2562c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mEventTime = from.mEventTime;
2572c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn}
2582c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn
25991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
26091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown// --- PointerCoords ---
26191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
2626f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brownfloat PointerCoords::getAxisValue(int32_t axis) const {
2636f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    if (axis < 0 || axis > 63) {
2646f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        return 0;
2656f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    }
2666f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown
2676f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    uint64_t axisBit = 1LL << axis;
2686f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    if (!(bits & axisBit)) {
2696f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        return 0;
2706f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    }
2716f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
2726f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    return values[index];
2736f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown}
2746f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown
2756f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brownstatus_t PointerCoords::setAxisValue(int32_t axis, float value) {
2766f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    if (axis < 0 || axis > 63) {
2776f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        return NAME_NOT_FOUND;
2786f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    }
2796f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown
2806f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    uint64_t axisBit = 1LL << axis;
2816f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
2826f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    if (!(bits & axisBit)) {
283be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        if (value == 0) {
284be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown            return OK; // axes with value 0 do not need to be stored
285be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        }
2866f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        uint32_t count = __builtin_popcountll(bits);
2876f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        if (count >= MAX_AXES) {
2886f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown            tooManyAxes(axis);
2896f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown            return NO_MEMORY;
2906f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        }
2916f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        bits |= axisBit;
2926f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        for (uint32_t i = count; i > index; i--) {
2936f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown            values[i] = values[i - 1];
2946f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        }
2956f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    }
2966f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    values[index] = value;
2976f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    return OK;
2986f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown}
2996f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown
300e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackbornstatic inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) {
301be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown    float value = c.getAxisValue(axis);
302be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown    if (value != 0) {
303be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        c.setAxisValue(axis, value * scaleFactor);
304e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
305e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn}
306e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
307e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackbornvoid PointerCoords::scale(float scaleFactor) {
308e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    // No need to scale pressure or size since they are normalized.
309e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    // No need to scale orientation since it is meaningless to do so.
310e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    scaleAxisValue(*this, AMOTION_EVENT_AXIS_X, scaleFactor);
311e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    scaleAxisValue(*this, AMOTION_EVENT_AXIS_Y, scaleFactor);
312e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MAJOR, scaleFactor);
313e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MINOR, scaleFactor);
314e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MAJOR, scaleFactor);
315e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor);
316e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn}
317e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
31891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#ifdef HAVE_ANDROID_OS
31991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownstatus_t PointerCoords::readFromParcel(Parcel* parcel) {
3206f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    bits = parcel->readInt64();
32191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
3226f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    uint32_t count = __builtin_popcountll(bits);
32391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    if (count > MAX_AXES) {
32491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        return BAD_VALUE;
32591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
32691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
32791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    for (uint32_t i = 0; i < count; i++) {
32891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        values[i] = parcel->readInt32();
32991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
33091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return OK;
33191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
33291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
33391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownstatus_t PointerCoords::writeToParcel(Parcel* parcel) const {
3346f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    parcel->writeInt64(bits);
33591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
3366f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    uint32_t count = __builtin_popcountll(bits);
33791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    for (uint32_t i = 0; i < count; i++) {
33891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        parcel->writeInt32(values[i]);
33991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
34091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return OK;
34191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
34291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#endif
34391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
34491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownvoid PointerCoords::tooManyAxes(int axis) {
34591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    LOGW("Could not set value for axis %d because the PointerCoords structure is full and "
34691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown            "cannot contain more than %d axis values.", axis, int(MAX_AXES));
34791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
34891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
349ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brownbool PointerCoords::operator==(const PointerCoords& other) const {
350ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    if (bits != other.bits) {
351ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        return false;
352ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    }
353ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    uint32_t count = __builtin_popcountll(bits);
354ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    for (uint32_t i = 0; i < count; i++) {
355ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        if (values[i] != other.values[i]) {
356ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            return false;
357ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        }
358ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    }
359ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    return true;
360ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown}
361ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
362ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brownvoid PointerCoords::copyFrom(const PointerCoords& other) {
363ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    bits = other.bits;
364ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    uint32_t count = __builtin_popcountll(bits);
365ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    for (uint32_t i = 0; i < count; i++) {
366ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        values[i] = other.values[i];
367ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    }
368ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown}
369ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
37091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
371fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown// --- PointerProperties ---
372fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown
373fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brownbool PointerProperties::operator==(const PointerProperties& other) const {
374fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    return id == other.id
375fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown            && toolType == other.toolType;
376fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown}
377fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown
378fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brownvoid PointerProperties::copyFrom(const PointerProperties& other) {
379fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    id = other.id;
380fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    toolType = other.toolType;
381fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown}
382fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown
383fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown
38447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown// --- MotionEvent ---
38546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
38646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownvoid MotionEvent::initialize(
38746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t deviceId,
388c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown        int32_t source,
38946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t action,
39085a3176704b5bfbeece9bd928369fbb76eec7dc6Jeff Brown        int32_t flags,
39146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t edgeFlags,
39246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t metaState,
393fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        int32_t buttonState,
3945c225b1680e696ae8bbf505a1997d6f720672f74Jeff Brown        float xOffset,
3955c225b1680e696ae8bbf505a1997d6f720672f74Jeff Brown        float yOffset,
39646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        float xPrecision,
39746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        float yPrecision,
39846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        nsecs_t downTime,
39946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        nsecs_t eventTime,
40046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        size_t pointerCount,
401fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        const PointerProperties* pointerProperties,
40246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        const PointerCoords* pointerCoords) {
403c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    InputEvent::initialize(deviceId, source);
40446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mAction = action;
40585a3176704b5bfbeece9bd928369fbb76eec7dc6Jeff Brown    mFlags = flags;
40646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mEdgeFlags = edgeFlags;
40746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mMetaState = metaState;
408fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mButtonState = buttonState;
4095c225b1680e696ae8bbf505a1997d6f720672f74Jeff Brown    mXOffset = xOffset;
4105c225b1680e696ae8bbf505a1997d6f720672f74Jeff Brown    mYOffset = yOffset;
41146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mXPrecision = xPrecision;
41246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mYPrecision = yPrecision;
41346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mDownTime = downTime;
414fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mPointerProperties.clear();
415fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mPointerProperties.appendArray(pointerProperties, pointerCount);
41646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mSampleEventTimes.clear();
41746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mSamplePointerCoords.clear();
41846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    addSample(eventTime, pointerCoords);
41946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
42046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
42191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownvoid MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
42291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    InputEvent::initialize(other->mDeviceId, other->mSource);
42391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mAction = other->mAction;
42491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mFlags = other->mFlags;
42591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mEdgeFlags = other->mEdgeFlags;
42691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mMetaState = other->mMetaState;
427fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mButtonState = other->mButtonState;
42891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mXOffset = other->mXOffset;
42991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mYOffset = other->mYOffset;
43091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mXPrecision = other->mXPrecision;
43191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mYPrecision = other->mYPrecision;
43291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mDownTime = other->mDownTime;
433fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mPointerProperties = other->mPointerProperties;
43491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
43591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    if (keepHistory) {
43691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        mSampleEventTimes = other->mSampleEventTimes;
43791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        mSamplePointerCoords = other->mSamplePointerCoords;
43891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    } else {
43991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        mSampleEventTimes.clear();
44091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        mSampleEventTimes.push(other->getEventTime());
44191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        mSamplePointerCoords.clear();
44291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        size_t pointerCount = other->getPointerCount();
44391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        size_t historySize = other->getHistorySize();
44491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array()
44591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown                + (historySize * pointerCount), pointerCount);
44691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
44791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
44891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
44946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownvoid MotionEvent::addSample(
45046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int64_t eventTime,
45146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        const PointerCoords* pointerCoords) {
45246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mSampleEventTimes.push(eventTime);
45346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
45446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
45546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
45691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownconst PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
45791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
45891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
45991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
46091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownfloat MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
46191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
46291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
46391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
46491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownfloat MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const {
46591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis);
46691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    switch (axis) {
467ebbd5d14ad3b1e762d9fcfa026e19413cc857e05Jeff Brown    case AMOTION_EVENT_AXIS_X:
468e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return value + mXOffset;
469ebbd5d14ad3b1e762d9fcfa026e19413cc857e05Jeff Brown    case AMOTION_EVENT_AXIS_Y:
470e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return value + mYOffset;
47191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
47291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return value;
47391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
47491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
47591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownconst PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
47691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        size_t pointerIndex, size_t historicalIndex) const {
47791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
47891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
47991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
48091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownfloat MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
48191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        size_t historicalIndex) const {
48291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
48391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
48491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
48591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownfloat MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
48691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        size_t historicalIndex) const {
48791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
48891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    switch (axis) {
489ebbd5d14ad3b1e762d9fcfa026e19413cc857e05Jeff Brown    case AMOTION_EVENT_AXIS_X:
490e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return value + mXOffset;
491ebbd5d14ad3b1e762d9fcfa026e19413cc857e05Jeff Brown    case AMOTION_EVENT_AXIS_Y:
492e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return value + mYOffset;
49391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
49491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return value;
49591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
49691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
4972ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
498fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    size_t pointerCount = mPointerProperties.size();
4992ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    for (size_t i = 0; i < pointerCount; i++) {
500fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        if (mPointerProperties.itemAt(i).id == pointerId) {
5012ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            return i;
5022ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        }
5032ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
5042ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    return -1;
5052ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
5062ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
50746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownvoid MotionEvent::offsetLocation(float xOffset, float yOffset) {
5085c225b1680e696ae8bbf505a1997d6f720672f74Jeff Brown    mXOffset += xOffset;
5095c225b1680e696ae8bbf505a1997d6f720672f74Jeff Brown    mYOffset += yOffset;
51046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
51146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
51291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownvoid MotionEvent::scale(float scaleFactor) {
51391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mXOffset *= scaleFactor;
51491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mYOffset *= scaleFactor;
51591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mXPrecision *= scaleFactor;
51691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mYPrecision *= scaleFactor;
51791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
51891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    size_t numSamples = mSamplePointerCoords.size();
51991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    for (size_t i = 0; i < numSamples; i++) {
520e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        mSamplePointerCoords.editItemAt(i).scale(scaleFactor);
52191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
52291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
52391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
52491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#ifdef HAVE_ANDROID_OS
52591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownstatic inline float transformAngle(const SkMatrix* matrix, float angleRadians) {
52691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    // Construct and transform a vector oriented at the specified clockwise angle from vertical.
52791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    // Coordinate system: down is increasing Y, right is increasing X.
52891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    SkPoint vector;
52991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    vector.fX = SkFloatToScalar(sinf(angleRadians));
53091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    vector.fY = SkFloatToScalar(-cosf(angleRadians));
53191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    matrix->mapVectors(& vector, 1);
53291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
53391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    // Derive the transformed vector's clockwise angle from vertical.
53491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY));
53591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    if (result < - M_PI_2) {
53691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        result += M_PI;
53791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    } else if (result > M_PI_2) {
53891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        result -= M_PI;
53991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
54091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return result;
54191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
54291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
54391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownvoid MotionEvent::transform(const SkMatrix* matrix) {
54491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float oldXOffset = mXOffset;
54591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float oldYOffset = mYOffset;
54691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
54791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    // The tricky part of this implementation is to preserve the value of
54891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    // rawX and rawY.  So we apply the transformation to the first point
54991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    // then derive an appropriate new X/Y offset that will preserve rawX and rawY.
55091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    SkPoint point;
55191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float rawX = getRawX(0);
55291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float rawY = getRawY(0);
55391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset),
55491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown            & point);
55591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float newX = SkScalarToFloat(point.fX);
55691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float newY = SkScalarToFloat(point.fY);
55791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float newXOffset = newX - rawX;
55891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float newYOffset = newY - rawY;
55991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
56091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mXOffset = newXOffset;
56191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mYOffset = newYOffset;
56291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
56391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    // Apply the transformation to all samples.
56491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    size_t numSamples = mSamplePointerCoords.size();
56591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    for (size_t i = 0; i < numSamples; i++) {
56691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        PointerCoords& c = mSamplePointerCoords.editItemAt(i);
567be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset;
568be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset;
569be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), &point);
570be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        c.setAxisValue(AMOTION_EVENT_AXIS_X, SkScalarToFloat(point.fX) - newXOffset);
571be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        c.setAxisValue(AMOTION_EVENT_AXIS_Y, SkScalarToFloat(point.fY) - newYOffset);
57291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
573be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
574be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(matrix, orientation));
57591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
57691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
57791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
57891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownstatus_t MotionEvent::readFromParcel(Parcel* parcel) {
57991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    size_t pointerCount = parcel->readInt32();
58091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    size_t sampleCount = parcel->readInt32();
58191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) {
58291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        return BAD_VALUE;
58391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
58491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
58591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mDeviceId = parcel->readInt32();
58691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mSource = parcel->readInt32();
58791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mAction = parcel->readInt32();
58891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mFlags = parcel->readInt32();
58991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mEdgeFlags = parcel->readInt32();
59091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mMetaState = parcel->readInt32();
591fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mButtonState = parcel->readInt32();
59291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mXOffset = parcel->readFloat();
59391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mYOffset = parcel->readFloat();
59491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mXPrecision = parcel->readFloat();
59591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mYPrecision = parcel->readFloat();
59691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mDownTime = parcel->readInt64();
59791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
598fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mPointerProperties.clear();
599fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mPointerProperties.setCapacity(pointerCount);
60091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mSampleEventTimes.clear();
60191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mSampleEventTimes.setCapacity(sampleCount);
60291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mSamplePointerCoords.clear();
60391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
60491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
60591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    for (size_t i = 0; i < pointerCount; i++) {
606fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        mPointerProperties.push();
607fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        PointerProperties& properties = mPointerProperties.editTop();
608fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        properties.id = parcel->readInt32();
609fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        properties.toolType = parcel->readInt32();
61091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
61191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
61291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    while (sampleCount-- > 0) {
61391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        mSampleEventTimes.push(parcel->readInt64());
61491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        for (size_t i = 0; i < pointerCount; i++) {
61591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown            mSamplePointerCoords.push();
61691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown            status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel);
617ebbd5d14ad3b1e762d9fcfa026e19413cc857e05Jeff Brown            if (status) {
61891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown                return status;
61991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown            }
62091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        }
62191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
62291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return OK;
62391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
62491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
62591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownstatus_t MotionEvent::writeToParcel(Parcel* parcel) const {
626fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    size_t pointerCount = mPointerProperties.size();
62791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    size_t sampleCount = mSampleEventTimes.size();
62891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
62991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(pointerCount);
63091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(sampleCount);
63191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
63291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(mDeviceId);
63391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(mSource);
63491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(mAction);
63591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(mFlags);
63691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(mEdgeFlags);
63791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(mMetaState);
638fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    parcel->writeInt32(mButtonState);
63991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeFloat(mXOffset);
64091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeFloat(mYOffset);
64191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeFloat(mXPrecision);
64291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeFloat(mYPrecision);
64391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt64(mDownTime);
64491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
64591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    for (size_t i = 0; i < pointerCount; i++) {
646fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        const PointerProperties& properties = mPointerProperties.itemAt(i);
647fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        parcel->writeInt32(properties.id);
648fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        parcel->writeInt32(properties.toolType);
64991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
65091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
65191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    const PointerCoords* pc = mSamplePointerCoords.array();
65291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    for (size_t h = 0; h < sampleCount; h++) {
65391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        parcel->writeInt64(mSampleEventTimes.itemAt(h));
65491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        for (size_t i = 0; i < pointerCount; i++) {
65591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown            status_t status = (pc++)->writeToParcel(parcel);
656ebbd5d14ad3b1e762d9fcfa026e19413cc857e05Jeff Brown            if (status) {
65791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown                return status;
65891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown            }
65991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        }
66091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
66191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return OK;
66291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
66391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#endif
66491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
66556194ebec6212e229f4ccdaa4b187166d20013efJeff Brownbool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
66656194ebec6212e229f4ccdaa4b187166d20013efJeff Brown    if (source & AINPUT_SOURCE_CLASS_POINTER) {
66756194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        // Specifically excludes HOVER_MOVE and SCROLL.
66856194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        switch (action & AMOTION_EVENT_ACTION_MASK) {
66956194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        case AMOTION_EVENT_ACTION_DOWN:
67056194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        case AMOTION_EVENT_ACTION_MOVE:
67156194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        case AMOTION_EVENT_ACTION_UP:
67256194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        case AMOTION_EVENT_ACTION_POINTER_DOWN:
67356194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        case AMOTION_EVENT_ACTION_POINTER_UP:
67456194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        case AMOTION_EVENT_ACTION_CANCEL:
67556194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        case AMOTION_EVENT_ACTION_OUTSIDE:
67656194ebec6212e229f4ccdaa4b187166d20013efJeff Brown            return true;
67756194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        }
67856194ebec6212e229f4ccdaa4b187166d20013efJeff Brown    }
67956194ebec6212e229f4ccdaa4b187166d20013efJeff Brown    return false;
68056194ebec6212e229f4ccdaa4b187166d20013efJeff Brown}
68156194ebec6212e229f4ccdaa4b187166d20013efJeff Brown
68291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
683ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown// --- VelocityTracker ---
684ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
68519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brownconst uint32_t VelocityTracker::HISTORY_SIZE;
68619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brownconst nsecs_t VelocityTracker::MAX_AGE;
68719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brownconst nsecs_t VelocityTracker::MIN_DURATION;
68819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
689ace13b17866dc9136aeecf6dfaf7077f37434469Jeff BrownVelocityTracker::VelocityTracker() {
690ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    clear();
691ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown}
692ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
693ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brownvoid VelocityTracker::clear() {
694ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    mIndex = 0;
695ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    mMovements[0].idBits.clear();
6962ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    mActivePointerId = -1;
6972ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
6982ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
6992ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownvoid VelocityTracker::clearPointers(BitSet32 idBits) {
7002ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    BitSet32 remainingIdBits(mMovements[mIndex].idBits.value & ~idBits.value);
7012ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    mMovements[mIndex].idBits = remainingIdBits;
7022ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
7032ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    if (mActivePointerId >= 0 && idBits.hasBit(mActivePointerId)) {
7042ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        mActivePointerId = !remainingIdBits.isEmpty() ? remainingIdBits.firstMarkedBit() : -1;
7052ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
706ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown}
707ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
708ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brownvoid VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions) {
709ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    if (++mIndex == HISTORY_SIZE) {
710ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        mIndex = 0;
711ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    }
7122ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
7132ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    while (idBits.count() > MAX_POINTERS) {
714be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        idBits.clearLastMarkedBit();
7152ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
7162ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
717ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    Movement& movement = mMovements[mIndex];
718ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    movement.eventTime = eventTime;
719ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    movement.idBits = idBits;
720ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    uint32_t count = idBits.count();
721ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    for (uint32_t i = 0; i < count; i++) {
722ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        movement.positions[i] = positions[i];
723ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    }
724ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
7252ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    if (mActivePointerId < 0 || !idBits.hasBit(mActivePointerId)) {
7262ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        mActivePointerId = count != 0 ? idBits.firstMarkedBit() : -1;
7272ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
7282ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
729ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown#if DEBUG_VELOCITY
7302ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    LOGD("VelocityTracker: addMovement eventTime=%lld, idBits=0x%08x, activePointerId=%d",
7312ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            eventTime, idBits.value, mActivePointerId);
732ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    for (BitSet32 iterBits(idBits); !iterBits.isEmpty(); ) {
733ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        uint32_t id = iterBits.firstMarkedBit();
734ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        uint32_t index = idBits.getIndexOfBit(id);
735ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        iterBits.clearBit(id);
736ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        float vx, vy;
737ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        bool available = getVelocity(id, &vx, &vy);
738ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        if (available) {
7392ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            LOGD("  %d: position (%0.3f, %0.3f), vx=%0.3f, vy=%0.3f, speed=%0.3f",
740ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown                    id, positions[index].x, positions[index].y, vx, vy, sqrtf(vx * vx + vy * vy));
741ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        } else {
742b6110c2de0cd7950360aeb2c248a44e4ea5f33f5Jeff Brown            LOG_ASSERT(vx == 0 && vy == 0);
743ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            LOGD("  %d: position (%0.3f, %0.3f), velocity not available",
744ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown                    id, positions[index].x, positions[index].y);
745ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        }
746ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    }
747ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown#endif
748ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown}
749ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
7502ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownvoid VelocityTracker::addMovement(const MotionEvent* event) {
7512ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    int32_t actionMasked = event->getActionMasked();
7522ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
7532ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    switch (actionMasked) {
7542ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    case AMOTION_EVENT_ACTION_DOWN:
7552ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // Clear all pointers on down before adding the new movement.
7562ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        clear();
7572ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        break;
7582ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    case AMOTION_EVENT_ACTION_POINTER_DOWN: {
7592ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // Start a new movement trace for a pointer that just went down.
7602ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // We do this on down instead of on up because the client may want to query the
7612ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // final velocity for a pointer that just went up.
7622ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        BitSet32 downIdBits;
763be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        downIdBits.markBit(event->getPointerId(event->getActionIndex()));
7642ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        clearPointers(downIdBits);
7652ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        break;
7662ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
7672ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    case AMOTION_EVENT_ACTION_OUTSIDE:
7682ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    case AMOTION_EVENT_ACTION_CANCEL:
7692ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    case AMOTION_EVENT_ACTION_SCROLL:
7702ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    case AMOTION_EVENT_ACTION_UP:
7712ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    case AMOTION_EVENT_ACTION_POINTER_UP:
7722ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // Ignore these actions because they do not convey any new information about
7732ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // pointer movement.  We also want to preserve the last known velocity of the pointers.
7742ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // Note that ACTION_UP and ACTION_POINTER_UP always report the last known position
7752ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // of the pointers that went up.  ACTION_POINTER_UP does include the new position of
7762ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // pointers that remained down but we will also receive an ACTION_MOVE with this
7772ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // information if any of them actually moved.  Since we don't know how many pointers
7782ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // will be going up at once it makes sense to just wait for the following ACTION_MOVE
7792ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // before adding the movement.
7802ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        return;
7812ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
7822ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
7832ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    size_t pointerCount = event->getPointerCount();
7842ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    if (pointerCount > MAX_POINTERS) {
7852ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        pointerCount = MAX_POINTERS;
7862ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
7872ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
7882ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    BitSet32 idBits;
7892ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    for (size_t i = 0; i < pointerCount; i++) {
7902ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        idBits.markBit(event->getPointerId(i));
7912ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
7922ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
7932ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    nsecs_t eventTime;
7942ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    Position positions[pointerCount];
7952ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
7962ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    size_t historySize = event->getHistorySize();
7972ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    for (size_t h = 0; h < historySize; h++) {
7982ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        eventTime = event->getHistoricalEventTime(h);
7992ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        for (size_t i = 0; i < pointerCount; i++) {
8002ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            positions[i].x = event->getHistoricalX(i, h);
8012ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            positions[i].y = event->getHistoricalY(i, h);
8022ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        }
8032ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        addMovement(eventTime, idBits, positions);
8042ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
8052ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
8062ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    eventTime = event->getEventTime();
8072ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    for (size_t i = 0; i < pointerCount; i++) {
8082ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        positions[i].x = event->getX(i);
8092ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        positions[i].y = event->getY(i);
8102ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
8112ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    addMovement(eventTime, idBits, positions);
8122ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
8132ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
814ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brownbool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const {
815ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    const Movement& newestMovement = mMovements[mIndex];
816ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    if (newestMovement.idBits.hasBit(id)) {
817ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        // Find the oldest sample that contains the pointer and that is not older than MAX_AGE.
818ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        nsecs_t minTime = newestMovement.eventTime - MAX_AGE;
819ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        uint32_t oldestIndex = mIndex;
820ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        uint32_t numTouches = 1;
821ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        do {
822ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            uint32_t nextOldestIndex = (oldestIndex == 0 ? HISTORY_SIZE : oldestIndex) - 1;
823ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            const Movement& nextOldestMovement = mMovements[nextOldestIndex];
824ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            if (!nextOldestMovement.idBits.hasBit(id)
825ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown                    || nextOldestMovement.eventTime < minTime) {
826ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown                break;
827ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            }
828ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            oldestIndex = nextOldestIndex;
829ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        } while (++numTouches < HISTORY_SIZE);
830ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
8312ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // Calculate an exponentially weighted moving average of the velocity estimate
8322ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // at different points in time measured relative to the oldest sample.
8332ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // This is essentially an IIR filter.  Newer samples are weighted more heavily
8342ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // than older samples.  Samples at equal time points are weighted more or less
8352ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // equally.
836ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        //
8372ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // One tricky problem is that the sample data may be poorly conditioned.
838ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        // Sometimes samples arrive very close together in time which can cause us to
839ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        // overestimate the velocity at that time point.  Most samples might be measured
8402ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // 16ms apart but some consecutive samples could be only 0.5sm apart because
8412ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // the hardware or driver reports them irregularly or in bursts.
842ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        float accumVx = 0;
843ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        float accumVy = 0;
844ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        uint32_t index = oldestIndex;
845ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        uint32_t samplesUsed = 0;
846ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        const Movement& oldestMovement = mMovements[oldestIndex];
847ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        const Position& oldestPosition =
848ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown                oldestMovement.positions[oldestMovement.idBits.getIndexOfBit(id)];
8492ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        nsecs_t lastDuration = 0;
8502352b978a3c94cd88f41d0d908f961333fdac1e9Jeff Brown
851ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        while (numTouches-- > 1) {
852ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            if (++index == HISTORY_SIZE) {
853ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown                index = 0;
854ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            }
855ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            const Movement& movement = mMovements[index];
856ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            nsecs_t duration = movement.eventTime - oldestMovement.eventTime;
8572ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
8582ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            // If the duration between samples is small, we may significantly overestimate
8592ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            // the velocity.  Consequently, we impose a minimum duration constraint on the
8602ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            // samples that we include in the calculation.
8612ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            if (duration >= MIN_DURATION) {
862ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown                const Position& position = movement.positions[movement.idBits.getIndexOfBit(id)];
863ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown                float scale = 1000000000.0f / duration; // one over time delta in seconds
864ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown                float vx = (position.x - oldestPosition.x) * scale;
865ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown                float vy = (position.y - oldestPosition.y) * scale;
8662ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
8672ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown                accumVx = (accumVx * lastDuration + vx * duration) / (duration + lastDuration);
8682ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown                accumVy = (accumVy * lastDuration + vy * duration) / (duration + lastDuration);
8692ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
8702ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown                lastDuration = duration;
871ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown                samplesUsed += 1;
872ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            }
873ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        }
874ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
875ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        // Make sure we used at least one sample.
876ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        if (samplesUsed != 0) {
877ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            *outVx = accumVx;
878ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            *outVy = accumVy;
879ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            return true;
880ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        }
881ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    }
882ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
883ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    // No data available for this pointer.
884ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    *outVx = 0;
885ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    *outVy = 0;
886ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    return false;
887ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown}
888ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
889ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
89019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown// --- VelocityControl ---
89119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
89219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brownconst nsecs_t VelocityControl::STOP_TIME;
89319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
89419c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff BrownVelocityControl::VelocityControl() {
89519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    reset();
89619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown}
89719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
89819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brownvoid VelocityControl::setParameters(const VelocityControlParameters& parameters) {
89919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    mParameters = parameters;
90019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    reset();
90119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown}
90219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
90319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brownvoid VelocityControl::reset() {
90419c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    mLastMovementTime = LLONG_MIN;
90519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    mRawPosition.x = 0;
90619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    mRawPosition.y = 0;
90719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    mVelocityTracker.clear();
90819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown}
90919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
91019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brownvoid VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) {
91119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    if ((deltaX && *deltaX) || (deltaY && *deltaY)) {
91219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        if (eventTime >= mLastMovementTime + STOP_TIME) {
91319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#if DEBUG_ACCELERATION
91419c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            LOGD("VelocityControl: stopped, last movement was %0.3fms ago",
91519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                    (eventTime - mLastMovementTime) * 0.000001f);
91619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#endif
91719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            reset();
91819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        }
91919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
92019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        mLastMovementTime = eventTime;
92119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        if (deltaX) {
92219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            mRawPosition.x += *deltaX;
92319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        }
92419c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        if (deltaY) {
92519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            mRawPosition.y += *deltaY;
92619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        }
92719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        mVelocityTracker.addMovement(eventTime, BitSet32(BitSet32::valueForBit(0)), &mRawPosition);
92819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
92919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        float vx, vy;
93019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        float scale = mParameters.scale;
93119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        if (mVelocityTracker.getVelocity(0, &vx, &vy)) {
93219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            float speed = hypotf(vx, vy) * scale;
93319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            if (speed >= mParameters.highThreshold) {
93419c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                // Apply full acceleration above the high speed threshold.
93519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                scale *= mParameters.acceleration;
93619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            } else if (speed > mParameters.lowThreshold) {
93719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                // Linearly interpolate the acceleration to apply between the low and high
93819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                // speed thresholds.
93919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                scale *= 1 + (speed - mParameters.lowThreshold)
94019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                        / (mParameters.highThreshold - mParameters.lowThreshold)
94119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                        * (mParameters.acceleration - 1);
94219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            }
94319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
94419c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#if DEBUG_ACCELERATION
94519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            LOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): "
94619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                    "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f",
94719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                    mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
94819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                    mParameters.acceleration,
94919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                    vx, vy, speed, scale / mParameters.scale);
95019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#endif
95119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        } else {
95219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#if DEBUG_ACCELERATION
95319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            LOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity",
95419c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                    mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
95519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                    mParameters.acceleration);
95619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#endif
95719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        }
95819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
95919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        if (deltaX) {
96019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            *deltaX *= scale;
96119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        }
96219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        if (deltaY) {
96319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            *deltaY *= scale;
96419c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        }
96519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    }
96619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown}
96719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
96819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
96947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown// --- InputDeviceInfo ---
9706d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
9716d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff BrownInputDeviceInfo::InputDeviceInfo() {
9726d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    initialize(-1, String8("uninitialized device info"));
9736d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
9746d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
9756d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff BrownInputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
9766d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown        mId(other.mId), mName(other.mName), mSources(other.mSources),
9776d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown        mKeyboardType(other.mKeyboardType),
9786d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown        mMotionRanges(other.mMotionRanges) {
9796d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
9806d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
9816d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff BrownInputDeviceInfo::~InputDeviceInfo() {
9826d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
9836d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
9846d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brownvoid InputDeviceInfo::initialize(int32_t id, const String8& name) {
9856d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    mId = id;
9866d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    mName = name;
9876d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    mSources = 0;
9886d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
9896d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    mMotionRanges.clear();
9906d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
9916d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
992efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brownconst InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(
993efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown        int32_t axis, uint32_t source) const {
994efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown    size_t numRanges = mMotionRanges.size();
995efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown    for (size_t i = 0; i < numRanges; i++) {
996efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown        const MotionRange& range = mMotionRanges.itemAt(i);
997efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown        if (range.axis == axis && range.source == source) {
998efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown            return &range;
999efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown        }
1000efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown    }
1001efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown    return NULL;
10026d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
10036d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
10046d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brownvoid InputDeviceInfo::addSource(uint32_t source) {
10056d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    mSources |= source;
10066d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
10076d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
1008efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brownvoid InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max,
10096d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown        float flat, float fuzz) {
1010efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown    MotionRange range = { axis, source, min, max, flat, fuzz };
1011efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown    mMotionRanges.add(range);
10126d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
10136d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
1014efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brownvoid InputDeviceInfo::addMotionRange(const MotionRange& range) {
1015efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown    mMotionRanges.add(range);
10166d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
10176d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
101846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} // namespace android
1019