• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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>
23 #include <input/Input.h>
24 #include <input/VelocityTracker.h>
25 #include "android_view_MotionEvent.h"
26 
27 #include <ScopedUtfChars.h>
28 
29 
30 namespace android {
31 
32 // Special constant to request the velocity of the active pointer.
33 static const int ACTIVE_POINTER_ID = -1;
34 
35 static struct {
36     jfieldID xCoeff;
37     jfieldID yCoeff;
38     jfieldID degree;
39     jfieldID confidence;
40 } gEstimatorClassInfo;
41 
42 
43 // --- VelocityTrackerState ---
44 
45 class VelocityTrackerState {
46 public:
47     VelocityTrackerState(const char* strategy);
48 
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);
53     bool getEstimator(int32_t id, VelocityTracker::Estimator* outEstimator);
54 
55 private:
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 
VelocityTrackerState(const char * strategy)66 VelocityTrackerState::VelocityTrackerState(const char* strategy) :
67         mVelocityTracker(strategy), mActivePointerId(-1) {
68 }
69 
clear()70 void VelocityTrackerState::clear() {
71     mVelocityTracker.clear();
72     mActivePointerId = -1;
73     mCalculatedIdBits.clear();
74 }
75 
addMovement(const MotionEvent * event)76 void VelocityTrackerState::addMovement(const MotionEvent* event) {
77     mVelocityTracker.addMovement(event);
78 }
79 
computeCurrentVelocity(int32_t units,float maxVelocity)80 void 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++) {
85         uint32_t id = idBits.clearFirstMarkedBit();
86 
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 
getVelocity(int32_t id,float * outVx,float * outVy)110 void 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 
getEstimator(int32_t id,VelocityTracker::Estimator * outEstimator)134 bool VelocityTrackerState::getEstimator(int32_t id, VelocityTracker::Estimator* outEstimator) {
135     return mVelocityTracker.getEstimator(id, outEstimator);
136 }
137 
138 
139 // --- JNI Methods ---
140 
android_view_VelocityTracker_nativeInitialize(JNIEnv * env,jclass clazz,jstring strategyStr)141 static jlong android_view_VelocityTracker_nativeInitialize(JNIEnv* env, jclass clazz,
142         jstring strategyStr) {
143     if (strategyStr) {
144         ScopedUtfChars strategy(env, strategyStr);
145         return reinterpret_cast<jlong>(new VelocityTrackerState(strategy.c_str()));
146     }
147     return reinterpret_cast<jlong>(new VelocityTrackerState(NULL));
148 }
149 
android_view_VelocityTracker_nativeDispose(JNIEnv * env,jclass clazz,jlong ptr)150 static void android_view_VelocityTracker_nativeDispose(JNIEnv* env, jclass clazz, jlong ptr) {
151     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
152     delete state;
153 }
154 
android_view_VelocityTracker_nativeClear(JNIEnv * env,jclass clazz,jlong ptr)155 static void android_view_VelocityTracker_nativeClear(JNIEnv* env, jclass clazz, jlong ptr) {
156     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
157     state->clear();
158 }
159 
android_view_VelocityTracker_nativeAddMovement(JNIEnv * env,jclass clazz,jlong ptr,jobject eventObj)160 static void android_view_VelocityTracker_nativeAddMovement(JNIEnv* env, jclass clazz, jlong ptr,
161         jobject eventObj) {
162     const MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj);
163     if (!event) {
164         ALOGW("nativeAddMovement failed because MotionEvent was finalized.");
165         return;
166     }
167 
168     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
169     state->addMovement(event);
170 }
171 
android_view_VelocityTracker_nativeComputeCurrentVelocity(JNIEnv * env,jclass clazz,jlong ptr,jint units,jfloat maxVelocity)172 static void android_view_VelocityTracker_nativeComputeCurrentVelocity(JNIEnv* env, jclass clazz,
173         jlong ptr, jint units, jfloat maxVelocity) {
174     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
175     state->computeCurrentVelocity(units, maxVelocity);
176 }
177 
android_view_VelocityTracker_nativeGetXVelocity(JNIEnv * env,jclass clazz,jlong ptr,jint id)178 static jfloat android_view_VelocityTracker_nativeGetXVelocity(JNIEnv* env, jclass clazz,
179         jlong ptr, jint id) {
180     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
181     float vx;
182     state->getVelocity(id, &vx, NULL);
183     return vx;
184 }
185 
android_view_VelocityTracker_nativeGetYVelocity(JNIEnv * env,jclass clazz,jlong ptr,jint id)186 static jfloat android_view_VelocityTracker_nativeGetYVelocity(JNIEnv* env, jclass clazz,
187         jlong ptr, jint id) {
188     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
189     float vy;
190     state->getVelocity(id, NULL, &vy);
191     return vy;
192 }
193 
android_view_VelocityTracker_nativeGetEstimator(JNIEnv * env,jclass clazz,jlong ptr,jint id,jobject outEstimatorObj)194 static jboolean android_view_VelocityTracker_nativeGetEstimator(JNIEnv* env, jclass clazz,
195         jlong ptr, jint id, jobject outEstimatorObj) {
196     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
197     VelocityTracker::Estimator estimator;
198     bool result = state->getEstimator(id, &estimator);
199 
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 
214 
215 // --- JNI Registration ---
216 
217 static JNINativeMethod gVelocityTrackerMethods[] = {
218     /* name, signature, funcPtr */
219     { "nativeInitialize",
220             "(Ljava/lang/String;)J",
221             (void*)android_view_VelocityTracker_nativeInitialize },
222     { "nativeDispose",
223             "(J)V",
224             (void*)android_view_VelocityTracker_nativeDispose },
225     { "nativeClear",
226             "(J)V",
227             (void*)android_view_VelocityTracker_nativeClear },
228     { "nativeAddMovement",
229             "(JLandroid/view/MotionEvent;)V",
230             (void*)android_view_VelocityTracker_nativeAddMovement },
231     { "nativeComputeCurrentVelocity",
232             "(JIF)V",
233             (void*)android_view_VelocityTracker_nativeComputeCurrentVelocity },
234     { "nativeGetXVelocity",
235             "(JI)F",
236             (void*)android_view_VelocityTracker_nativeGetXVelocity },
237     { "nativeGetYVelocity",
238             "(JI)F",
239             (void*)android_view_VelocityTracker_nativeGetYVelocity },
240     { "nativeGetEstimator",
241             "(JILandroid/view/VelocityTracker$Estimator;)Z",
242             (void*)android_view_VelocityTracker_nativeGetEstimator },
243 };
244 
245 #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 
register_android_view_VelocityTracker(JNIEnv * env)253 int 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.");
257 
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");
269     return 0;
270 }
271 
272 } // namespace android
273