blob: 153789c7f933a3438a94a00172b52c408383390f [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
Steven Moreland2279b252017-07-19 09:50:45 -070019#include <nativehelper/JNIHelp.h>
Jeff Brown2ed24622011-03-14 19:39:54 -070020
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
Steven Moreland2279b252017-07-19 09:50:45 -070027#include <nativehelper/ScopedUtfChars.h>
Jeff Brown9eb7d862012-06-01 12:39:25 -070028
Andreas Gampe987f79f2014-11-18 17:29:46 -080029#include "core_jni_helpers.h"
Jeff Brown2ed24622011-03-14 19:39:54 -070030
31namespace android {
32
33// Special constant to request the velocity of the active pointer.
34static const int ACTIVE_POINTER_ID = -1;
35
Jeff Brownb59ab9f2011-09-14 10:53:18 -070036static struct {
37 jfieldID xCoeff;
38 jfieldID yCoeff;
39 jfieldID degree;
40 jfieldID confidence;
41} gEstimatorClassInfo;
42
43
Jeff Brown2ed24622011-03-14 19:39:54 -070044// --- VelocityTrackerState ---
45
46class VelocityTrackerState {
47public:
Chih-Hung Hsiehc6baf562016-04-27 11:29:23 -070048 explicit VelocityTrackerState(const char* strategy);
Jeff Brown2ed24622011-03-14 19:39:54 -070049
50 void clear();
51 void addMovement(const MotionEvent* event);
52 void computeCurrentVelocity(int32_t units, float maxVelocity);
53 void getVelocity(int32_t id, float* outVx, float* outVy);
Jeff Brown85bd0d62012-05-13 15:30:42 -070054 bool getEstimator(int32_t id, VelocityTracker::Estimator* outEstimator);
Jeff Brown2ed24622011-03-14 19:39:54 -070055
56private:
57 struct Velocity {
58 float vx, vy;
59 };
60
61 VelocityTracker mVelocityTracker;
62 int32_t mActivePointerId;
63 BitSet32 mCalculatedIdBits;
64 Velocity mCalculatedVelocity[MAX_POINTERS];
65};
66
Jeff Brown9eb7d862012-06-01 12:39:25 -070067VelocityTrackerState::VelocityTrackerState(const char* strategy) :
68 mVelocityTracker(strategy), mActivePointerId(-1) {
Jeff Brown2ed24622011-03-14 19:39:54 -070069}
70
71void VelocityTrackerState::clear() {
72 mVelocityTracker.clear();
73 mActivePointerId = -1;
74 mCalculatedIdBits.clear();
75}
76
77void VelocityTrackerState::addMovement(const MotionEvent* event) {
78 mVelocityTracker.addMovement(event);
79}
80
81void VelocityTrackerState::computeCurrentVelocity(int32_t units, float maxVelocity) {
82 BitSet32 idBits(mVelocityTracker.getCurrentPointerIdBits());
83 mCalculatedIdBits = idBits;
84
85 for (uint32_t index = 0; !idBits.isEmpty(); index++) {
Jeff Brownbe1aa822011-07-27 16:04:54 -070086 uint32_t id = idBits.clearFirstMarkedBit();
Jeff Brown2ed24622011-03-14 19:39:54 -070087
88 float vx, vy;
89 mVelocityTracker.getVelocity(id, &vx, &vy);
90
91 vx = vx * units / 1000;
92 vy = vy * units / 1000;
93
94 if (vx > maxVelocity) {
95 vx = maxVelocity;
96 } else if (vx < -maxVelocity) {
97 vx = -maxVelocity;
98 }
99 if (vy > maxVelocity) {
100 vy = maxVelocity;
101 } else if (vy < -maxVelocity) {
102 vy = -maxVelocity;
103 }
104
105 Velocity& velocity = mCalculatedVelocity[index];
106 velocity.vx = vx;
107 velocity.vy = vy;
108 }
109}
110
111void VelocityTrackerState::getVelocity(int32_t id, float* outVx, float* outVy) {
112 if (id == ACTIVE_POINTER_ID) {
113 id = mVelocityTracker.getActivePointerId();
114 }
115
116 float vx, vy;
117 if (id >= 0 && id <= MAX_POINTER_ID && mCalculatedIdBits.hasBit(id)) {
118 uint32_t index = mCalculatedIdBits.getIndexOfBit(id);
119 const Velocity& velocity = mCalculatedVelocity[index];
120 vx = velocity.vx;
121 vy = velocity.vy;
122 } else {
123 vx = 0;
124 vy = 0;
125 }
126
127 if (outVx) {
128 *outVx = vx;
129 }
130 if (outVy) {
131 *outVy = vy;
132 }
133}
134
Jeff Brown85bd0d62012-05-13 15:30:42 -0700135bool VelocityTrackerState::getEstimator(int32_t id, VelocityTracker::Estimator* outEstimator) {
136 return mVelocityTracker.getEstimator(id, outEstimator);
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700137}
138
Jeff Brown2ed24622011-03-14 19:39:54 -0700139
140// --- JNI Methods ---
141
Ashok Bhat96804bc2014-01-08 15:45:39 +0000142static jlong android_view_VelocityTracker_nativeInitialize(JNIEnv* env, jclass clazz,
Jeff Brown9eb7d862012-06-01 12:39:25 -0700143 jstring strategyStr) {
144 if (strategyStr) {
145 ScopedUtfChars strategy(env, strategyStr);
Ashok Bhat96804bc2014-01-08 15:45:39 +0000146 return reinterpret_cast<jlong>(new VelocityTrackerState(strategy.c_str()));
Jeff Brown9eb7d862012-06-01 12:39:25 -0700147 }
Ashok Bhat96804bc2014-01-08 15:45:39 +0000148 return reinterpret_cast<jlong>(new VelocityTrackerState(NULL));
Jeff Brown2ed24622011-03-14 19:39:54 -0700149}
150
Ashok Bhat96804bc2014-01-08 15:45:39 +0000151static void android_view_VelocityTracker_nativeDispose(JNIEnv* env, jclass clazz, jlong ptr) {
Jeff Brown2ed24622011-03-14 19:39:54 -0700152 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
153 delete state;
154}
155
Ashok Bhat96804bc2014-01-08 15:45:39 +0000156static void android_view_VelocityTracker_nativeClear(JNIEnv* env, jclass clazz, jlong ptr) {
Jeff Brown2ed24622011-03-14 19:39:54 -0700157 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
158 state->clear();
159}
160
Ashok Bhat96804bc2014-01-08 15:45:39 +0000161static void android_view_VelocityTracker_nativeAddMovement(JNIEnv* env, jclass clazz, jlong ptr,
Jeff Brown2ed24622011-03-14 19:39:54 -0700162 jobject eventObj) {
163 const MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj);
164 if (!event) {
Steve Block8564c8d2012-01-05 23:22:43 +0000165 ALOGW("nativeAddMovement failed because MotionEvent was finalized.");
Jeff Brown2ed24622011-03-14 19:39:54 -0700166 return;
167 }
168
169 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
170 state->addMovement(event);
171}
172
173static void android_view_VelocityTracker_nativeComputeCurrentVelocity(JNIEnv* env, jclass clazz,
Ashok Bhat96804bc2014-01-08 15:45:39 +0000174 jlong ptr, jint units, jfloat maxVelocity) {
Jeff Brown2ed24622011-03-14 19:39:54 -0700175 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
176 state->computeCurrentVelocity(units, maxVelocity);
177}
178
179static jfloat android_view_VelocityTracker_nativeGetXVelocity(JNIEnv* env, jclass clazz,
Ashok Bhat96804bc2014-01-08 15:45:39 +0000180 jlong ptr, jint id) {
Jeff Brown2ed24622011-03-14 19:39:54 -0700181 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
182 float vx;
183 state->getVelocity(id, &vx, NULL);
184 return vx;
185}
186
187static jfloat android_view_VelocityTracker_nativeGetYVelocity(JNIEnv* env, jclass clazz,
Ashok Bhat96804bc2014-01-08 15:45:39 +0000188 jlong ptr, jint id) {
Jeff Brown2ed24622011-03-14 19:39:54 -0700189 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
190 float vy;
191 state->getVelocity(id, NULL, &vy);
192 return vy;
193}
194
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700195static jboolean android_view_VelocityTracker_nativeGetEstimator(JNIEnv* env, jclass clazz,
Ashok Bhat96804bc2014-01-08 15:45:39 +0000196 jlong ptr, jint id, jobject outEstimatorObj) {
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700197 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
198 VelocityTracker::Estimator estimator;
Jeff Brown85bd0d62012-05-13 15:30:42 -0700199 bool result = state->getEstimator(id, &estimator);
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700200
201 jfloatArray xCoeffObj = jfloatArray(env->GetObjectField(outEstimatorObj,
202 gEstimatorClassInfo.xCoeff));
203 jfloatArray yCoeffObj = jfloatArray(env->GetObjectField(outEstimatorObj,
204 gEstimatorClassInfo.yCoeff));
205
206 env->SetFloatArrayRegion(xCoeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
207 estimator.xCoeff);
208 env->SetFloatArrayRegion(yCoeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
209 estimator.yCoeff);
210 env->SetIntField(outEstimatorObj, gEstimatorClassInfo.degree, estimator.degree);
211 env->SetFloatField(outEstimatorObj, gEstimatorClassInfo.confidence, estimator.confidence);
212 return result;
213}
214
Jeff Brown2ed24622011-03-14 19:39:54 -0700215
216// --- JNI Registration ---
217
Daniel Micay76f6a862015-09-19 17:31:01 -0400218static const JNINativeMethod gVelocityTrackerMethods[] = {
Jeff Brown2ed24622011-03-14 19:39:54 -0700219 /* name, signature, funcPtr */
220 { "nativeInitialize",
Ashok Bhat96804bc2014-01-08 15:45:39 +0000221 "(Ljava/lang/String;)J",
Jeff Brown2ed24622011-03-14 19:39:54 -0700222 (void*)android_view_VelocityTracker_nativeInitialize },
223 { "nativeDispose",
Ashok Bhat96804bc2014-01-08 15:45:39 +0000224 "(J)V",
Jeff Brown2ed24622011-03-14 19:39:54 -0700225 (void*)android_view_VelocityTracker_nativeDispose },
226 { "nativeClear",
Ashok Bhat96804bc2014-01-08 15:45:39 +0000227 "(J)V",
Jeff Brown2ed24622011-03-14 19:39:54 -0700228 (void*)android_view_VelocityTracker_nativeClear },
229 { "nativeAddMovement",
Ashok Bhat96804bc2014-01-08 15:45:39 +0000230 "(JLandroid/view/MotionEvent;)V",
Jeff Brown2ed24622011-03-14 19:39:54 -0700231 (void*)android_view_VelocityTracker_nativeAddMovement },
232 { "nativeComputeCurrentVelocity",
Ashok Bhat96804bc2014-01-08 15:45:39 +0000233 "(JIF)V",
Jeff Brown2ed24622011-03-14 19:39:54 -0700234 (void*)android_view_VelocityTracker_nativeComputeCurrentVelocity },
235 { "nativeGetXVelocity",
Ashok Bhat96804bc2014-01-08 15:45:39 +0000236 "(JI)F",
Jeff Brown2ed24622011-03-14 19:39:54 -0700237 (void*)android_view_VelocityTracker_nativeGetXVelocity },
238 { "nativeGetYVelocity",
Ashok Bhat96804bc2014-01-08 15:45:39 +0000239 "(JI)F",
Jeff Brown2ed24622011-03-14 19:39:54 -0700240 (void*)android_view_VelocityTracker_nativeGetYVelocity },
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700241 { "nativeGetEstimator",
Ashok Bhat96804bc2014-01-08 15:45:39 +0000242 "(JILandroid/view/VelocityTracker$Estimator;)Z",
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700243 (void*)android_view_VelocityTracker_nativeGetEstimator },
Jeff Brown2ed24622011-03-14 19:39:54 -0700244};
245
246int register_android_view_VelocityTracker(JNIEnv* env) {
Andreas Gampe987f79f2014-11-18 17:29:46 -0800247 int res = RegisterMethodsOrDie(env, "android/view/VelocityTracker", gVelocityTrackerMethods,
248 NELEM(gVelocityTrackerMethods));
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700249
Andreas Gampe987f79f2014-11-18 17:29:46 -0800250 jclass clazz = FindClassOrDie(env, "android/view/VelocityTracker$Estimator");
Jeff Brownb59ab9f2011-09-14 10:53:18 -0700251
Andreas Gampe987f79f2014-11-18 17:29:46 -0800252 gEstimatorClassInfo.xCoeff = GetFieldIDOrDie(env, clazz, "xCoeff", "[F");
253 gEstimatorClassInfo.yCoeff = GetFieldIDOrDie(env, clazz, "yCoeff", "[F");
254 gEstimatorClassInfo.degree = GetFieldIDOrDie(env, clazz, "degree", "I");
255 gEstimatorClassInfo.confidence = GetFieldIDOrDie(env, clazz, "confidence", "F");
256
257 return res;
Jeff Brown2ed24622011-03-14 19:39:54 -0700258}
259
260} // namespace android