• 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 <android_runtime/AndroidRuntime.h>
20 #include <cutils/properties.h>
21 #include <input/Input.h>
22 #include <input/VelocityTracker.h>
23 #include <nativehelper/JNIHelp.h>
24 #include <nativehelper/ScopedUtfChars.h>
25 #include <utils/Log.h>
26 #include "android_view_MotionEvent.h"
27 #include "core_jni_helpers.h"
28 
29 namespace android {
30 
31 // Special constant to request the velocity of the active pointer.
32 static const int ACTIVE_POINTER_ID = -1;
33 
34 static struct {
35     jfieldID xCoeff;
36     jfieldID yCoeff;
37     jfieldID degree;
38     jfieldID confidence;
39 } gEstimatorClassInfo;
40 
41 
42 // --- VelocityTrackerState ---
43 
44 class VelocityTrackerState {
45 public:
46     explicit VelocityTrackerState(const VelocityTracker::Strategy strategy);
47 
48     void clear();
49     void addMovement(const MotionEvent* event);
50     void computeCurrentVelocity(int32_t units, float maxVelocity);
51     void getVelocity(int32_t id, float* outVx, float* outVy);
52     bool getEstimator(int32_t id, VelocityTracker::Estimator* outEstimator);
53 
54 private:
55     struct Velocity {
56         float vx, vy;
57     };
58 
59     VelocityTracker mVelocityTracker;
60     int32_t mActivePointerId;
61     BitSet32 mCalculatedIdBits;
62     Velocity mCalculatedVelocity[MAX_POINTERS];
63 };
64 
VelocityTrackerState(const VelocityTracker::Strategy strategy)65 VelocityTrackerState::VelocityTrackerState(const VelocityTracker::Strategy strategy)
66       : mVelocityTracker(strategy), mActivePointerId(-1) {}
67 
clear()68 void VelocityTrackerState::clear() {
69     mVelocityTracker.clear();
70     mActivePointerId = -1;
71     mCalculatedIdBits.clear();
72 }
73 
addMovement(const MotionEvent * event)74 void VelocityTrackerState::addMovement(const MotionEvent* event) {
75     mVelocityTracker.addMovement(event);
76 }
77 
computeCurrentVelocity(int32_t units,float maxVelocity)78 void VelocityTrackerState::computeCurrentVelocity(int32_t units, float maxVelocity) {
79     BitSet32 idBits(mVelocityTracker.getCurrentPointerIdBits());
80     mCalculatedIdBits = idBits;
81 
82     for (uint32_t index = 0; !idBits.isEmpty(); index++) {
83         uint32_t id = idBits.clearFirstMarkedBit();
84 
85         float vx, vy;
86         mVelocityTracker.getVelocity(id, &vx, &vy);
87 
88         vx = vx * units / 1000;
89         vy = vy * units / 1000;
90 
91         if (vx > maxVelocity) {
92             vx = maxVelocity;
93         } else if (vx < -maxVelocity) {
94             vx = -maxVelocity;
95         }
96         if (vy > maxVelocity) {
97             vy = maxVelocity;
98         } else if (vy < -maxVelocity) {
99             vy = -maxVelocity;
100         }
101 
102         Velocity& velocity = mCalculatedVelocity[index];
103         velocity.vx = vx;
104         velocity.vy = vy;
105     }
106 }
107 
getVelocity(int32_t id,float * outVx,float * outVy)108 void VelocityTrackerState::getVelocity(int32_t id, float* outVx, float* outVy) {
109     if (id == ACTIVE_POINTER_ID) {
110         id = mVelocityTracker.getActivePointerId();
111     }
112 
113     float vx, vy;
114     if (id >= 0 && id <= MAX_POINTER_ID && mCalculatedIdBits.hasBit(id)) {
115         uint32_t index = mCalculatedIdBits.getIndexOfBit(id);
116         const Velocity& velocity = mCalculatedVelocity[index];
117         vx = velocity.vx;
118         vy = velocity.vy;
119     } else {
120         vx = 0;
121         vy = 0;
122     }
123 
124     if (outVx) {
125         *outVx = vx;
126     }
127     if (outVy) {
128         *outVy = vy;
129     }
130 }
131 
getEstimator(int32_t id,VelocityTracker::Estimator * outEstimator)132 bool VelocityTrackerState::getEstimator(int32_t id, VelocityTracker::Estimator* outEstimator) {
133     return mVelocityTracker.getEstimator(id, outEstimator);
134 }
135 
136 // Return a strategy enum from integer value.
getStrategyFromInt(const int32_t strategy)137 inline static VelocityTracker::Strategy getStrategyFromInt(const int32_t strategy) {
138     if (strategy < static_cast<int32_t>(VelocityTracker::Strategy::MIN) ||
139         strategy > static_cast<int32_t>(VelocityTracker::Strategy::MAX)) {
140         return VelocityTracker::Strategy::DEFAULT;
141     }
142     return static_cast<VelocityTracker::Strategy>(strategy);
143 }
144 
145 // --- JNI Methods ---
146 
android_view_VelocityTracker_nativeInitialize(JNIEnv * env,jclass clazz,jint strategy)147 static jlong android_view_VelocityTracker_nativeInitialize(JNIEnv* env, jclass clazz,
148                                                            jint strategy) {
149     return reinterpret_cast<jlong>(new VelocityTrackerState(getStrategyFromInt(strategy)));
150 }
151 
android_view_VelocityTracker_nativeDispose(JNIEnv * env,jclass clazz,jlong ptr)152 static void android_view_VelocityTracker_nativeDispose(JNIEnv* env, jclass clazz, jlong ptr) {
153     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
154     delete state;
155 }
156 
android_view_VelocityTracker_nativeClear(JNIEnv * env,jclass clazz,jlong ptr)157 static void android_view_VelocityTracker_nativeClear(JNIEnv* env, jclass clazz, jlong ptr) {
158     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
159     state->clear();
160 }
161 
android_view_VelocityTracker_nativeAddMovement(JNIEnv * env,jclass clazz,jlong ptr,jobject eventObj)162 static void android_view_VelocityTracker_nativeAddMovement(JNIEnv* env, jclass clazz, jlong ptr,
163         jobject eventObj) {
164     const MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj);
165     if (!event) {
166         ALOGW("nativeAddMovement failed because MotionEvent was finalized.");
167         return;
168     }
169 
170     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
171     state->addMovement(event);
172 }
173 
android_view_VelocityTracker_nativeComputeCurrentVelocity(JNIEnv * env,jclass clazz,jlong ptr,jint units,jfloat maxVelocity)174 static void android_view_VelocityTracker_nativeComputeCurrentVelocity(JNIEnv* env, jclass clazz,
175         jlong ptr, jint units, jfloat maxVelocity) {
176     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
177     state->computeCurrentVelocity(units, maxVelocity);
178 }
179 
android_view_VelocityTracker_nativeGetXVelocity(JNIEnv * env,jclass clazz,jlong ptr,jint id)180 static jfloat android_view_VelocityTracker_nativeGetXVelocity(JNIEnv* env, jclass clazz,
181         jlong ptr, jint id) {
182     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
183     float vx;
184     state->getVelocity(id, &vx, NULL);
185     return vx;
186 }
187 
android_view_VelocityTracker_nativeGetYVelocity(JNIEnv * env,jclass clazz,jlong ptr,jint id)188 static jfloat android_view_VelocityTracker_nativeGetYVelocity(JNIEnv* env, jclass clazz,
189         jlong ptr, jint id) {
190     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
191     float vy;
192     state->getVelocity(id, NULL, &vy);
193     return vy;
194 }
195 
android_view_VelocityTracker_nativeGetEstimator(JNIEnv * env,jclass clazz,jlong ptr,jint id,jobject outEstimatorObj)196 static jboolean android_view_VelocityTracker_nativeGetEstimator(JNIEnv* env, jclass clazz,
197         jlong ptr, jint id, jobject outEstimatorObj) {
198     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
199     VelocityTracker::Estimator estimator;
200     bool result = state->getEstimator(id, &estimator);
201 
202     jfloatArray xCoeffObj = jfloatArray(env->GetObjectField(outEstimatorObj,
203             gEstimatorClassInfo.xCoeff));
204     jfloatArray yCoeffObj = jfloatArray(env->GetObjectField(outEstimatorObj,
205             gEstimatorClassInfo.yCoeff));
206 
207     env->SetFloatArrayRegion(xCoeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
208             estimator.xCoeff);
209     env->SetFloatArrayRegion(yCoeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
210             estimator.yCoeff);
211     env->SetIntField(outEstimatorObj, gEstimatorClassInfo.degree, estimator.degree);
212     env->SetFloatField(outEstimatorObj, gEstimatorClassInfo.confidence, estimator.confidence);
213     return result;
214 }
215 
216 // --- JNI Registration ---
217 
218 static const JNINativeMethod gVelocityTrackerMethods[] = {
219         /* name, signature, funcPtr */
220         {"nativeInitialize", "(I)J", (void*)android_view_VelocityTracker_nativeInitialize},
221         {"nativeDispose", "(J)V", (void*)android_view_VelocityTracker_nativeDispose},
222         {"nativeClear", "(J)V", (void*)android_view_VelocityTracker_nativeClear},
223         {"nativeAddMovement", "(JLandroid/view/MotionEvent;)V",
224          (void*)android_view_VelocityTracker_nativeAddMovement},
225         {"nativeComputeCurrentVelocity", "(JIF)V",
226          (void*)android_view_VelocityTracker_nativeComputeCurrentVelocity},
227         {"nativeGetXVelocity", "(JI)F", (void*)android_view_VelocityTracker_nativeGetXVelocity},
228         {"nativeGetYVelocity", "(JI)F", (void*)android_view_VelocityTracker_nativeGetYVelocity},
229         {"nativeGetEstimator", "(JILandroid/view/VelocityTracker$Estimator;)Z",
230          (void*)android_view_VelocityTracker_nativeGetEstimator},
231 };
232 
register_android_view_VelocityTracker(JNIEnv * env)233 int register_android_view_VelocityTracker(JNIEnv* env) {
234     int res = RegisterMethodsOrDie(env, "android/view/VelocityTracker", gVelocityTrackerMethods,
235                                    NELEM(gVelocityTrackerMethods));
236 
237     jclass clazz = FindClassOrDie(env, "android/view/VelocityTracker$Estimator");
238 
239     gEstimatorClassInfo.xCoeff = GetFieldIDOrDie(env, clazz, "xCoeff", "[F");
240     gEstimatorClassInfo.yCoeff = GetFieldIDOrDie(env, clazz, "yCoeff", "[F");
241     gEstimatorClassInfo.degree = GetFieldIDOrDie(env, clazz, "degree", "I");
242     gEstimatorClassInfo.confidence = GetFieldIDOrDie(env, clazz, "confidence", "F");
243 
244     return res;
245 }
246 
247 } // namespace android
248