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
16b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown// Log debug messages about least squares fitting.
17b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#define DEBUG_LEAST_SQUARES 0
18b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
1919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown// Log debug messages about acceleration.
2019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#define DEBUG_ACCELERATION 0
2119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
2219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
2347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#include <stdlib.h>
2447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#include <unistd.h>
259065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown#include <ctype.h>
2647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
2746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown#include <ui/Input.h>
2846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
2991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#include <math.h>
3019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#include <limits.h>
3191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
3291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#ifdef HAVE_ANDROID_OS
3391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#include <binder/Parcel.h>
3491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
3591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#include "SkPoint.h"
3691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#include "SkMatrix.h"
3791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#include "SkScalar.h"
3891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#endif
3991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
4046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownnamespace android {
4146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
4247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownstatic const char* CONFIGURATION_FILE_DIR[] = {
4347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        "idc/",
4447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        "keylayout/",
4547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        "keychars/",
4647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown};
4747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
4847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownstatic const char* CONFIGURATION_FILE_EXTENSION[] = {
4947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        ".idc",
5047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        ".kl",
5147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        ".kcm",
5247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown};
5347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
549065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brownstatic bool isValidNameChar(char ch) {
559065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown    return isascii(ch) && (isdigit(ch) || isalpha(ch) || ch == '-' || ch == '_');
569065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown}
579065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown
5847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brownstatic void appendInputDeviceConfigurationFileRelativePath(String8& path,
5947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        const String8& name, InputDeviceConfigurationFileType type) {
6047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    path.append(CONFIGURATION_FILE_DIR[type]);
6147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    for (size_t i = 0; i < name.length(); i++) {
6247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        char ch = name[i];
639065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        if (!isValidNameChar(ch)) {
6447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown            ch = '_';
6547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        }
6647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        path.append(&ch, 1);
6747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    }
6847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    path.append(CONFIGURATION_FILE_EXTENSION[type]);
6947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown}
7047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
719065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff BrownString8 getInputDeviceConfigurationFilePathByDeviceIdentifier(
729065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        const InputDeviceIdentifier& deviceIdentifier,
739065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        InputDeviceConfigurationFileType type) {
749065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown    if (deviceIdentifier.vendor !=0 && deviceIdentifier.product != 0) {
759065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        if (deviceIdentifier.version != 0) {
769065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown            // Try vendor product version.
779065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown            String8 versionPath(getInputDeviceConfigurationFilePathByName(
789065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                    String8::format("Vendor_%04x_Product_%04x_Version_%04x",
799065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                            deviceIdentifier.vendor, deviceIdentifier.product,
809065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                            deviceIdentifier.version),
819065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                    type));
829065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown            if (!versionPath.isEmpty()) {
839065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                return versionPath;
849065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown            }
859065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        }
869065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown
879065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        // Try vendor product.
889065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        String8 productPath(getInputDeviceConfigurationFilePathByName(
899065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                String8::format("Vendor_%04x_Product_%04x",
909065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                        deviceIdentifier.vendor, deviceIdentifier.product),
919065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown                type));
929065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        if (!productPath.isEmpty()) {
939065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown            return productPath;
949065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown        }
959065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown    }
969065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown
979065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown    // Try device name.
989065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown    return getInputDeviceConfigurationFilePathByName(deviceIdentifier.name, type);
999065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown}
1009065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff Brown
1019065504a63d6bf37bf621191fda1d1fe4da76ee3Jeff BrownString8 getInputDeviceConfigurationFilePathByName(
10247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        const String8& name, InputDeviceConfigurationFileType type) {
10347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    // Search system repository.
10447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    String8 path;
10547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    path.setTo(getenv("ANDROID_ROOT"));
10647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    path.append("/usr/");
10747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    appendInputDeviceConfigurationFileRelativePath(path, name, type);
10847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#if DEBUG_PROBE
10947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    LOGD("Probing for system provided input device configuration file: path='%s'", path.string());
11047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#endif
11147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    if (!access(path.string(), R_OK)) {
11247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#if DEBUG_PROBE
11347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        LOGD("Found");
11447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#endif
11547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        return path;
11647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    }
11747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
11847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    // Search user repository.
11947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    // TODO Should only look here if not in safe mode.
12047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    path.setTo(getenv("ANDROID_DATA"));
12147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    path.append("/system/devices/");
12247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    appendInputDeviceConfigurationFileRelativePath(path, name, type);
12347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#if DEBUG_PROBE
12447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    LOGD("Probing for system user input device configuration file: path='%s'", path.string());
12547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#endif
12647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    if (!access(path.string(), R_OK)) {
12747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#if DEBUG_PROBE
12847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        LOGD("Found");
12947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#endif
13047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown        return path;
13147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    }
13247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
13347e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    // Not found.
13447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#if DEBUG_PROBE
13547e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    LOGD("Probe failed to find input device configuration file: name='%s', type=%d",
13647e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown            name.string(), type);
13747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown#endif
13847e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown    return String8();
13947e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown}
14047e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
14147e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown
14247e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown// --- InputEvent ---
14346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
144c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brownvoid InputEvent::initialize(int32_t deviceId, int32_t source) {
14546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mDeviceId = deviceId;
146c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    mSource = source;
14746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
14846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
1492c6081ce3593712f30dacd990a97209c791d6cedDianne Hackbornvoid InputEvent::initialize(const InputEvent& from) {
1502c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mDeviceId = from.mDeviceId;
1512c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mSource = from.mSource;
1522c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn}
1532c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn
15447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown// --- KeyEvent ---
15546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
1563c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackbornbool KeyEvent::hasDefaultAction(int32_t keyCode) {
1573c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    switch (keyCode) {
158fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_HOME:
159fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_BACK:
160fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_CALL:
161fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_ENDCALL:
162fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_VOLUME_UP:
163fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_VOLUME_DOWN:
164b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_VOLUME_MUTE:
165fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_POWER:
166fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_CAMERA:
167fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_HEADSETHOOK:
168fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MENU:
169fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_NOTIFICATION:
170fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_FOCUS:
171fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_SEARCH:
172b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_MEDIA_PLAY:
173b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_MEDIA_PAUSE:
174fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_PLAY_PAUSE:
175fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_STOP:
176fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_NEXT:
177fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_PREVIOUS:
178fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_REWIND:
179b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_MEDIA_RECORD:
180fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_FAST_FORWARD:
181fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MUTE:
1823c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn            return true;
1833c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    }
1843c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
1853c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    return false;
1863c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn}
1873c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
1883c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackbornbool KeyEvent::hasDefaultAction() const {
1893c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    return hasDefaultAction(getKeyCode());
1903c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn}
1913c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
1923c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackbornbool KeyEvent::isSystemKey(int32_t keyCode) {
1933c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    switch (keyCode) {
194fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MENU:
195fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_SOFT_RIGHT:
196fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_HOME:
197fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_BACK:
198fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_CALL:
199fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_ENDCALL:
200fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_VOLUME_UP:
201fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_VOLUME_DOWN:
202b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_VOLUME_MUTE:
203fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MUTE:
204fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_POWER:
205fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_HEADSETHOOK:
206b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_MEDIA_PLAY:
207b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_MEDIA_PAUSE:
208fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_PLAY_PAUSE:
209fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_STOP:
210fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_NEXT:
211fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_PREVIOUS:
212fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_REWIND:
213b0418da0e7594a8c2164a46985c5f1993632e010Jeff Brown        case AKEYCODE_MEDIA_RECORD:
214fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_MEDIA_FAST_FORWARD:
215fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_CAMERA:
216fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_FOCUS:
217fd03582995e0fce963dd0fa0669e3211b74c0dd7Jeff Brown        case AKEYCODE_SEARCH:
2183c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn            return true;
2193c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    }
2203c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
2213c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    return false;
2223c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn}
2233c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
2243c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackbornbool KeyEvent::isSystemKey() const {
2253c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn    return isSystemKey(getKeyCode());
2263c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn}
2273c80a4a044865bdf1289c7896baffa1c082d835cDianne Hackborn
22846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownvoid KeyEvent::initialize(
22946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t deviceId,
230c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown        int32_t source,
23146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t action,
23246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t flags,
23346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t keyCode,
23446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t scanCode,
23546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t metaState,
23646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t repeatCount,
23746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        nsecs_t downTime,
23846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        nsecs_t eventTime) {
239c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    InputEvent::initialize(deviceId, source);
24046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mAction = action;
24146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mFlags = flags;
24246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mKeyCode = keyCode;
24346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mScanCode = scanCode;
24446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mMetaState = metaState;
24546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mRepeatCount = repeatCount;
24646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mDownTime = downTime;
24746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mEventTime = eventTime;
24846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
24946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
2502c6081ce3593712f30dacd990a97209c791d6cedDianne Hackbornvoid KeyEvent::initialize(const KeyEvent& from) {
2512c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    InputEvent::initialize(from);
2522c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mAction = from.mAction;
2532c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mFlags = from.mFlags;
2542c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mKeyCode = from.mKeyCode;
2552c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mScanCode = from.mScanCode;
2562c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mMetaState = from.mMetaState;
2572c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mRepeatCount = from.mRepeatCount;
2582c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mDownTime = from.mDownTime;
2592c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn    mEventTime = from.mEventTime;
2602c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn}
2612c6081ce3593712f30dacd990a97209c791d6cedDianne Hackborn
26291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
26391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown// --- PointerCoords ---
26491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
2656f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brownfloat PointerCoords::getAxisValue(int32_t axis) const {
2666f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    if (axis < 0 || axis > 63) {
2676f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        return 0;
2686f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    }
2696f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown
2706f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    uint64_t axisBit = 1LL << axis;
2716f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    if (!(bits & axisBit)) {
2726f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        return 0;
2736f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    }
2746f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
2756f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    return values[index];
2766f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown}
2776f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown
2786f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brownstatus_t PointerCoords::setAxisValue(int32_t axis, float value) {
2796f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    if (axis < 0 || axis > 63) {
2806f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        return NAME_NOT_FOUND;
2816f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    }
2826f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown
2836f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    uint64_t axisBit = 1LL << axis;
2846f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL));
2856f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    if (!(bits & axisBit)) {
286be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        if (value == 0) {
287be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown            return OK; // axes with value 0 do not need to be stored
288be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        }
2896f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        uint32_t count = __builtin_popcountll(bits);
2906f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        if (count >= MAX_AXES) {
2916f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown            tooManyAxes(axis);
2926f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown            return NO_MEMORY;
2936f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        }
2946f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        bits |= axisBit;
2956f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        for (uint32_t i = count; i > index; i--) {
2966f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown            values[i] = values[i - 1];
2976f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown        }
2986f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    }
2996f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    values[index] = value;
3006f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    return OK;
3016f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown}
3026f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown
303e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackbornstatic inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) {
304be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown    float value = c.getAxisValue(axis);
305be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown    if (value != 0) {
306be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        c.setAxisValue(axis, value * scaleFactor);
307e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    }
308e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn}
309e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
310e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackbornvoid PointerCoords::scale(float scaleFactor) {
311e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    // No need to scale pressure or size since they are normalized.
312e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    // No need to scale orientation since it is meaningless to do so.
313e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    scaleAxisValue(*this, AMOTION_EVENT_AXIS_X, scaleFactor);
314e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    scaleAxisValue(*this, AMOTION_EVENT_AXIS_Y, scaleFactor);
315e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MAJOR, scaleFactor);
316e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MINOR, scaleFactor);
317e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MAJOR, scaleFactor);
318e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn    scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor);
319e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn}
320e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn
32191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#ifdef HAVE_ANDROID_OS
32291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownstatus_t PointerCoords::readFromParcel(Parcel* parcel) {
3236f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    bits = parcel->readInt64();
32491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
3256f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    uint32_t count = __builtin_popcountll(bits);
32691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    if (count > MAX_AXES) {
32791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        return BAD_VALUE;
32891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
32991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
33091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    for (uint32_t i = 0; i < count; i++) {
33191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        values[i] = parcel->readInt32();
33291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
33391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return OK;
33491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
33591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
33691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownstatus_t PointerCoords::writeToParcel(Parcel* parcel) const {
3376f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    parcel->writeInt64(bits);
33891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
3396f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown    uint32_t count = __builtin_popcountll(bits);
34091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    for (uint32_t i = 0; i < count; i++) {
34191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        parcel->writeInt32(values[i]);
34291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
34391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return OK;
34491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
34591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#endif
34691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
34791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownvoid PointerCoords::tooManyAxes(int axis) {
34891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    LOGW("Could not set value for axis %d because the PointerCoords structure is full and "
34991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown            "cannot contain more than %d axis values.", axis, int(MAX_AXES));
35091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
35191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
352ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brownbool PointerCoords::operator==(const PointerCoords& other) const {
353ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    if (bits != other.bits) {
354ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        return false;
355ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    }
356ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    uint32_t count = __builtin_popcountll(bits);
357ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    for (uint32_t i = 0; i < count; i++) {
358ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        if (values[i] != other.values[i]) {
359ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            return false;
360ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        }
361ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    }
362ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    return true;
363ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown}
364ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
365ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brownvoid PointerCoords::copyFrom(const PointerCoords& other) {
366ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    bits = other.bits;
367ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    uint32_t count = __builtin_popcountll(bits);
368ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    for (uint32_t i = 0; i < count; i++) {
369ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        values[i] = other.values[i];
370ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    }
371ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown}
372ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
37391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
374fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown// --- PointerProperties ---
375fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown
376fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brownbool PointerProperties::operator==(const PointerProperties& other) const {
377fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    return id == other.id
378fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown            && toolType == other.toolType;
379fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown}
380fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown
381fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brownvoid PointerProperties::copyFrom(const PointerProperties& other) {
382fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    id = other.id;
383fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    toolType = other.toolType;
384fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown}
385fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown
386fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown
38747e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown// --- MotionEvent ---
38846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
38946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownvoid MotionEvent::initialize(
39046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t deviceId,
391c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown        int32_t source,
39246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t action,
39385a3176704b5bfbeece9bd928369fbb76eec7dc6Jeff Brown        int32_t flags,
39446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t edgeFlags,
39546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int32_t metaState,
396fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        int32_t buttonState,
3975c225b1680e696ae8bbf505a1997d6f720672f74Jeff Brown        float xOffset,
3985c225b1680e696ae8bbf505a1997d6f720672f74Jeff Brown        float yOffset,
39946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        float xPrecision,
40046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        float yPrecision,
40146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        nsecs_t downTime,
40246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        nsecs_t eventTime,
40346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        size_t pointerCount,
404fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        const PointerProperties* pointerProperties,
40546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        const PointerCoords* pointerCoords) {
406c5ed5910c9ef066cec6a13bbb404ec57b1e92637Jeff Brown    InputEvent::initialize(deviceId, source);
40746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mAction = action;
40885a3176704b5bfbeece9bd928369fbb76eec7dc6Jeff Brown    mFlags = flags;
40946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mEdgeFlags = edgeFlags;
41046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mMetaState = metaState;
411fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mButtonState = buttonState;
4125c225b1680e696ae8bbf505a1997d6f720672f74Jeff Brown    mXOffset = xOffset;
4135c225b1680e696ae8bbf505a1997d6f720672f74Jeff Brown    mYOffset = yOffset;
41446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mXPrecision = xPrecision;
41546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mYPrecision = yPrecision;
41646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mDownTime = downTime;
417fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mPointerProperties.clear();
418fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mPointerProperties.appendArray(pointerProperties, pointerCount);
41946b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mSampleEventTimes.clear();
42046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mSamplePointerCoords.clear();
42146b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    addSample(eventTime, pointerCoords);
42246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
42346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
42491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownvoid MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
42591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    InputEvent::initialize(other->mDeviceId, other->mSource);
42691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mAction = other->mAction;
42791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mFlags = other->mFlags;
42891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mEdgeFlags = other->mEdgeFlags;
42991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mMetaState = other->mMetaState;
430fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mButtonState = other->mButtonState;
43191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mXOffset = other->mXOffset;
43291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mYOffset = other->mYOffset;
43391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mXPrecision = other->mXPrecision;
43491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mYPrecision = other->mYPrecision;
43591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mDownTime = other->mDownTime;
436fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mPointerProperties = other->mPointerProperties;
43791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
43891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    if (keepHistory) {
43991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        mSampleEventTimes = other->mSampleEventTimes;
44091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        mSamplePointerCoords = other->mSamplePointerCoords;
44191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    } else {
44291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        mSampleEventTimes.clear();
44391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        mSampleEventTimes.push(other->getEventTime());
44491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        mSamplePointerCoords.clear();
44591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        size_t pointerCount = other->getPointerCount();
44691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        size_t historySize = other->getHistorySize();
44791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array()
44891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown                + (historySize * pointerCount), pointerCount);
44991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
45091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
45191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
45246b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownvoid MotionEvent::addSample(
45346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        int64_t eventTime,
45446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown        const PointerCoords* pointerCoords) {
45546b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mSampleEventTimes.push(eventTime);
45646b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown    mSamplePointerCoords.appendArray(pointerCoords, getPointerCount());
45746b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
45846b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
45991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownconst PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const {
46091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex];
46191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
46291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
46391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownfloat MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const {
46491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return getRawPointerCoords(pointerIndex)->getAxisValue(axis);
46591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
46691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
46791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownfloat MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const {
46891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis);
46991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    switch (axis) {
470ebbd5d14ad3b1e762d9fcfa026e19413cc857e05Jeff Brown    case AMOTION_EVENT_AXIS_X:
471e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return value + mXOffset;
472ebbd5d14ad3b1e762d9fcfa026e19413cc857e05Jeff Brown    case AMOTION_EVENT_AXIS_Y:
473e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return value + mYOffset;
47491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
47591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return value;
47691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
47791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
47891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownconst PointerCoords* MotionEvent::getHistoricalRawPointerCoords(
47991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        size_t pointerIndex, size_t historicalIndex) const {
48091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex];
48191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
48291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
48391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownfloat MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex,
48491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        size_t historicalIndex) const {
48591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
48691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
48791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
48891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownfloat MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex,
48991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        size_t historicalIndex) const {
49091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis);
49191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    switch (axis) {
492ebbd5d14ad3b1e762d9fcfa026e19413cc857e05Jeff Brown    case AMOTION_EVENT_AXIS_X:
493e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return value + mXOffset;
494ebbd5d14ad3b1e762d9fcfa026e19413cc857e05Jeff Brown    case AMOTION_EVENT_AXIS_Y:
495e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        return value + mYOffset;
49691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
49791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return value;
49891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
49991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
5002ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownssize_t MotionEvent::findPointerIndex(int32_t pointerId) const {
501fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    size_t pointerCount = mPointerProperties.size();
5022ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    for (size_t i = 0; i < pointerCount; i++) {
503fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        if (mPointerProperties.itemAt(i).id == pointerId) {
5042ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            return i;
5052ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        }
5062ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
5072ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    return -1;
5082ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
5092ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
51046b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brownvoid MotionEvent::offsetLocation(float xOffset, float yOffset) {
5115c225b1680e696ae8bbf505a1997d6f720672f74Jeff Brown    mXOffset += xOffset;
5125c225b1680e696ae8bbf505a1997d6f720672f74Jeff Brown    mYOffset += yOffset;
51346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown}
51446b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown
51591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownvoid MotionEvent::scale(float scaleFactor) {
51691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mXOffset *= scaleFactor;
51791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mYOffset *= scaleFactor;
51891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mXPrecision *= scaleFactor;
51991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mYPrecision *= scaleFactor;
52091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
52191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    size_t numSamples = mSamplePointerCoords.size();
52291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    for (size_t i = 0; i < numSamples; i++) {
523e2515eebf42c763c0a2d9f873a153711778cfc17Dianne Hackborn        mSamplePointerCoords.editItemAt(i).scale(scaleFactor);
52491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
52591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
52691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
52791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#ifdef HAVE_ANDROID_OS
52891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownstatic inline float transformAngle(const SkMatrix* matrix, float angleRadians) {
52991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    // Construct and transform a vector oriented at the specified clockwise angle from vertical.
53091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    // Coordinate system: down is increasing Y, right is increasing X.
53191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    SkPoint vector;
53291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    vector.fX = SkFloatToScalar(sinf(angleRadians));
53391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    vector.fY = SkFloatToScalar(-cosf(angleRadians));
53491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    matrix->mapVectors(& vector, 1);
53591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
53691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    // Derive the transformed vector's clockwise angle from vertical.
53791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY));
53891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    if (result < - M_PI_2) {
53991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        result += M_PI;
54091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    } else if (result > M_PI_2) {
54191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        result -= M_PI;
54291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
54391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return result;
54491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
54591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
54691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownvoid MotionEvent::transform(const SkMatrix* matrix) {
54791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float oldXOffset = mXOffset;
54891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float oldYOffset = mYOffset;
54991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
55091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    // The tricky part of this implementation is to preserve the value of
55191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    // rawX and rawY.  So we apply the transformation to the first point
55291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    // then derive an appropriate new X/Y offset that will preserve rawX and rawY.
55391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    SkPoint point;
55491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float rawX = getRawX(0);
55591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float rawY = getRawY(0);
55691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset),
55791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown            & point);
55891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float newX = SkScalarToFloat(point.fX);
55991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float newY = SkScalarToFloat(point.fY);
56091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float newXOffset = newX - rawX;
56191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    float newYOffset = newY - rawY;
56291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
56391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mXOffset = newXOffset;
56491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mYOffset = newYOffset;
56591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
56691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    // Apply the transformation to all samples.
56791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    size_t numSamples = mSamplePointerCoords.size();
56891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    for (size_t i = 0; i < numSamples; i++) {
56991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        PointerCoords& c = mSamplePointerCoords.editItemAt(i);
570be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset;
571be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset;
572be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), &point);
573be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        c.setAxisValue(AMOTION_EVENT_AXIS_X, SkScalarToFloat(point.fX) - newXOffset);
574be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        c.setAxisValue(AMOTION_EVENT_AXIS_Y, SkScalarToFloat(point.fY) - newYOffset);
57591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
576be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
577be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(matrix, orientation));
57891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
57991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
58091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
58191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownstatus_t MotionEvent::readFromParcel(Parcel* parcel) {
58291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    size_t pointerCount = parcel->readInt32();
58391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    size_t sampleCount = parcel->readInt32();
58491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) {
58591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        return BAD_VALUE;
58691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
58791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
58891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mDeviceId = parcel->readInt32();
58991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mSource = parcel->readInt32();
59091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mAction = parcel->readInt32();
59191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mFlags = parcel->readInt32();
59291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mEdgeFlags = parcel->readInt32();
59391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mMetaState = parcel->readInt32();
594fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mButtonState = parcel->readInt32();
59591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mXOffset = parcel->readFloat();
59691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mYOffset = parcel->readFloat();
59791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mXPrecision = parcel->readFloat();
59891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mYPrecision = parcel->readFloat();
59991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mDownTime = parcel->readInt64();
60091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
601fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mPointerProperties.clear();
602fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    mPointerProperties.setCapacity(pointerCount);
60391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mSampleEventTimes.clear();
60491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mSampleEventTimes.setCapacity(sampleCount);
60591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mSamplePointerCoords.clear();
60691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    mSamplePointerCoords.setCapacity(sampleCount * pointerCount);
60791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
60891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    for (size_t i = 0; i < pointerCount; i++) {
609fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        mPointerProperties.push();
610fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        PointerProperties& properties = mPointerProperties.editTop();
611fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        properties.id = parcel->readInt32();
612fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        properties.toolType = parcel->readInt32();
61391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
61491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
61591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    while (sampleCount-- > 0) {
61691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        mSampleEventTimes.push(parcel->readInt64());
61791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        for (size_t i = 0; i < pointerCount; i++) {
61891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown            mSamplePointerCoords.push();
61991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown            status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel);
620ebbd5d14ad3b1e762d9fcfa026e19413cc857e05Jeff Brown            if (status) {
62191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown                return status;
62291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown            }
62391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        }
62491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
62591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return OK;
62691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
62791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
62891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brownstatus_t MotionEvent::writeToParcel(Parcel* parcel) const {
629fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    size_t pointerCount = mPointerProperties.size();
63091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    size_t sampleCount = mSampleEventTimes.size();
63191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
63291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(pointerCount);
63391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(sampleCount);
63491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
63591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(mDeviceId);
63691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(mSource);
63791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(mAction);
63891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(mFlags);
63991c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(mEdgeFlags);
64091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt32(mMetaState);
641fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown    parcel->writeInt32(mButtonState);
64291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeFloat(mXOffset);
64391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeFloat(mYOffset);
64491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeFloat(mXPrecision);
64591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeFloat(mYPrecision);
64691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    parcel->writeInt64(mDownTime);
64791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
64891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    for (size_t i = 0; i < pointerCount; i++) {
649fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        const PointerProperties& properties = mPointerProperties.itemAt(i);
650fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        parcel->writeInt32(properties.id);
651fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown        parcel->writeInt32(properties.toolType);
65291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
65391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
65491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    const PointerCoords* pc = mSamplePointerCoords.array();
65591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    for (size_t h = 0; h < sampleCount; h++) {
65691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        parcel->writeInt64(mSampleEventTimes.itemAt(h));
65791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        for (size_t i = 0; i < pointerCount; i++) {
65891c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown            status_t status = (pc++)->writeToParcel(parcel);
659ebbd5d14ad3b1e762d9fcfa026e19413cc857e05Jeff Brown            if (status) {
66091c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown                return status;
66191c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown            }
66291c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown        }
66391c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    }
66491c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown    return OK;
66591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown}
66691c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown#endif
66791c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
66856194ebec6212e229f4ccdaa4b187166d20013efJeff Brownbool MotionEvent::isTouchEvent(int32_t source, int32_t action) {
66956194ebec6212e229f4ccdaa4b187166d20013efJeff Brown    if (source & AINPUT_SOURCE_CLASS_POINTER) {
67056194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        // Specifically excludes HOVER_MOVE and SCROLL.
67156194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        switch (action & AMOTION_EVENT_ACTION_MASK) {
67256194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        case AMOTION_EVENT_ACTION_DOWN:
67356194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        case AMOTION_EVENT_ACTION_MOVE:
67456194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        case AMOTION_EVENT_ACTION_UP:
67556194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        case AMOTION_EVENT_ACTION_POINTER_DOWN:
67656194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        case AMOTION_EVENT_ACTION_POINTER_UP:
67756194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        case AMOTION_EVENT_ACTION_CANCEL:
67856194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        case AMOTION_EVENT_ACTION_OUTSIDE:
67956194ebec6212e229f4ccdaa4b187166d20013efJeff Brown            return true;
68056194ebec6212e229f4ccdaa4b187166d20013efJeff Brown        }
68156194ebec6212e229f4ccdaa4b187166d20013efJeff Brown    }
68256194ebec6212e229f4ccdaa4b187166d20013efJeff Brown    return false;
68356194ebec6212e229f4ccdaa4b187166d20013efJeff Brown}
68456194ebec6212e229f4ccdaa4b187166d20013efJeff Brown
68591c69ab01539f7ba28708f41ec1835cc2920d0a0Jeff Brown
686ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown// --- VelocityTracker ---
687ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
688b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brownconst uint32_t VelocityTracker::DEFAULT_DEGREE;
689b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brownconst nsecs_t VelocityTracker::DEFAULT_HORIZON;
69019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brownconst uint32_t VelocityTracker::HISTORY_SIZE;
691b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
692b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brownstatic inline float vectorDot(const float* a, const float* b, uint32_t m) {
693b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    float r = 0;
694b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    while (m--) {
695b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        r += *(a++) * *(b++);
696b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
697b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    return r;
698b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown}
699b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
700b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brownstatic inline float vectorNorm(const float* a, uint32_t m) {
701b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    float r = 0;
702b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    while (m--) {
703b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        float t = *(a++);
704b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        r += t * t;
705b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
706b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    return sqrtf(r);
707b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown}
708b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
709b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#if DEBUG_LEAST_SQUARES || DEBUG_VELOCITY
710b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brownstatic String8 vectorToString(const float* a, uint32_t m) {
711b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    String8 str;
712b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    str.append("[");
713b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    while (m--) {
714b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        str.appendFormat(" %f", *(a++));
715b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        if (m) {
716b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            str.append(",");
717b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
718b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
719b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    str.append(" ]");
720b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    return str;
721b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown}
722b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
723b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brownstatic String8 matrixToString(const float* a, uint32_t m, uint32_t n, bool rowMajor) {
724b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    String8 str;
725b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    str.append("[");
726b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    for (size_t i = 0; i < m; i++) {
727b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        if (i) {
728b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            str.append(",");
729b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
730b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        str.append(" [");
731b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        for (size_t j = 0; j < n; j++) {
732b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            if (j) {
733b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                str.append(",");
734b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            }
735b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            str.appendFormat(" %f", a[rowMajor ? i * n + j : j * m + i]);
736b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
737b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        str.append(" ]");
738b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
739b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    str.append(" ]");
740b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    return str;
741b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown}
742b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#endif
74319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
744ace13b17866dc9136aeecf6dfaf7077f37434469Jeff BrownVelocityTracker::VelocityTracker() {
745ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    clear();
746ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown}
747ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
748ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brownvoid VelocityTracker::clear() {
749ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    mIndex = 0;
750ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    mMovements[0].idBits.clear();
7512ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    mActivePointerId = -1;
7522ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
7532ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
7542ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownvoid VelocityTracker::clearPointers(BitSet32 idBits) {
7552ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    BitSet32 remainingIdBits(mMovements[mIndex].idBits.value & ~idBits.value);
7562ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    mMovements[mIndex].idBits = remainingIdBits;
7572ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
7582ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    if (mActivePointerId >= 0 && idBits.hasBit(mActivePointerId)) {
7592ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        mActivePointerId = !remainingIdBits.isEmpty() ? remainingIdBits.firstMarkedBit() : -1;
7602ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
761ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown}
762ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
763ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brownvoid VelocityTracker::addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions) {
764ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    if (++mIndex == HISTORY_SIZE) {
765ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        mIndex = 0;
766ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    }
7672ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
7682ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    while (idBits.count() > MAX_POINTERS) {
769be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        idBits.clearLastMarkedBit();
7702ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
7712ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
772ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    Movement& movement = mMovements[mIndex];
773ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    movement.eventTime = eventTime;
774ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    movement.idBits = idBits;
775ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    uint32_t count = idBits.count();
776ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    for (uint32_t i = 0; i < count; i++) {
777ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        movement.positions[i] = positions[i];
778ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    }
779ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
7802ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    if (mActivePointerId < 0 || !idBits.hasBit(mActivePointerId)) {
7812ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        mActivePointerId = count != 0 ? idBits.firstMarkedBit() : -1;
7822ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
7832ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
784ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown#if DEBUG_VELOCITY
7852ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    LOGD("VelocityTracker: addMovement eventTime=%lld, idBits=0x%08x, activePointerId=%d",
7862ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            eventTime, idBits.value, mActivePointerId);
787ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    for (BitSet32 iterBits(idBits); !iterBits.isEmpty(); ) {
788ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        uint32_t id = iterBits.firstMarkedBit();
789ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        uint32_t index = idBits.getIndexOfBit(id);
790ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        iterBits.clearBit(id);
791b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        Estimator estimator;
792b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        getEstimator(id, DEFAULT_DEGREE, DEFAULT_HORIZON, &estimator);
793b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        LOGD("  %d: position (%0.3f, %0.3f), "
794b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                "estimator (degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f)",
795b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                id, positions[index].x, positions[index].y,
796b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                int(estimator.degree),
797b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                vectorToString(estimator.xCoeff, estimator.degree).string(),
798b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                vectorToString(estimator.yCoeff, estimator.degree).string(),
799b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                estimator.confidence);
800ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    }
801ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown#endif
802ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown}
803ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
8042ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownvoid VelocityTracker::addMovement(const MotionEvent* event) {
8052ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    int32_t actionMasked = event->getActionMasked();
8062ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
8072ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    switch (actionMasked) {
8082ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    case AMOTION_EVENT_ACTION_DOWN:
809581761d4aa0133fe7354cc9e4a5dd3d9d7258c5fJeff Brown    case AMOTION_EVENT_ACTION_HOVER_ENTER:
8102ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // Clear all pointers on down before adding the new movement.
8112ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        clear();
8122ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        break;
8132ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    case AMOTION_EVENT_ACTION_POINTER_DOWN: {
8142ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // Start a new movement trace for a pointer that just went down.
8152ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // We do this on down instead of on up because the client may want to query the
8162ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // final velocity for a pointer that just went up.
8172ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        BitSet32 downIdBits;
818be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        downIdBits.markBit(event->getPointerId(event->getActionIndex()));
8192ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        clearPointers(downIdBits);
8202ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        break;
8212ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
822581761d4aa0133fe7354cc9e4a5dd3d9d7258c5fJeff Brown    case AMOTION_EVENT_ACTION_MOVE:
823581761d4aa0133fe7354cc9e4a5dd3d9d7258c5fJeff Brown    case AMOTION_EVENT_ACTION_HOVER_MOVE:
824581761d4aa0133fe7354cc9e4a5dd3d9d7258c5fJeff Brown        break;
825581761d4aa0133fe7354cc9e4a5dd3d9d7258c5fJeff Brown    default:
826581761d4aa0133fe7354cc9e4a5dd3d9d7258c5fJeff Brown        // Ignore all other actions because they do not convey any new information about
8272ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // pointer movement.  We also want to preserve the last known velocity of the pointers.
8282ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // Note that ACTION_UP and ACTION_POINTER_UP always report the last known position
8292ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // of the pointers that went up.  ACTION_POINTER_UP does include the new position of
8302ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // pointers that remained down but we will also receive an ACTION_MOVE with this
8312ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // information if any of them actually moved.  Since we don't know how many pointers
8322ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // will be going up at once it makes sense to just wait for the following ACTION_MOVE
8332ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        // before adding the movement.
8342ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        return;
8352ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
8362ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
8372ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    size_t pointerCount = event->getPointerCount();
8382ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    if (pointerCount > MAX_POINTERS) {
8392ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        pointerCount = MAX_POINTERS;
8402ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
8412ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
8422ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    BitSet32 idBits;
8432ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    for (size_t i = 0; i < pointerCount; i++) {
8442ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        idBits.markBit(event->getPointerId(i));
8452ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
8462ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
8472ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    nsecs_t eventTime;
8482ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    Position positions[pointerCount];
8492ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
8502ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    size_t historySize = event->getHistorySize();
8512ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    for (size_t h = 0; h < historySize; h++) {
8522ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        eventTime = event->getHistoricalEventTime(h);
8532ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        for (size_t i = 0; i < pointerCount; i++) {
8542ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            positions[i].x = event->getHistoricalX(i, h);
8552ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            positions[i].y = event->getHistoricalY(i, h);
8562ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        }
8572ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        addMovement(eventTime, idBits, positions);
8582ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
8592ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
8602ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    eventTime = event->getEventTime();
8612ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    for (size_t i = 0; i < pointerCount; i++) {
8622ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        positions[i].x = event->getX(i);
8632ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        positions[i].y = event->getY(i);
8642ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
8652ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    addMovement(eventTime, idBits, positions);
8662ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
8672ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
868b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown/**
869b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * Solves a linear least squares problem to obtain a N degree polynomial that fits
870b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * the specified input data as nearly as possible.
871b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown *
872b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * Returns true if a solution is found, false otherwise.
873b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown *
874b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * The input consists of two vectors of data points X and Y with indices 0..m-1.
875b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * The output is a vector B with indices 0..n-1 that describes a polynomial
876b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * that fits the data, such the sum of abs(Y[i] - (B[0] + B[1] X[i] + B[2] X[i]^2 ... B[n] X[i]^n))
877b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * for all i between 0 and m-1 is minimized.
878b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown *
879b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * That is to say, the function that generated the input data can be approximated
880b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * by y(x) ~= B[0] + B[1] x + B[2] x^2 + ... + B[n] x^n.
881b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown *
882b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * The coefficient of determination (R^2) is also returned to describe the goodness
883b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * of fit of the model for the given data.  It is a value between 0 and 1, where 1
884b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * indicates perfect correspondence.
885b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown *
886b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * This function first expands the X vector to a m by n matrix A such that
887b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * A[i][0] = 1, A[i][1] = X[i], A[i][2] = X[i]^2, ..., A[i][n] = X[i]^n.
888b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown *
889b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * Then it calculates the QR decomposition of A yielding an m by m orthonormal matrix Q
890b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * and an m by n upper triangular matrix R.  Because R is upper triangular (lower
891b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * part is all zeroes), we can simplify the decomposition into an m by n matrix
892b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * Q1 and a n by n matrix R1 such that A = Q1 R1.
893b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown *
894b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * Finally we solve the system of linear equations given by R1 B = (Qtranspose Y)
895b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * to find B.
896b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown *
897b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * For efficiency, we lay out A and Q column-wise in memory because we frequently
898b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * operate on the column vectors.  Conversely, we lay out R row-wise.
899b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown *
900b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * http://en.wikipedia.org/wiki/Numerical_methods_for_linear_least_squares
901b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown * http://en.wikipedia.org/wiki/Gram-Schmidt
902b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown */
903b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brownstatic bool solveLeastSquares(const float* x, const float* y, uint32_t m, uint32_t n,
904b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        float* outB, float* outDet) {
905b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#if DEBUG_LEAST_SQUARES
906b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    LOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s", int(m), int(n),
907b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            vectorToString(x, m).string(), vectorToString(y, m).string());
908b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#endif
909b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
910b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    // Expand the X vector to a matrix A.
911b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    float a[n][m]; // column-major order
912b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    for (uint32_t h = 0; h < m; h++) {
913b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        a[0][h] = 1;
914b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        for (uint32_t i = 1; i < n; i++) {
915b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            a[i][h] = a[i - 1][h] * x[h];
916b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
917b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
918b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#if DEBUG_LEAST_SQUARES
919b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    LOGD("  - a=%s", matrixToString(&a[0][0], m, n, false /*rowMajor*/).string());
920b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#endif
921b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
922b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    // Apply the Gram-Schmidt process to A to obtain its QR decomposition.
923b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    float q[n][m]; // orthonormal basis, column-major order
924b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    float r[n][n]; // upper triangular matrix, row-major order
925b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    for (uint32_t j = 0; j < n; j++) {
926b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        for (uint32_t h = 0; h < m; h++) {
927b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            q[j][h] = a[j][h];
928b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
929b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        for (uint32_t i = 0; i < j; i++) {
930b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            float dot = vectorDot(&q[j][0], &q[i][0], m);
931b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            for (uint32_t h = 0; h < m; h++) {
932b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                q[j][h] -= dot * q[i][h];
933ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown            }
934b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
935581761d4aa0133fe7354cc9e4a5dd3d9d7258c5fJeff Brown
936b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        float norm = vectorNorm(&q[j][0], m);
937b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        if (norm < 0.000001f) {
938b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            // vectors are linearly dependent or zero so no solution
939b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#if DEBUG_LEAST_SQUARES
940b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            LOGD("  - no solution, norm=%f", norm);
941b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#endif
942b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            return false;
943b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
944b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
945b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        float invNorm = 1.0f / norm;
946b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        for (uint32_t h = 0; h < m; h++) {
947b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            q[j][h] *= invNorm;
948b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
949b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        for (uint32_t i = 0; i < n; i++) {
950b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            r[j][i] = i < j ? 0 : vectorDot(&q[j][0], &a[i][0], m);
951b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
952b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
953b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#if DEBUG_LEAST_SQUARES
954b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    LOGD("  - q=%s", matrixToString(&q[0][0], m, n, false /*rowMajor*/).string());
955b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    LOGD("  - r=%s", matrixToString(&r[0][0], n, n, true /*rowMajor*/).string());
956b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
957b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    // calculate QR, if we factored A correctly then QR should equal A
958b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    float qr[n][m];
959b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    for (uint32_t h = 0; h < m; h++) {
960b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        for (uint32_t i = 0; i < n; i++) {
961b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            qr[i][h] = 0;
962b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            for (uint32_t j = 0; j < n; j++) {
963b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                qr[i][h] += q[j][h] * r[j][i];
964581761d4aa0133fe7354cc9e4a5dd3d9d7258c5fJeff Brown            }
965b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
966b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
967b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    LOGD("  - qr=%s", matrixToString(&qr[0][0], m, n, false /*rowMajor*/).string());
968b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#endif
969581761d4aa0133fe7354cc9e4a5dd3d9d7258c5fJeff Brown
970b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    // Solve R B = Qt Y to find B.  This is easy because R is upper triangular.
971b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    // We just work from bottom-right to top-left calculating B's coefficients.
972b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    for (uint32_t i = n; i-- != 0; ) {
973b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        outB[i] = vectorDot(&q[i][0], y, m);
974b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        for (uint32_t j = n - 1; j > i; j--) {
975b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            outB[i] -= r[i][j] * outB[j];
976b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
977b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        outB[i] /= r[i][i];
978b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
979b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#if DEBUG_LEAST_SQUARES
980b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    LOGD("  - b=%s", vectorToString(outB, n).string());
981b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#endif
982b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
983b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    // Calculate the coefficient of determination as 1 - (SSerr / SStot) where
984b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    // SSerr is the residual sum of squares (squared variance of the error),
985b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    // and SStot is the total sum of squares (squared variance of the data).
986b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    float ymean = 0;
987b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    for (uint32_t h = 0; h < m; h++) {
988b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        ymean += y[h];
989b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
990b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    ymean /= m;
991b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
992b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    float sserr = 0;
993b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    float sstot = 0;
994b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    for (uint32_t h = 0; h < m; h++) {
995b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        float err = y[h] - outB[0];
996b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        float term = 1;
997b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        for (uint32_t i = 1; i < n; i++) {
998b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            term *= x[h];
999b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            err -= term * outB[i];
1000ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown        }
1001b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        sserr += err * err;
1002b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        float var = y[h] - ymean;
1003b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        sstot += var * var;
1004ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    }
1005b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    *outDet = sstot > 0.000001f ? 1.0f - (sserr / sstot) : 1;
1006b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#if DEBUG_LEAST_SQUARES
1007b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    LOGD("  - sserr=%f", sserr);
1008b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    LOGD("  - sstot=%f", sstot);
1009b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    LOGD("  - det=%f", *outDet);
1010b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#endif
1011b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    return true;
1012b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown}
1013ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
1014b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brownbool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const {
1015b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    Estimator estimator;
1016b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    if (getEstimator(id, DEFAULT_DEGREE, DEFAULT_HORIZON, &estimator)) {
1017b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        if (estimator.degree >= 1) {
1018b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            *outVx = estimator.xCoeff[1];
1019b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            *outVy = estimator.yCoeff[1];
1020b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            return true;
1021b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
1022b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
1023b0c71eb9f50ce06327fa6bb6219f0970e04fd856Jeff Brown    *outVx = 0;
1024b0c71eb9f50ce06327fa6bb6219f0970e04fd856Jeff Brown    *outVy = 0;
1025ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown    return false;
1026ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown}
1027ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
1028b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brownbool VelocityTracker::getEstimator(uint32_t id, uint32_t degree, nsecs_t horizon,
1029b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        Estimator* outEstimator) const {
1030b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    outEstimator->clear();
1031b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
1032b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    // Iterate over movement samples in reverse time order and collect samples.
1033b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    float x[HISTORY_SIZE];
1034b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    float y[HISTORY_SIZE];
1035b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    float time[HISTORY_SIZE];
1036b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    uint32_t m = 0;
1037b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    uint32_t index = mIndex;
1038b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    const Movement& newestMovement = mMovements[mIndex];
1039b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    do {
1040b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        const Movement& movement = mMovements[index];
1041b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        if (!movement.idBits.hasBit(id)) {
1042b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            break;
1043b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
1044b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
1045b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        nsecs_t age = newestMovement.eventTime - movement.eventTime;
1046b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        if (age > horizon) {
1047b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            break;
1048b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
1049b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
1050b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        const Position& position = movement.getPosition(id);
1051b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        x[m] = position.x;
1052b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        y[m] = position.y;
1053b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        time[m] = -age * 0.000000001f;
1054b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        index = (index == 0 ? HISTORY_SIZE : index) - 1;
1055b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    } while (++m < HISTORY_SIZE);
1056b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
1057b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    if (m == 0) {
1058b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        return false; // no data
1059b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
1060b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
1061b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    // Calculate a least squares polynomial fit.
1062b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    if (degree > Estimator::MAX_DEGREE) {
1063b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        degree = Estimator::MAX_DEGREE;
1064b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
1065b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    if (degree > m - 1) {
1066b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        degree = m - 1;
1067b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
1068b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    if (degree >= 1) {
1069b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        float xdet, ydet;
1070b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        uint32_t n = degree + 1;
1071b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        if (solveLeastSquares(time, x, m, n, outEstimator->xCoeff, &xdet)
1072b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                && solveLeastSquares(time, y, m, n, outEstimator->yCoeff, &ydet)) {
1073b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            outEstimator->degree = degree;
1074b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            outEstimator->confidence = xdet * ydet;
1075b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#if DEBUG_LEAST_SQUARES
1076b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            LOGD("estimate: degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f",
1077b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                    int(outEstimator->degree),
1078b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                    vectorToString(outEstimator->xCoeff, n).string(),
1079b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                    vectorToString(outEstimator->yCoeff, n).string(),
1080b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                    outEstimator->confidence);
1081b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#endif
1082b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            return true;
1083b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
1084b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
1085b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
1086b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    // No velocity data available for this pointer, but we do have its current position.
1087b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    outEstimator->xCoeff[0] = x[0];
1088b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    outEstimator->yCoeff[0] = y[0];
1089b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    outEstimator->degree = 0;
1090b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    outEstimator->confidence = 1;
1091b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    return true;
1092b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown}
1093b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
1094ace13b17866dc9136aeecf6dfaf7077f37434469Jeff Brown
109519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown// --- VelocityControl ---
109619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
109719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brownconst nsecs_t VelocityControl::STOP_TIME;
109819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
109919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff BrownVelocityControl::VelocityControl() {
110019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    reset();
110119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown}
110219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
110319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brownvoid VelocityControl::setParameters(const VelocityControlParameters& parameters) {
110419c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    mParameters = parameters;
110519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    reset();
110619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown}
110719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
110819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brownvoid VelocityControl::reset() {
110919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    mLastMovementTime = LLONG_MIN;
111019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    mRawPosition.x = 0;
111119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    mRawPosition.y = 0;
111219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    mVelocityTracker.clear();
111319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown}
111419c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
111519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brownvoid VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) {
111619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    if ((deltaX && *deltaX) || (deltaY && *deltaY)) {
111719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        if (eventTime >= mLastMovementTime + STOP_TIME) {
111819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#if DEBUG_ACCELERATION
111919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            LOGD("VelocityControl: stopped, last movement was %0.3fms ago",
112019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                    (eventTime - mLastMovementTime) * 0.000001f);
112119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#endif
112219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            reset();
112319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        }
112419c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
112519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        mLastMovementTime = eventTime;
112619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        if (deltaX) {
112719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            mRawPosition.x += *deltaX;
112819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        }
112919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        if (deltaY) {
113019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            mRawPosition.y += *deltaY;
113119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        }
113219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        mVelocityTracker.addMovement(eventTime, BitSet32(BitSet32::valueForBit(0)), &mRawPosition);
113319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
113419c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        float vx, vy;
113519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        float scale = mParameters.scale;
113619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        if (mVelocityTracker.getVelocity(0, &vx, &vy)) {
113719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            float speed = hypotf(vx, vy) * scale;
113819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            if (speed >= mParameters.highThreshold) {
113919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                // Apply full acceleration above the high speed threshold.
114019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                scale *= mParameters.acceleration;
114119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            } else if (speed > mParameters.lowThreshold) {
114219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                // Linearly interpolate the acceleration to apply between the low and high
114319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                // speed thresholds.
114419c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                scale *= 1 + (speed - mParameters.lowThreshold)
114519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                        / (mParameters.highThreshold - mParameters.lowThreshold)
114619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                        * (mParameters.acceleration - 1);
114719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            }
114819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
114919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#if DEBUG_ACCELERATION
115019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            LOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): "
115119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                    "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f",
115219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                    mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
115319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                    mParameters.acceleration,
115419c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                    vx, vy, speed, scale / mParameters.scale);
115519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#endif
115619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        } else {
115719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#if DEBUG_ACCELERATION
115819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            LOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity",
115919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                    mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
116019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown                    mParameters.acceleration);
116119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown#endif
116219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        }
116319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
116419c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        if (deltaX) {
116519c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            *deltaX *= scale;
116619c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        }
116719c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        if (deltaY) {
116819c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown            *deltaY *= scale;
116919c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown        }
117019c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown    }
117119c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown}
117219c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
117319c97d46fb57f87ff45d9e6ea7122b4eb21ede8cJeff Brown
117447e6b1b5eef8ee99872f278f66bc498c4fcca0d8Jeff Brown// --- InputDeviceInfo ---
11756d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
11766d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff BrownInputDeviceInfo::InputDeviceInfo() {
11776d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    initialize(-1, String8("uninitialized device info"));
11786d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
11796d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
11806d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff BrownInputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
11816d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown        mId(other.mId), mName(other.mName), mSources(other.mSources),
11826d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown        mKeyboardType(other.mKeyboardType),
11836d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown        mMotionRanges(other.mMotionRanges) {
11846d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
11856d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
11866d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff BrownInputDeviceInfo::~InputDeviceInfo() {
11876d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
11886d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
11896d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brownvoid InputDeviceInfo::initialize(int32_t id, const String8& name) {
11906d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    mId = id;
11916d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    mName = name;
11926d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    mSources = 0;
11936d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
11946d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    mMotionRanges.clear();
11956d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
11966d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
1197efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brownconst InputDeviceInfo::MotionRange* InputDeviceInfo::getMotionRange(
1198efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown        int32_t axis, uint32_t source) const {
1199efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown    size_t numRanges = mMotionRanges.size();
1200efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown    for (size_t i = 0; i < numRanges; i++) {
1201efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown        const MotionRange& range = mMotionRanges.itemAt(i);
1202efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown        if (range.axis == axis && range.source == source) {
1203efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown            return &range;
1204efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown        }
1205efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown    }
1206efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown    return NULL;
12076d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
12086d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
12096d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brownvoid InputDeviceInfo::addSource(uint32_t source) {
12106d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown    mSources |= source;
12116d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
12126d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
1213efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brownvoid InputDeviceInfo::addMotionRange(int32_t axis, uint32_t source, float min, float max,
12146d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown        float flat, float fuzz) {
1215efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown    MotionRange range = { axis, source, min, max, flat, fuzz };
1216efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown    mMotionRanges.add(range);
12176d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
12186d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
1219efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brownvoid InputDeviceInfo::addMotionRange(const MotionRange& range) {
1220efd3266b719eed5f1b217021c0a9e76e4b274b06Jeff Brown    mMotionRanges.add(range);
12216d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown}
12226d0fec2de3601821f4f44eeb7d7deedebb2b7117Jeff Brown
122346b9ac0ae2162309774a7478cd9d4e578747bfc2Jeff Brown} // namespace android
1224