blob: 90ba2ba849e84a54c5cd925b65f62e2e8a31ee93 [file] [log] [blame]
Jeff Brown2ed24622011-03-14 19:39:54 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "VelocityTracker-JNI"
18
19#include "JNIHelp.h"
20
21#include <android_runtime/AndroidRuntime.h>
22#include <utils/Log.h>
Jeff Brown9d3b1a42013-07-01 19:07:15 -070023#include <input/Input.h>
24#include <input/VelocityTracker.h>
Jeff Brown2ed24622011-03-14 19:39:54 -070025#include "android_view_MotionEvent.h"
26
Jeff Brown9eb7d862012-06-01 12:39:25 -070027#include <ScopedUtfChars.h>
28
Jeff Brown2ed24622011-03-14 19:39:54 -070029
30namespace android {
31
32// Special constant to request the velocity of the active pointer.
33static const int ACTIVE_POINTER_ID = -1;
34
Jeff Brownb59ab9f2011-09-14 10:53:18 -070035static struct {
36 jfieldID xCoeff;
37 jfieldID yCoeff;
38 jfieldID degree;
39 jfieldID confidence;
40} gEstimatorClassInfo;
41
42
Jeff Brown2ed24622011-03-14 19:39:54 -070043// --- VelocityTrackerState ---
44
45class VelocityTrackerState {
46public:
Jeff Brown9eb7d862012-06-01 12:39:25 -070047 VelocityTrackerState(const char* strategy);
Jeff Brown2ed24622011-03-14 19:39:54 -070048
49 void clear();
50 void addMovement(const MotionEvent* event);
51 void computeCurrentVelocity(int32_t units, float maxVelocity);
52 void getVelocity(int32_t id, float* outVx, float* outVy);
Jeff Brown85bd0d62012-05-13 15:30:42 -070053 bool getEstimator(int32_t id, VelocityTracker::Estimator* outEstimator);
Jeff Brown2ed24622011-03-14 19:39:54 -070054
55private:
56 struct Velocity {
57 float vx, vy;
58 };
59
60 VelocityTracker mVelocityTracker;
61 int32_t mActivePointerId;
62 BitSet32 mCalculatedIdBits;
63 Velocity mCalculatedVelocity[MAX_POINTERS];
64};
65
Jeff Brown9eb7d862012-06-01 12:39:25 -070066VelocityTrackerState::VelocityTrackerState(const char* strategy) :
67 mVelocityTracker(strategy), mActivePointerId(-1) {
Jeff Brown2ed24622011-03-14 19:39:54 -070068}
69
70void VelocityTrackerState::clear() {
71 mVelocityTracker.clear();
72 mActivePointerId = -1;
73 mCalculatedIdBits.clear();
74}
75
76void VelocityTrackerState::addMovement(const MotionEvent* event) {
77 mVelocityTracker.addMovement(event);
78}
79
80void VelocityTrackerState::computeCurrentVelocity(int32_t units, float maxVelocity) {
81 BitSet32 idBits(mVelocityTracker.getCurrentPointerIdBits());
82 mCalculatedIdBits = idBits;
83
84 for (uint32_t index = 0; !idBits.isEmpty(); index++) {
Jeff Brownbe1aa822011-07-27 16:04:54 -070085 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brown2ed24622011-03-14 19:39:54 -070086
87 float vx, vy;
88 mVelocityTracker.getVelocity(id, &vx, &vy);
89
90 vx = vx * units / 1000;
91 vy = vy * units / 1000;
92
93 if (vx > maxVelocity) {
94 vx = maxVelocity;
95 } else if (vx < -maxVelocity) {
96 vx = -maxVelocity;
97 }
98 if (vy > maxVelocity) {
99 vy = maxVelocity;
100 } else if (vy < -maxVelocity) {
101 vy = -maxVelocity;
102 }
103
104 Velocity& velocity = mCalculatedVelocity[index];
105 velocity.vx = vx;
106 velocity.vy = vy;
107 }
108}
109
110void VelocityTrackerState::getVelocity(int32_t id, float* outVx, float* outVy) {
111 if (id == ACTIVE_POINTER_ID) {
112 id = mVelocityTracker.getActivePointerId();
113 }
114
115 float vx, vy;
116 if (id >= 0 && id <= MAX_POINTER_ID && mCalculatedIdBits.hasBit(id)) {
117 uint32_t index = mCalculatedIdBits.getIndexOfBit(id);
118 const Velocity& velocity = mCalculatedVelocity[index];
119 vx = velocity.vx;
120 vy = velocity.vy;
121 } else {
122 vx = 0;
123 vy = 0;
124 }
125
126 if (outVx) {
127 *outVx = vx;
128 }
129 if (outVy) {
130 *outVy = vy;
131 }
132}
133
Jeff Brown85bd0d62012-05-13 15:30:42 -0700134bool VelocityTrackerState::getEstimator(int32_t id, VelocityTracker::Estimator* outEstimator) {
135 return mVelocityTracker.getEstimator(id, outEstimator);
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700136}
137
Jeff Brown2ed24622011-03-14 19:39:54 -0700138
139// --- JNI Methods ---
140
Jeff Brown9eb7d862012-06-01 12:39:25 -0700141static 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));
Jeff Brown2ed24622011-03-14 19:39:54 -0700148}
149
150static void android_view_VelocityTracker_nativeDispose(JNIEnv* env, jclass clazz, jint ptr) {
151 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
152 delete state;
153}
154
155static void android_view_VelocityTracker_nativeClear(JNIEnv* env, jclass clazz, jint ptr) {
156 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
157 state->clear();
158}
159
160static void android_view_VelocityTracker_nativeAddMovement(JNIEnv* env, jclass clazz, jint ptr,
161 jobject eventObj) {
162 const MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj);
163 if (!event) {
Steve Block8564c8d2012-01-05 23:22:43 +0000164 ALOGW("nativeAddMovement failed because MotionEvent was finalized.");
Jeff Brown2ed24622011-03-14 19:39:54 -0700165 return;
166 }
167
168 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
169 state->addMovement(event);
170}
171
172static void android_view_VelocityTracker_nativeComputeCurrentVelocity(JNIEnv* env, jclass clazz,
173 jint ptr, jint units, jfloat maxVelocity) {
174 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
175 state->computeCurrentVelocity(units, maxVelocity);
176}
177
178static jfloat android_view_VelocityTracker_nativeGetXVelocity(JNIEnv* env, jclass clazz,
179 jint ptr, jint id) {
180 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
181 float vx;
182 state->getVelocity(id, &vx, NULL);
183 return vx;
184}
185
186static jfloat android_view_VelocityTracker_nativeGetYVelocity(JNIEnv* env, jclass clazz,
187 jint ptr, jint id) {
188 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
189 float vy;
190 state->getVelocity(id, NULL, &vy);
191 return vy;
192}
193
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700194static jboolean android_view_VelocityTracker_nativeGetEstimator(JNIEnv* env, jclass clazz,
Jeff Brown85bd0d62012-05-13 15:30:42 -0700195 jint ptr, jint id, jobject outEstimatorObj) {
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700196 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
197 VelocityTracker::Estimator estimator;
Jeff Brown85bd0d62012-05-13 15:30:42 -0700198 bool result = state->getEstimator(id, &estimator);
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700199
200 jfloatArray xCoeffObj = jfloatArray(env->GetObjectField(outEstimatorObj,
201 gEstimatorClassInfo.xCoeff));
202 jfloatArray yCoeffObj = jfloatArray(env->GetObjectField(outEstimatorObj,
203 gEstimatorClassInfo.yCoeff));
204
205 env->SetFloatArrayRegion(xCoeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
206 estimator.xCoeff);
207 env->SetFloatArrayRegion(yCoeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
208 estimator.yCoeff);
209 env->SetIntField(outEstimatorObj, gEstimatorClassInfo.degree, estimator.degree);
210 env->SetFloatField(outEstimatorObj, gEstimatorClassInfo.confidence, estimator.confidence);
211 return result;
212}
213
Jeff Brown2ed24622011-03-14 19:39:54 -0700214
215// --- JNI Registration ---
216
217static JNINativeMethod gVelocityTrackerMethods[] = {
218 /* name, signature, funcPtr */
219 { "nativeInitialize",
Jeff Brown9eb7d862012-06-01 12:39:25 -0700220 "(Ljava/lang/String;)I",
Jeff Brown2ed24622011-03-14 19:39:54 -0700221 (void*)android_view_VelocityTracker_nativeInitialize },
222 { "nativeDispose",
223 "(I)V",
224 (void*)android_view_VelocityTracker_nativeDispose },
225 { "nativeClear",
226 "(I)V",
227 (void*)android_view_VelocityTracker_nativeClear },
228 { "nativeAddMovement",
229 "(ILandroid/view/MotionEvent;)V",
230 (void*)android_view_VelocityTracker_nativeAddMovement },
231 { "nativeComputeCurrentVelocity",
232 "(IIF)V",
233 (void*)android_view_VelocityTracker_nativeComputeCurrentVelocity },
234 { "nativeGetXVelocity",
235 "(II)F",
236 (void*)android_view_VelocityTracker_nativeGetXVelocity },
237 { "nativeGetYVelocity",
238 "(II)F",
239 (void*)android_view_VelocityTracker_nativeGetYVelocity },
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700240 { "nativeGetEstimator",
Jeff Brown85bd0d62012-05-13 15:30:42 -0700241 "(IILandroid/view/VelocityTracker$Estimator;)Z",
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700242 (void*)android_view_VelocityTracker_nativeGetEstimator },
Jeff Brown2ed24622011-03-14 19:39:54 -0700243};
244
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700245#define FIND_CLASS(var, className) \
246 var = env->FindClass(className); \
247 LOG_FATAL_IF(! var, "Unable to find class " className);
248
249#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
250 var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
251 LOG_FATAL_IF(! var, "Unable to find field " fieldName);
252
Jeff Brown2ed24622011-03-14 19:39:54 -0700253int register_android_view_VelocityTracker(JNIEnv* env) {
254 int res = jniRegisterNativeMethods(env, "android/view/VelocityTracker",
255 gVelocityTrackerMethods, NELEM(gVelocityTrackerMethods));
256 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700257
258 jclass clazz;
259 FIND_CLASS(clazz, "android/view/VelocityTracker$Estimator");
260
261 GET_FIELD_ID(gEstimatorClassInfo.xCoeff, clazz,
262 "xCoeff", "[F");
263 GET_FIELD_ID(gEstimatorClassInfo.yCoeff, clazz,
264 "yCoeff", "[F");
265 GET_FIELD_ID(gEstimatorClassInfo.degree, clazz,
266 "degree", "I");
267 GET_FIELD_ID(gEstimatorClassInfo.confidence, clazz,
268 "confidence", "F");
Jeff Brown2ed24622011-03-14 19:39:54 -0700269 return 0;
270}
271
272} // namespace android