Loading include/input/VelocityControl.h +1 −1 Original line number Diff line number Diff line Loading @@ -98,7 +98,7 @@ private: VelocityControlParameters mParameters; nsecs_t mLastMovementTime; float mRawPositionX, mRawPositionY; VelocityTracker::Position mRawPosition; VelocityTracker mVelocityTracker; }; Loading include/input/VelocityTracker.h +45 −74 Original line number Diff line number Diff line Loading @@ -20,8 +20,6 @@ #include <input/Input.h> #include <utils/BitSet.h> #include <utils/Timers.h> #include <map> #include <set> namespace android { Loading @@ -48,14 +46,18 @@ public: MAX = LEGACY, }; struct Position { float x, y; }; struct Estimator { static const size_t MAX_DEGREE = 4; // Estimator time base. nsecs_t time; // Polynomial coefficients describing motion. float coeff[MAX_DEGREE + 1]; // Polynomial coefficients describing motion in X and Y. float xCoeff[MAX_DEGREE + 1], yCoeff[MAX_DEGREE + 1]; // Polynomial degree (number of coefficients), or zero if no information is // available. Loading @@ -69,40 +71,14 @@ public: degree = 0; confidence = 0; for (size_t i = 0; i <= MAX_DEGREE; i++) { coeff[i] = 0; xCoeff[i] = 0; yCoeff[i] = 0; } } }; /* * Contains all available velocity data from a VelocityTracker. */ struct ComputedVelocity { inline std::optional<float> getVelocity(int32_t axis, uint32_t id) const { const auto& axisVelocities = mVelocities.find(axis); if (axisVelocities == mVelocities.end()) { return {}; } const auto& axisIdVelocity = axisVelocities->second.find(id); if (axisIdVelocity == axisVelocities->second.end()) { return {}; } return axisIdVelocity->second; } inline void addVelocity(int32_t axis, uint32_t id, float velocity) { mVelocities[axis][id] = velocity; } private: std::map<int32_t /*axis*/, std::map<int32_t /*pointerId*/, float /*velocity*/>> mVelocities; }; // Creates a velocity tracker using the specified strategy for each supported axis. // Creates a velocity tracker using the specified strategy. // If strategy is not provided, uses the default strategy for the platform. // TODO(b/32830165): support axis-specific strategies. VelocityTracker(const Strategy strategy = Strategy::DEFAULT); ~VelocityTracker(); Loading @@ -116,57 +92,45 @@ public: void clearPointers(BitSet32 idBits); // Adds movement information for a set of pointers. // The idBits bitfield specifies the pointer ids of the pointers whose data points // The idBits bitfield specifies the pointer ids of the pointers whose positions // are included in the movement. // The positions map contains a mapping of an axis to positions array. // The positions arrays contain information for each pointer in order by increasing id. // Each array's size should be equal to the number of one bits in idBits. void addMovement(nsecs_t eventTime, BitSet32 idBits, const std::map<int32_t, std::vector<float>>& positions); // The positions array contains position information for each pointer in order by // increasing id. Its size should be equal to the number of one bits in idBits. void addMovement(nsecs_t eventTime, BitSet32 idBits, const std::vector<Position>& positions); // Adds movement information for all pointers in a MotionEvent, including historical samples. void addMovement(const MotionEvent* event); // Returns the velocity of the specified pointer id and axis in position units per second. // Returns empty optional if there is insufficient movement information for the pointer, or if // the given axis is not supported for velocity tracking. std::optional<float> getVelocity(int32_t axis, uint32_t id) const; // Populates a ComputedVelocity instance with all available velocity data, using the given units // (reference: units == 1 means "per millisecond"), and clamping each velocity between // [-maxVelocity, maxVelocity], inclusive. void populateComputedVelocity(ComputedVelocity& computedVelocity, int32_t units, float maxVelocity); // Gets the velocity of the specified pointer id in position units per second. // Returns false and sets the velocity components to zero if there is // insufficient movement information for the pointer. bool getVelocity(uint32_t id, float* outVx, float* outVy) const; // Gets an estimator for the recent movements of the specified pointer id for the given axis. // Gets an estimator for the recent movements of the specified pointer id. // Returns false and clears the estimator if there is no information available // about the pointer. bool getEstimator(int32_t axis, uint32_t id, Estimator* outEstimator) const; bool getEstimator(uint32_t id, Estimator* outEstimator) const; // Gets the active pointer id, or -1 if none. inline int32_t getActivePointerId() const { return mActivePointerId; } // Gets a bitset containing all pointer ids from the most recent movement. inline BitSet32 getCurrentPointerIdBits() const { return mCurrentPointerIdBits; } private: // The default velocity tracker strategy. // Although other strategies are available for testing and comparison purposes, // this is the strategy that applications will actually use. Be very careful // when adjusting the default strategy because it can dramatically affect // (often in a bad way) the user experience. // TODO(b/32830165): define default strategy per axis. static const Strategy DEFAULT_STRATEGY = Strategy::LSQ2; // Set of all axes supported for velocity tracking. static const std::set<int32_t> SUPPORTED_AXES; // Axes specifying location on a 2D plane (i.e. X and Y). static const std::set<int32_t> PLANAR_AXES; nsecs_t mLastEventTime; BitSet32 mCurrentPointerIdBits; int32_t mActivePointerId; std::map<int32_t /*axis*/, std::unique_ptr<VelocityTrackerStrategy>> mStrategies; std::unique_ptr<VelocityTrackerStrategy> mStrategy; void configureStrategy(int32_t axis, const Strategy strategy); bool configureStrategy(const Strategy strategy); static std::unique_ptr<VelocityTrackerStrategy> createStrategy(const Strategy strategy); }; Loading @@ -185,7 +149,7 @@ public: virtual void clear() = 0; virtual void clearPointers(BitSet32 idBits) = 0; virtual void addMovement(nsecs_t eventTime, BitSet32 idBits, const std::vector<float>& positions) = 0; const std::vector<VelocityTracker::Position>& positions) = 0; virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const = 0; }; Loading Loading @@ -217,7 +181,7 @@ public: virtual void clear(); virtual void clearPointers(BitSet32 idBits); void addMovement(nsecs_t eventTime, BitSet32 idBits, const std::vector<float>& positions) override; const std::vector<VelocityTracker::Position>& positions) override; virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const; private: Loading @@ -232,9 +196,11 @@ private: struct Movement { nsecs_t eventTime; BitSet32 idBits; float positions[MAX_POINTERS]; VelocityTracker::Position positions[MAX_POINTERS]; inline float getPosition(uint32_t id) const { return positions[idBits.getIndexOfBit(id)]; } inline const VelocityTracker::Position& getPosition(uint32_t id) const { return positions[idBits.getIndexOfBit(id)]; } }; float chooseWeight(uint32_t index) const; Loading @@ -258,7 +224,7 @@ public: virtual void clear(); virtual void clearPointers(BitSet32 idBits); void addMovement(nsecs_t eventTime, BitSet32 idBits, const std::vector<float>& positions) override; const std::vector<VelocityTracker::Position>& positions) override; virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const; private: Loading @@ -267,15 +233,16 @@ private: nsecs_t updateTime; uint32_t degree; float pos, vel, accel; float xpos, xvel, xaccel; float ypos, yvel, yaccel; }; const uint32_t mDegree; BitSet32 mPointerIdBits; State mPointerState[MAX_POINTER_ID + 1]; void initState(State& state, nsecs_t eventTime, float pos) const; void updateState(State& state, nsecs_t eventTime, float pos) const; void initState(State& state, nsecs_t eventTime, float xpos, float ypos) const; void updateState(State& state, nsecs_t eventTime, float xpos, float ypos) const; void populateEstimator(const State& state, VelocityTracker::Estimator* outEstimator) const; }; Loading @@ -291,7 +258,7 @@ public: virtual void clear(); virtual void clearPointers(BitSet32 idBits); void addMovement(nsecs_t eventTime, BitSet32 idBits, const std::vector<float>& positions) override; const std::vector<VelocityTracker::Position>& positions) override; virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const; private: Loading @@ -307,9 +274,11 @@ private: struct Movement { nsecs_t eventTime; BitSet32 idBits; float positions[MAX_POINTERS]; VelocityTracker::Position positions[MAX_POINTERS]; inline float getPosition(uint32_t id) const { return positions[idBits.getIndexOfBit(id)]; } inline const VelocityTracker::Position& getPosition(uint32_t id) const { return positions[idBits.getIndexOfBit(id)]; } }; uint32_t mIndex; Loading @@ -324,7 +293,7 @@ public: virtual void clear(); virtual void clearPointers(BitSet32 idBits); void addMovement(nsecs_t eventTime, BitSet32 idBits, const std::vector<float>& positions) override; const std::vector<VelocityTracker::Position>& positions) override; virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const; private: Loading @@ -339,9 +308,11 @@ private: struct Movement { nsecs_t eventTime; BitSet32 idBits; float positions[MAX_POINTERS]; VelocityTracker::Position positions[MAX_POINTERS]; inline float getPosition(uint32_t id) const { return positions[idBits.getIndexOfBit(id)]; } inline const VelocityTracker::Position& getPosition(uint32_t id) const { return positions[idBits.getIndexOfBit(id)]; } }; size_t mIndex; Loading libs/input/VelocityControl.cpp +12 −14 Original line number Diff line number Diff line Loading @@ -44,8 +44,8 @@ void VelocityControl::setParameters(const VelocityControlParameters& parameters) void VelocityControl::reset() { mLastMovementTime = LLONG_MIN; mRawPositionX = 0; mRawPositionY = 0; mRawPosition.x = 0; mRawPosition.y = 0; mVelocityTracker.clear(); } Loading @@ -61,20 +61,17 @@ void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) { mLastMovementTime = eventTime; if (deltaX) { mRawPositionX += *deltaX; mRawPosition.x += *deltaX; } if (deltaY) { mRawPositionY += *deltaY; mRawPosition.y += *deltaY; } mVelocityTracker.addMovement(eventTime, BitSet32(BitSet32::valueForBit(0)), {{AMOTION_EVENT_AXIS_X, {mRawPositionX}}, {AMOTION_EVENT_AXIS_Y, {mRawPositionY}}}); mVelocityTracker.addMovement(eventTime, BitSet32(BitSet32::valueForBit(0)), {mRawPosition}); std::optional<float> vx = mVelocityTracker.getVelocity(AMOTION_EVENT_AXIS_X, 0); std::optional<float> vy = mVelocityTracker.getVelocity(AMOTION_EVENT_AXIS_Y, 0); float vx, vy; float scale = mParameters.scale; if (vx && vy) { float speed = hypotf(*vx, *vy) * scale; if (mVelocityTracker.getVelocity(0, &vx, &vy)) { float speed = hypotf(vx, vy) * scale; if (speed >= mParameters.highThreshold) { // Apply full acceleration above the high speed threshold. scale *= mParameters.acceleration; Loading @@ -90,7 +87,8 @@ void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) { ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): " "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f", mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold, mParameters.acceleration, *vx, *vy, speed, scale / mParameters.scale); mParameters.acceleration, vx, vy, speed, scale / mParameters.scale); } } else { Loading Loading
include/input/VelocityControl.h +1 −1 Original line number Diff line number Diff line Loading @@ -98,7 +98,7 @@ private: VelocityControlParameters mParameters; nsecs_t mLastMovementTime; float mRawPositionX, mRawPositionY; VelocityTracker::Position mRawPosition; VelocityTracker mVelocityTracker; }; Loading
include/input/VelocityTracker.h +45 −74 Original line number Diff line number Diff line Loading @@ -20,8 +20,6 @@ #include <input/Input.h> #include <utils/BitSet.h> #include <utils/Timers.h> #include <map> #include <set> namespace android { Loading @@ -48,14 +46,18 @@ public: MAX = LEGACY, }; struct Position { float x, y; }; struct Estimator { static const size_t MAX_DEGREE = 4; // Estimator time base. nsecs_t time; // Polynomial coefficients describing motion. float coeff[MAX_DEGREE + 1]; // Polynomial coefficients describing motion in X and Y. float xCoeff[MAX_DEGREE + 1], yCoeff[MAX_DEGREE + 1]; // Polynomial degree (number of coefficients), or zero if no information is // available. Loading @@ -69,40 +71,14 @@ public: degree = 0; confidence = 0; for (size_t i = 0; i <= MAX_DEGREE; i++) { coeff[i] = 0; xCoeff[i] = 0; yCoeff[i] = 0; } } }; /* * Contains all available velocity data from a VelocityTracker. */ struct ComputedVelocity { inline std::optional<float> getVelocity(int32_t axis, uint32_t id) const { const auto& axisVelocities = mVelocities.find(axis); if (axisVelocities == mVelocities.end()) { return {}; } const auto& axisIdVelocity = axisVelocities->second.find(id); if (axisIdVelocity == axisVelocities->second.end()) { return {}; } return axisIdVelocity->second; } inline void addVelocity(int32_t axis, uint32_t id, float velocity) { mVelocities[axis][id] = velocity; } private: std::map<int32_t /*axis*/, std::map<int32_t /*pointerId*/, float /*velocity*/>> mVelocities; }; // Creates a velocity tracker using the specified strategy for each supported axis. // Creates a velocity tracker using the specified strategy. // If strategy is not provided, uses the default strategy for the platform. // TODO(b/32830165): support axis-specific strategies. VelocityTracker(const Strategy strategy = Strategy::DEFAULT); ~VelocityTracker(); Loading @@ -116,57 +92,45 @@ public: void clearPointers(BitSet32 idBits); // Adds movement information for a set of pointers. // The idBits bitfield specifies the pointer ids of the pointers whose data points // The idBits bitfield specifies the pointer ids of the pointers whose positions // are included in the movement. // The positions map contains a mapping of an axis to positions array. // The positions arrays contain information for each pointer in order by increasing id. // Each array's size should be equal to the number of one bits in idBits. void addMovement(nsecs_t eventTime, BitSet32 idBits, const std::map<int32_t, std::vector<float>>& positions); // The positions array contains position information for each pointer in order by // increasing id. Its size should be equal to the number of one bits in idBits. void addMovement(nsecs_t eventTime, BitSet32 idBits, const std::vector<Position>& positions); // Adds movement information for all pointers in a MotionEvent, including historical samples. void addMovement(const MotionEvent* event); // Returns the velocity of the specified pointer id and axis in position units per second. // Returns empty optional if there is insufficient movement information for the pointer, or if // the given axis is not supported for velocity tracking. std::optional<float> getVelocity(int32_t axis, uint32_t id) const; // Populates a ComputedVelocity instance with all available velocity data, using the given units // (reference: units == 1 means "per millisecond"), and clamping each velocity between // [-maxVelocity, maxVelocity], inclusive. void populateComputedVelocity(ComputedVelocity& computedVelocity, int32_t units, float maxVelocity); // Gets the velocity of the specified pointer id in position units per second. // Returns false and sets the velocity components to zero if there is // insufficient movement information for the pointer. bool getVelocity(uint32_t id, float* outVx, float* outVy) const; // Gets an estimator for the recent movements of the specified pointer id for the given axis. // Gets an estimator for the recent movements of the specified pointer id. // Returns false and clears the estimator if there is no information available // about the pointer. bool getEstimator(int32_t axis, uint32_t id, Estimator* outEstimator) const; bool getEstimator(uint32_t id, Estimator* outEstimator) const; // Gets the active pointer id, or -1 if none. inline int32_t getActivePointerId() const { return mActivePointerId; } // Gets a bitset containing all pointer ids from the most recent movement. inline BitSet32 getCurrentPointerIdBits() const { return mCurrentPointerIdBits; } private: // The default velocity tracker strategy. // Although other strategies are available for testing and comparison purposes, // this is the strategy that applications will actually use. Be very careful // when adjusting the default strategy because it can dramatically affect // (often in a bad way) the user experience. // TODO(b/32830165): define default strategy per axis. static const Strategy DEFAULT_STRATEGY = Strategy::LSQ2; // Set of all axes supported for velocity tracking. static const std::set<int32_t> SUPPORTED_AXES; // Axes specifying location on a 2D plane (i.e. X and Y). static const std::set<int32_t> PLANAR_AXES; nsecs_t mLastEventTime; BitSet32 mCurrentPointerIdBits; int32_t mActivePointerId; std::map<int32_t /*axis*/, std::unique_ptr<VelocityTrackerStrategy>> mStrategies; std::unique_ptr<VelocityTrackerStrategy> mStrategy; void configureStrategy(int32_t axis, const Strategy strategy); bool configureStrategy(const Strategy strategy); static std::unique_ptr<VelocityTrackerStrategy> createStrategy(const Strategy strategy); }; Loading @@ -185,7 +149,7 @@ public: virtual void clear() = 0; virtual void clearPointers(BitSet32 idBits) = 0; virtual void addMovement(nsecs_t eventTime, BitSet32 idBits, const std::vector<float>& positions) = 0; const std::vector<VelocityTracker::Position>& positions) = 0; virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const = 0; }; Loading Loading @@ -217,7 +181,7 @@ public: virtual void clear(); virtual void clearPointers(BitSet32 idBits); void addMovement(nsecs_t eventTime, BitSet32 idBits, const std::vector<float>& positions) override; const std::vector<VelocityTracker::Position>& positions) override; virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const; private: Loading @@ -232,9 +196,11 @@ private: struct Movement { nsecs_t eventTime; BitSet32 idBits; float positions[MAX_POINTERS]; VelocityTracker::Position positions[MAX_POINTERS]; inline float getPosition(uint32_t id) const { return positions[idBits.getIndexOfBit(id)]; } inline const VelocityTracker::Position& getPosition(uint32_t id) const { return positions[idBits.getIndexOfBit(id)]; } }; float chooseWeight(uint32_t index) const; Loading @@ -258,7 +224,7 @@ public: virtual void clear(); virtual void clearPointers(BitSet32 idBits); void addMovement(nsecs_t eventTime, BitSet32 idBits, const std::vector<float>& positions) override; const std::vector<VelocityTracker::Position>& positions) override; virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const; private: Loading @@ -267,15 +233,16 @@ private: nsecs_t updateTime; uint32_t degree; float pos, vel, accel; float xpos, xvel, xaccel; float ypos, yvel, yaccel; }; const uint32_t mDegree; BitSet32 mPointerIdBits; State mPointerState[MAX_POINTER_ID + 1]; void initState(State& state, nsecs_t eventTime, float pos) const; void updateState(State& state, nsecs_t eventTime, float pos) const; void initState(State& state, nsecs_t eventTime, float xpos, float ypos) const; void updateState(State& state, nsecs_t eventTime, float xpos, float ypos) const; void populateEstimator(const State& state, VelocityTracker::Estimator* outEstimator) const; }; Loading @@ -291,7 +258,7 @@ public: virtual void clear(); virtual void clearPointers(BitSet32 idBits); void addMovement(nsecs_t eventTime, BitSet32 idBits, const std::vector<float>& positions) override; const std::vector<VelocityTracker::Position>& positions) override; virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const; private: Loading @@ -307,9 +274,11 @@ private: struct Movement { nsecs_t eventTime; BitSet32 idBits; float positions[MAX_POINTERS]; VelocityTracker::Position positions[MAX_POINTERS]; inline float getPosition(uint32_t id) const { return positions[idBits.getIndexOfBit(id)]; } inline const VelocityTracker::Position& getPosition(uint32_t id) const { return positions[idBits.getIndexOfBit(id)]; } }; uint32_t mIndex; Loading @@ -324,7 +293,7 @@ public: virtual void clear(); virtual void clearPointers(BitSet32 idBits); void addMovement(nsecs_t eventTime, BitSet32 idBits, const std::vector<float>& positions) override; const std::vector<VelocityTracker::Position>& positions) override; virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const; private: Loading @@ -339,9 +308,11 @@ private: struct Movement { nsecs_t eventTime; BitSet32 idBits; float positions[MAX_POINTERS]; VelocityTracker::Position positions[MAX_POINTERS]; inline float getPosition(uint32_t id) const { return positions[idBits.getIndexOfBit(id)]; } inline const VelocityTracker::Position& getPosition(uint32_t id) const { return positions[idBits.getIndexOfBit(id)]; } }; size_t mIndex; Loading
libs/input/VelocityControl.cpp +12 −14 Original line number Diff line number Diff line Loading @@ -44,8 +44,8 @@ void VelocityControl::setParameters(const VelocityControlParameters& parameters) void VelocityControl::reset() { mLastMovementTime = LLONG_MIN; mRawPositionX = 0; mRawPositionY = 0; mRawPosition.x = 0; mRawPosition.y = 0; mVelocityTracker.clear(); } Loading @@ -61,20 +61,17 @@ void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) { mLastMovementTime = eventTime; if (deltaX) { mRawPositionX += *deltaX; mRawPosition.x += *deltaX; } if (deltaY) { mRawPositionY += *deltaY; mRawPosition.y += *deltaY; } mVelocityTracker.addMovement(eventTime, BitSet32(BitSet32::valueForBit(0)), {{AMOTION_EVENT_AXIS_X, {mRawPositionX}}, {AMOTION_EVENT_AXIS_Y, {mRawPositionY}}}); mVelocityTracker.addMovement(eventTime, BitSet32(BitSet32::valueForBit(0)), {mRawPosition}); std::optional<float> vx = mVelocityTracker.getVelocity(AMOTION_EVENT_AXIS_X, 0); std::optional<float> vy = mVelocityTracker.getVelocity(AMOTION_EVENT_AXIS_Y, 0); float vx, vy; float scale = mParameters.scale; if (vx && vy) { float speed = hypotf(*vx, *vy) * scale; if (mVelocityTracker.getVelocity(0, &vx, &vy)) { float speed = hypotf(vx, vy) * scale; if (speed >= mParameters.highThreshold) { // Apply full acceleration above the high speed threshold. scale *= mParameters.acceleration; Loading @@ -90,7 +87,8 @@ void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) { ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): " "vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f", mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold, mParameters.acceleration, *vx, *vy, speed, scale / mParameters.scale); mParameters.acceleration, vx, vy, speed, scale / mParameters.scale); } } else { Loading