@@ -752,6 +752,7 @@ void VelocityTracker::addMovement(const MotionEvent* event) {
752752
753753 switch (actionMasked) {
754754 case AMOTION_EVENT_ACTION_DOWN:
755+ case AMOTION_EVENT_ACTION_HOVER_ENTER:
755756 // Clear all pointers on down before adding the new movement.
756757 clear ();
757758 break ;
@@ -764,12 +765,11 @@ void VelocityTracker::addMovement(const MotionEvent* event) {
764765 clearPointers (downIdBits);
765766 break ;
766767 }
767- case AMOTION_EVENT_ACTION_OUTSIDE:
768- case AMOTION_EVENT_ACTION_CANCEL:
769- case AMOTION_EVENT_ACTION_SCROLL:
770- case AMOTION_EVENT_ACTION_UP:
771- case AMOTION_EVENT_ACTION_POINTER_UP:
772- // Ignore these actions because they do not convey any new information about
768+ case AMOTION_EVENT_ACTION_MOVE:
769+ case AMOTION_EVENT_ACTION_HOVER_MOVE:
770+ break ;
771+ default :
772+ // Ignore all other actions because they do not convey any new information about
773773 // pointer movement. We also want to preserve the last known velocity of the pointers.
774774 // Note that ACTION_UP and ACTION_POINTER_UP always report the last known position
775775 // of the pointers that went up. ACTION_POINTER_UP does include the new position of
@@ -814,68 +814,36 @@ void VelocityTracker::addMovement(const MotionEvent* event) {
814814bool VelocityTracker::getVelocity (uint32_t id, float * outVx, float * outVy) const {
815815 const Movement& newestMovement = mMovements [mIndex ];
816816 if (newestMovement.idBits .hasBit (id)) {
817- // Find the oldest sample that contains the pointer and that is not older than MAX_AGE.
818- nsecs_t minTime = newestMovement.eventTime - MAX_AGE;
819- uint32_t oldestIndex = mIndex ;
820- uint32_t numTouches = 1 ;
821- do {
822- uint32_t nextOldestIndex = (oldestIndex == 0 ? HISTORY_SIZE : oldestIndex) - 1 ;
823- const Movement& nextOldestMovement = mMovements [nextOldestIndex];
824- if (!nextOldestMovement.idBits .hasBit (id)
825- || nextOldestMovement.eventTime < minTime) {
826- break ;
827- }
828- oldestIndex = nextOldestIndex;
829- } while (++numTouches < HISTORY_SIZE);
830-
831- // Calculate an exponentially weighted moving average of the velocity estimate
832- // at different points in time measured relative to the oldest sample.
833- // This is essentially an IIR filter. Newer samples are weighted more heavily
834- // than older samples. Samples at equal time points are weighted more or less
835- // equally.
836- //
837- // One tricky problem is that the sample data may be poorly conditioned.
838- // Sometimes samples arrive very close together in time which can cause us to
839- // overestimate the velocity at that time point. Most samples might be measured
840- // 16ms apart but some consecutive samples could be only 0.5sm apart because
841- // the hardware or driver reports them irregularly or in bursts.
817+ const Position& newestPosition = newestMovement.getPosition (id);
842818 float accumVx = 0 ;
843819 float accumVy = 0 ;
844- uint32_t index = oldestIndex;
845- uint32_t samplesUsed = 0 ;
846- const Movement& oldestMovement = mMovements [oldestIndex];
847- const Position& oldestPosition =
848- oldestMovement.positions [oldestMovement.idBits .getIndexOfBit (id)];
849- nsecs_t lastDuration = 0 ;
850-
851- while (numTouches-- > 1 ) {
852- if (++index == HISTORY_SIZE) {
853- index = 0 ;
854- }
820+ float duration = 0 ;
821+
822+ // Iterate over movement samples in reverse time order and accumulate velocity.
823+ uint32_t index = mIndex ;
824+ do {
825+ index = (index == 0 ? HISTORY_SIZE : index) - 1 ;
855826 const Movement& movement = mMovements [index];
856- nsecs_t duration = movement.eventTime - oldestMovement.eventTime ;
857-
858- // If the duration between samples is small, we may significantly overestimate
859- // the velocity. Consequently, we impose a minimum duration constraint on the
860- // samples that we include in the calculation.
861- if (duration >= MIN_DURATION) {
862- const Position& position = movement.positions [movement.idBits .getIndexOfBit (id)];
863- float scale = 1000000000 .0f / duration; // one over time delta in seconds
864- float vx = (position.x - oldestPosition.x ) * scale;
865- float vy = (position.y - oldestPosition.y ) * scale;
866-
867- accumVx = (accumVx * lastDuration + vx * duration) / (duration + lastDuration);
868- accumVy = (accumVy * lastDuration + vy * duration) / (duration + lastDuration);
869-
870- lastDuration = duration;
871- samplesUsed += 1 ;
827+ if (!movement.idBits .hasBit (id)) {
828+ break ;
872829 }
873- }
830+
831+ nsecs_t age = newestMovement.eventTime - movement.eventTime ;
832+ if (age > MAX_AGE) {
833+ break ;
834+ }
835+
836+ const Position& position = movement.getPosition (id);
837+ accumVx += newestPosition.x - position.x ;
838+ accumVy += newestPosition.y - position.y ;
839+ duration += age;
840+ } while (index != mIndex );
874841
875842 // Make sure we used at least one sample.
876- if (samplesUsed != 0 ) {
877- *outVx = accumVx;
878- *outVy = accumVy;
843+ if (duration >= MIN_DURATION) {
844+ float scale = 1000000000 .0f / duration; // one over time delta in seconds
845+ *outVx = accumVx * scale;
846+ *outVy = accumVy * scale;
879847 return true ;
880848 }
881849 }
0 commit comments