Skip to content

Commit 9eb7d86

Browse files
author
Jeff Brown
committed
Make velocity tracker strategy configurable.
This change is very useful for testing purposes because it makes it easy to compare different implementations to see how they behave. There is no change to the current default strategy. Bug: 6413587 Change-Id: I4d8567aa4160571ba9fa397ce419882cd9366749
1 parent 6e8e41a commit 9eb7d86

File tree

5 files changed

+178
-36
lines changed

5 files changed

+178
-36
lines changed

core/java/android/view/VelocityTracker.java

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public final class VelocityTracker implements Poolable<VelocityTracker> {
3535
private static final Pool<VelocityTracker> sPool = Pools.synchronizedPool(
3636
Pools.finitePool(new PoolableManager<VelocityTracker>() {
3737
public VelocityTracker newInstance() {
38-
return new VelocityTracker();
38+
return new VelocityTracker(null);
3939
}
4040

4141
public void onAcquired(VelocityTracker element) {
@@ -50,10 +50,12 @@ public void onReleased(VelocityTracker element) {
5050
private static final int ACTIVE_POINTER_ID = -1;
5151

5252
private int mPtr;
53+
private final String mStrategy;
54+
5355
private VelocityTracker mNext;
5456
private boolean mIsPooled;
5557

56-
private static native int nativeInitialize();
58+
private static native int nativeInitialize(String strategy);
5759
private static native void nativeDispose(int ptr);
5860
private static native void nativeClear(int ptr);
5961
private static native void nativeAddMovement(int ptr, MotionEvent event);
@@ -74,12 +76,30 @@ static public VelocityTracker obtain() {
7476
return sPool.acquire();
7577
}
7678

79+
/**
80+
* Obtains a velocity tracker with the specified strategy.
81+
* For testing and comparison purposes only.
82+
*
83+
* @param strategy The strategy, or null to use the default.
84+
* @return The velocity tracker.
85+
*
86+
* @hide
87+
*/
88+
public static VelocityTracker obtain(String strategy) {
89+
if (strategy == null) {
90+
return obtain();
91+
}
92+
return new VelocityTracker(strategy);
93+
}
94+
7795
/**
7896
* Return a VelocityTracker object back to be re-used by others. You must
7997
* not touch the object after calling this function.
8098
*/
8199
public void recycle() {
82-
sPool.release(this);
100+
if (mStrategy == null) {
101+
sPool.release(this);
102+
}
83103
}
84104

85105
/**
@@ -110,8 +130,9 @@ public void setPooled(boolean isPooled) {
110130
mIsPooled = isPooled;
111131
}
112132

113-
private VelocityTracker() {
114-
mPtr = nativeInitialize();
133+
private VelocityTracker(String strategy) {
134+
mPtr = nativeInitialize(strategy);
135+
mStrategy = strategy;
115136
}
116137

117138
@Override
@@ -253,7 +274,7 @@ public boolean getEstimator(int id, Estimator outEstimator) {
253274
*/
254275
public static final class Estimator {
255276
// Must match VelocityTracker::Estimator::MAX_DEGREE
256-
private static final int MAX_DEGREE = 2;
277+
private static final int MAX_DEGREE = 4;
257278

258279
/**
259280
* Polynomial coefficients describing motion in X.

core/java/com/android/internal/widget/PointerLocationView.java

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import android.graphics.Paint.FontMetricsInt;
2424
import android.hardware.input.InputManager;
2525
import android.hardware.input.InputManager.InputDeviceListener;
26+
import android.os.SystemProperties;
2627
import android.util.Log;
2728
import android.view.InputDevice;
2829
import android.view.KeyEvent;
@@ -36,7 +37,11 @@
3637

3738
public class PointerLocationView extends View implements InputDeviceListener {
3839
private static final String TAG = "Pointer";
39-
40+
41+
// The system property key used to specify an alternate velocity tracker strategy
42+
// to plot alongside the default one. Useful for testing and comparison purposes.
43+
private static final String ALT_STRATEGY_PROPERY_KEY = "debug.velocitytracker.alt";
44+
4045
public static class PointerState {
4146
// Trace of previous points.
4247
private float[] mTraceX = new float[32];
@@ -53,9 +58,12 @@ public static class PointerState {
5358
// Most recent velocity.
5459
private float mXVelocity;
5560
private float mYVelocity;
61+
private float mAltXVelocity;
62+
private float mAltYVelocity;
5663

5764
// Position estimator.
5865
private VelocityTracker.Estimator mEstimator = new VelocityTracker.Estimator();
66+
private VelocityTracker.Estimator mAltEstimator = new VelocityTracker.Estimator();
5967

6068
public void clearTrace() {
6169
mTraceCount = 0;
@@ -103,7 +111,8 @@ public void addTrace(float x, float y) {
103111
private final PointerCoords mTempCoords = new PointerCoords();
104112

105113
private final VelocityTracker mVelocity;
106-
114+
private final VelocityTracker mAltVelocity;
115+
107116
private final FasterStringBuilder mText = new FasterStringBuilder();
108117

109118
private boolean mPrintCoords = true;
@@ -145,6 +154,14 @@ public PointerLocationView(Context c) {
145154
mActivePointerId = 0;
146155

147156
mVelocity = VelocityTracker.obtain();
157+
158+
String altStrategy = SystemProperties.get(ALT_STRATEGY_PROPERY_KEY);
159+
if (altStrategy.length() != 0) {
160+
Log.d(TAG, "Comparing default velocity tracker strategy with " + altStrategy);
161+
mAltVelocity = VelocityTracker.obtain(altStrategy);
162+
} else {
163+
mAltVelocity = null;
164+
}
148165
}
149166

150167
public void setPrintCoords(boolean state) {
@@ -296,6 +313,25 @@ protected void onDraw(Canvas canvas) {
296313
float xVel = ps.mXVelocity * (1000 / 60);
297314
float yVel = ps.mYVelocity * (1000 / 60);
298315
canvas.drawLine(lastX, lastY, lastX + xVel, lastY + yVel, mPaint);
316+
317+
// Draw alternate estimate.
318+
if (mAltVelocity != null) {
319+
mPaint.setARGB(128, 0, 128, 128);
320+
lx = ps.mAltEstimator.estimateX(-ESTIMATE_PAST_POINTS * ESTIMATE_INTERVAL);
321+
ly = ps.mAltEstimator.estimateY(-ESTIMATE_PAST_POINTS * ESTIMATE_INTERVAL);
322+
for (int i = -ESTIMATE_PAST_POINTS + 1; i <= ESTIMATE_FUTURE_POINTS; i++) {
323+
float x = ps.mAltEstimator.estimateX(i * ESTIMATE_INTERVAL);
324+
float y = ps.mAltEstimator.estimateY(i * ESTIMATE_INTERVAL);
325+
canvas.drawLine(lx, ly, x, y, mPaint);
326+
lx = x;
327+
ly = y;
328+
}
329+
330+
mPaint.setARGB(255, 64, 255, 128);
331+
xVel = ps.mAltXVelocity * (1000 / 60);
332+
yVel = ps.mAltYVelocity * (1000 / 60);
333+
canvas.drawLine(lastX, lastY, lastX + xVel, lastY + yVel, mPaint);
334+
}
299335
}
300336

301337
if (mCurDown && ps.mCurDown) {
@@ -470,6 +506,9 @@ public void addPointerEvent(MotionEvent event) {
470506
mCurNumPointers = 0;
471507
mMaxNumPointers = 0;
472508
mVelocity.clear();
509+
if (mAltVelocity != null) {
510+
mAltVelocity.clear();
511+
}
473512
}
474513

475514
mCurNumPointers += 1;
@@ -497,6 +536,10 @@ public void addPointerEvent(MotionEvent event) {
497536

498537
mVelocity.addMovement(event);
499538
mVelocity.computeCurrentVelocity(1);
539+
if (mAltVelocity != null) {
540+
mAltVelocity.addMovement(event);
541+
mAltVelocity.computeCurrentVelocity(1);
542+
}
500543

501544
final int N = event.getHistorySize();
502545
for (int historyPos = 0; historyPos < N; historyPos++) {
@@ -528,6 +571,11 @@ public void addPointerEvent(MotionEvent event) {
528571
ps.mXVelocity = mVelocity.getXVelocity(id);
529572
ps.mYVelocity = mVelocity.getYVelocity(id);
530573
mVelocity.getEstimator(id, ps.mEstimator);
574+
if (mAltVelocity != null) {
575+
ps.mAltXVelocity = mAltVelocity.getXVelocity(id);
576+
ps.mAltYVelocity = mAltVelocity.getYVelocity(id);
577+
mAltVelocity.getEstimator(id, ps.mAltEstimator);
578+
}
531579
ps.mToolType = event.getToolType(i);
532580
}
533581
}

core/jni/android_view_VelocityTracker.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include <androidfw/VelocityTracker.h>
2525
#include "android_view_MotionEvent.h"
2626

27+
#include <ScopedUtfChars.h>
28+
2729

2830
namespace android {
2931

@@ -42,7 +44,7 @@ static struct {
4244

4345
class VelocityTrackerState {
4446
public:
45-
VelocityTrackerState();
47+
VelocityTrackerState(const char* strategy);
4648

4749
void clear();
4850
void addMovement(const MotionEvent* event);
@@ -61,7 +63,8 @@ class VelocityTrackerState {
6163
Velocity mCalculatedVelocity[MAX_POINTERS];
6264
};
6365

64-
VelocityTrackerState::VelocityTrackerState() : mActivePointerId(-1) {
66+
VelocityTrackerState::VelocityTrackerState(const char* strategy) :
67+
mVelocityTracker(strategy), mActivePointerId(-1) {
6568
}
6669

6770
void VelocityTrackerState::clear() {
@@ -135,8 +138,13 @@ bool VelocityTrackerState::getEstimator(int32_t id, VelocityTracker::Estimator*
135138

136139
// --- JNI Methods ---
137140

138-
static jint android_view_VelocityTracker_nativeInitialize(JNIEnv* env, jclass clazz) {
139-
return reinterpret_cast<jint>(new VelocityTrackerState());
141+
static jint android_view_VelocityTracker_nativeInitialize(JNIEnv* env, jclass clazz,
142+
jstring strategyStr) {
143+
if (strategyStr) {
144+
ScopedUtfChars strategy(env, strategyStr);
145+
return reinterpret_cast<jint>(new VelocityTrackerState(strategy.c_str()));
146+
}
147+
return reinterpret_cast<jint>(new VelocityTrackerState(NULL));
140148
}
141149

142150
static void android_view_VelocityTracker_nativeDispose(JNIEnv* env, jclass clazz, jint ptr) {
@@ -209,7 +217,7 @@ static jboolean android_view_VelocityTracker_nativeGetEstimator(JNIEnv* env, jcl
209217
static JNINativeMethod gVelocityTrackerMethods[] = {
210218
/* name, signature, funcPtr */
211219
{ "nativeInitialize",
212-
"()I",
220+
"(Ljava/lang/String;)I",
213221
(void*)android_view_VelocityTracker_nativeInitialize },
214222
{ "nativeDispose",
215223
"(I)V",

include/androidfw/VelocityTracker.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class VelocityTracker {
3535
};
3636

3737
struct Estimator {
38-
static const size_t MAX_DEGREE = 2;
38+
static const size_t MAX_DEGREE = 4;
3939

4040
// Estimator time base.
4141
nsecs_t time;
@@ -61,7 +61,10 @@ class VelocityTracker {
6161
}
6262
};
6363

64-
VelocityTracker();
64+
// Creates a velocity tracker using the specified strategy.
65+
// If strategy is NULL, uses the default strategy for the platform.
66+
VelocityTracker(const char* strategy = NULL);
67+
6568
~VelocityTracker();
6669

6770
// Resets the velocity tracker state.
@@ -99,10 +102,16 @@ class VelocityTracker {
99102
inline BitSet32 getCurrentPointerIdBits() const { return mCurrentPointerIdBits; }
100103

101104
private:
105+
static const char* DEFAULT_STRATEGY;
106+
102107
nsecs_t mLastEventTime;
103108
BitSet32 mCurrentPointerIdBits;
104109
int32_t mActivePointerId;
105110
VelocityTrackerStrategy* mStrategy;
111+
112+
bool configureStrategy(const char* strategy);
113+
114+
static VelocityTrackerStrategy* createStrategy(const char* strategy);
106115
};
107116

108117

@@ -129,7 +138,8 @@ class VelocityTrackerStrategy {
129138
*/
130139
class LeastSquaresVelocityTrackerStrategy : public VelocityTrackerStrategy {
131140
public:
132-
LeastSquaresVelocityTrackerStrategy();
141+
// Degree must be no greater than Estimator::MAX_DEGREE.
142+
LeastSquaresVelocityTrackerStrategy(uint32_t degree);
133143
virtual ~LeastSquaresVelocityTrackerStrategy();
134144

135145
virtual void clear();
@@ -139,9 +149,6 @@ class LeastSquaresVelocityTrackerStrategy : public VelocityTrackerStrategy {
139149
virtual bool getEstimator(uint32_t id, VelocityTracker::Estimator* outEstimator) const;
140150

141151
private:
142-
// Polynomial degree. Must be less than or equal to Estimator::MAX_DEGREE.
143-
static const uint32_t DEGREE = 2;
144-
145152
// Sample horizon.
146153
// We don't use too much history by default since we want to react to quick
147154
// changes in direction.
@@ -160,6 +167,7 @@ class LeastSquaresVelocityTrackerStrategy : public VelocityTrackerStrategy {
160167
}
161168
};
162169

170+
const uint32_t mDegree;
163171
uint32_t mIndex;
164172
Movement mMovements[HISTORY_SIZE];
165173
};

0 commit comments

Comments
 (0)