Skip to content

Commit f47e76e

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Make velocity tracker strategy configurable." into jb-dev
2 parents cc822a7 + 9eb7d86 commit f47e76e

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)