1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/gonk/libui/VelocityTracker.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,269 @@ 1.4 +/* 1.5 + * Copyright (C) 2012 The Android Open Source Project 1.6 + * 1.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.8 + * you may not use this file except in compliance with the License. 1.9 + * You may obtain a copy of the License at 1.10 + * 1.11 + * http://www.apache.org/licenses/LICENSE-2.0 1.12 + * 1.13 + * Unless required by applicable law or agreed to in writing, software 1.14 + * distributed under the License is distributed on an "AS IS" BASIS, 1.15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.16 + * See the License for the specific language governing permissions and 1.17 + * limitations under the License. 1.18 + */ 1.19 + 1.20 +#ifndef _ANDROIDFW_VELOCITY_TRACKER_H 1.21 +#define _ANDROIDFW_VELOCITY_TRACKER_H 1.22 + 1.23 +#include "Input.h" 1.24 +#include <utils/Timers.h> 1.25 +#include <utils/BitSet.h> 1.26 + 1.27 +namespace android { 1.28 + 1.29 +class VelocityTrackerStrategy; 1.30 + 1.31 +/* 1.32 + * Calculates the velocity of pointer movements over time. 1.33 + */ 1.34 +class VelocityTracker { 1.35 +public: 1.36 + struct Position { 1.37 + float x, y; 1.38 + }; 1.39 + 1.40 + struct Estimator { 1.41 + static const size_t MAX_DEGREE = 4; 1.42 + 1.43 + // Estimator time base. 1.44 + nsecs_t time; 1.45 + 1.46 + // Polynomial coefficients describing motion in X and Y. 1.47 + float xCoeff[MAX_DEGREE + 1], yCoeff[MAX_DEGREE + 1]; 1.48 + 1.49 + // Polynomial degree (number of coefficients), or zero if no information is 1.50 + // available. 1.51 + uint32_t degree; 1.52 + 1.53 + // Confidence (coefficient of determination), between 0 (no fit) and 1 (perfect fit). 1.54 + float confidence; 1.55 + 1.56 + inline void clear() { 1.57 + time = 0; 1.58 + degree = 0; 1.59 + confidence = 0; 1.60 + for (size_t i = 0; i <= MAX_DEGREE; i++) { 1.61 + xCoeff[i] = 0; 1.62 + yCoeff[i] = 0; 1.63 + } 1.64 + } 1.65 + }; 1.66 + 1.67 + // Creates a velocity tracker using the specified strategy. 1.68 + // If strategy is NULL, uses the default strategy for the platform. 1.69 + VelocityTracker(const char* strategy = NULL); 1.70 + 1.71 + ~VelocityTracker(); 1.72 + 1.73 + // Resets the velocity tracker state. 1.74 + void clear(); 1.75 + 1.76 + // Resets the velocity tracker state for specific pointers. 1.77 + // Call this method when some pointers have changed and may be reusing 1.78 + // an id that was assigned to a different pointer earlier. 1.79 + void clearPointers(BitSet32 idBits); 1.80 + 1.81 + // Adds movement information for a set of pointers. 1.82 + // The idBits bitfield specifies the pointer ids of the pointers whose positions 1.83 + // are included in the movement. 1.84 + // The positions array contains position information for each pointer in order by 1.85 + // increasing id. Its size should be equal to the number of one bits in idBits. 1.86 + void addMovement(nsecs_t eventTime, BitSet32 idBits, const Position* positions); 1.87 + 1.88 + // Adds movement information for all pointers in a MotionEvent, including historical samples. 1.89 + void addMovement(const MotionEvent* event); 1.90 + 1.91 + // Gets the velocity of the specified pointer id in position units per second. 1.92 + // Returns false and sets the velocity components to zero if there is 1.93 + // insufficient movement information for the pointer. 1.94 + bool getVelocity(uint32_t id, float* outVx, float* outVy) const; 1.95 + 1.96 + // Gets an estimator for the recent movements of the specified pointer id. 1.97 + // Returns false and clears the estimator if there is no information available 1.98 + // about the pointer. 1.99 + bool getEstimator(uint32_t id, Estimator* outEstimator) const; 1.100 + 1.101 + // Gets the active pointer id, or -1 if none. 1.102 + inline int32_t getActivePointerId() const { return mActivePointerId; } 1.103 + 1.104 + // Gets a bitset containing all pointer ids from the most recent movement. 1.105 + inline BitSet32 getCurrentPointerIdBits() const { return mCurrentPointerIdBits; } 1.106 + 1.107 +private: 1.108 + static const char* DEFAULT_STRATEGY; 1.109 + 1.110 + nsecs_t mLastEventTime; 1.111 + BitSet32 mCurrentPointerIdBits; 1.112 + int32_t mActivePointerId; 1.113 + VelocityTrackerStrategy* mStrategy; 1.114 + 1.115 + bool configureStrategy(const char* strategy); 1.116 + 1.117 + static VelocityTrackerStrategy* createStrategy(const char* strategy); 1.118 +}; 1.119 + 1.120 + 1.121 +/* 1.122 + * Implements a particular velocity tracker algorithm. 1.123 + */ 1.124 +class VelocityTrackerStrategy { 1.125 +protected: 1.126 + VelocityTrackerStrategy() { } 1.127 + 1.128 +public: 1.129 + virtual ~VelocityTrackerStrategy() { } 1.130 + 1.131 + virtual void clear() = 0; 1.132 + virtual void clearPointers(BitSet32 idBits) = 0; 1.133 + virtual void addMovement(nsecs_t eventTime, BitSet32 idBits, 1.134 + const VelocityTracker::Position* positions) = 0; 1.135 + virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const = 0; 1.136 +}; 1.137 + 1.138 + 1.139 +/* 1.140 + * Velocity tracker algorithm based on least-squares linear regression. 1.141 + */ 1.142 +class LeastSquaresVelocityTrackerStrategy : public VelocityTrackerStrategy { 1.143 +public: 1.144 + enum Weighting { 1.145 + // No weights applied. All data points are equally reliable. 1.146 + WEIGHTING_NONE, 1.147 + 1.148 + // Weight by time delta. Data points clustered together are weighted less. 1.149 + WEIGHTING_DELTA, 1.150 + 1.151 + // Weight such that points within a certain horizon are weighed more than those 1.152 + // outside of that horizon. 1.153 + WEIGHTING_CENTRAL, 1.154 + 1.155 + // Weight such that points older than a certain amount are weighed less. 1.156 + WEIGHTING_RECENT, 1.157 + }; 1.158 + 1.159 + // Degree must be no greater than Estimator::MAX_DEGREE. 1.160 + LeastSquaresVelocityTrackerStrategy(uint32_t degree, Weighting weighting = WEIGHTING_NONE); 1.161 + virtual ~LeastSquaresVelocityTrackerStrategy(); 1.162 + 1.163 + virtual void clear(); 1.164 + virtual void clearPointers(BitSet32 idBits); 1.165 + virtual void addMovement(nsecs_t eventTime, BitSet32 idBits, 1.166 + const VelocityTracker::Position* positions); 1.167 + virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const; 1.168 + 1.169 +private: 1.170 + // Sample horizon. 1.171 + // We don't use too much history by default since we want to react to quick 1.172 + // changes in direction. 1.173 + static const nsecs_t HORIZON = 100 * 1000000; // 100 ms 1.174 + 1.175 + // Number of samples to keep. 1.176 + static const uint32_t HISTORY_SIZE = 20; 1.177 + 1.178 + struct Movement { 1.179 + nsecs_t eventTime; 1.180 + BitSet32 idBits; 1.181 + VelocityTracker::Position positions[MAX_POINTERS]; 1.182 + 1.183 + inline const VelocityTracker::Position& getPosition(uint32_t id) const { 1.184 + return positions[idBits.getIndexOfBit(id)]; 1.185 + } 1.186 + }; 1.187 + 1.188 + float chooseWeight(uint32_t index) const; 1.189 + 1.190 + const uint32_t mDegree; 1.191 + const Weighting mWeighting; 1.192 + uint32_t mIndex; 1.193 + Movement mMovements[HISTORY_SIZE]; 1.194 +}; 1.195 + 1.196 + 1.197 +/* 1.198 + * Velocity tracker algorithm that uses an IIR filter. 1.199 + */ 1.200 +class IntegratingVelocityTrackerStrategy : public VelocityTrackerStrategy { 1.201 +public: 1.202 + // Degree must be 1 or 2. 1.203 + IntegratingVelocityTrackerStrategy(uint32_t degree); 1.204 + ~IntegratingVelocityTrackerStrategy(); 1.205 + 1.206 + virtual void clear(); 1.207 + virtual void clearPointers(BitSet32 idBits); 1.208 + virtual void addMovement(nsecs_t eventTime, BitSet32 idBits, 1.209 + const VelocityTracker::Position* positions); 1.210 + virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const; 1.211 + 1.212 +private: 1.213 + // Current state estimate for a particular pointer. 1.214 + struct State { 1.215 + nsecs_t updateTime; 1.216 + uint32_t degree; 1.217 + 1.218 + float xpos, xvel, xaccel; 1.219 + float ypos, yvel, yaccel; 1.220 + }; 1.221 + 1.222 + const uint32_t mDegree; 1.223 + BitSet32 mPointerIdBits; 1.224 + State mPointerState[MAX_POINTER_ID + 1]; 1.225 + 1.226 + void initState(State& state, nsecs_t eventTime, float xpos, float ypos) const; 1.227 + void updateState(State& state, nsecs_t eventTime, float xpos, float ypos) const; 1.228 + void populateEstimator(const State& state, VelocityTracker::Estimator* outEstimator) const; 1.229 +}; 1.230 + 1.231 + 1.232 +/* 1.233 + * Velocity tracker strategy used prior to ICS. 1.234 + */ 1.235 +class LegacyVelocityTrackerStrategy : public VelocityTrackerStrategy { 1.236 +public: 1.237 + LegacyVelocityTrackerStrategy(); 1.238 + virtual ~LegacyVelocityTrackerStrategy(); 1.239 + 1.240 + virtual void clear(); 1.241 + virtual void clearPointers(BitSet32 idBits); 1.242 + virtual void addMovement(nsecs_t eventTime, BitSet32 idBits, 1.243 + const VelocityTracker::Position* positions); 1.244 + virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const; 1.245 + 1.246 +private: 1.247 + // Oldest sample to consider when calculating the velocity. 1.248 + static const nsecs_t HORIZON = 200 * 1000000; // 100 ms 1.249 + 1.250 + // Number of samples to keep. 1.251 + static const uint32_t HISTORY_SIZE = 20; 1.252 + 1.253 + // The minimum duration between samples when estimating velocity. 1.254 + static const nsecs_t MIN_DURATION = 10 * 1000000; // 10 ms 1.255 + 1.256 + struct Movement { 1.257 + nsecs_t eventTime; 1.258 + BitSet32 idBits; 1.259 + VelocityTracker::Position positions[MAX_POINTERS]; 1.260 + 1.261 + inline const VelocityTracker::Position& getPosition(uint32_t id) const { 1.262 + return positions[idBits.getIndexOfBit(id)]; 1.263 + } 1.264 + }; 1.265 + 1.266 + uint32_t mIndex; 1.267 + Movement mMovements[HISTORY_SIZE]; 1.268 +}; 1.269 + 1.270 +} // namespace android 1.271 + 1.272 +#endif // _ANDROIDFW_VELOCITY_TRACKER_H