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 ⦥ 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