blob: daa0adc243ddcb5e025f5d12652d9db7616cb934 [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>
23#include <ui/Input.h>
24#include "android_view_MotionEvent.h"
25
26
27namespace android {
28
29// Special constant to request the velocity of the active pointer.
30static const int ACTIVE_POINTER_ID = -1;
31
32// --- VelocityTrackerState ---
33
34class VelocityTrackerState {
35public:
36 VelocityTrackerState();
37
38 void clear();
39 void addMovement(const MotionEvent* event);
40 void computeCurrentVelocity(int32_t units, float maxVelocity);
41 void getVelocity(int32_t id, float* outVx, float* outVy);
42
43private:
44 struct Velocity {
45 float vx, vy;
46 };
47
48 VelocityTracker mVelocityTracker;
49 int32_t mActivePointerId;
50 BitSet32 mCalculatedIdBits;
51 Velocity mCalculatedVelocity[MAX_POINTERS];
52};
53
54VelocityTrackerState::VelocityTrackerState() : mActivePointerId(-1) {
55}
56
57void VelocityTrackerState::clear() {
58 mVelocityTracker.clear();
59 mActivePointerId = -1;
60 mCalculatedIdBits.clear();
61}
62
63void VelocityTrackerState::addMovement(const MotionEvent* event) {
64 mVelocityTracker.addMovement(event);
65}
66
67void VelocityTrackerState::computeCurrentVelocity(int32_t units, float maxVelocity) {
68 BitSet32 idBits(mVelocityTracker.getCurrentPointerIdBits());
69 mCalculatedIdBits = idBits;
70
71 for (uint32_t index = 0; !idBits.isEmpty(); index++) {
72 uint32_t id = idBits.firstMarkedBit();
73 idBits.clearBit(id);
74
75 float vx, vy;
76 mVelocityTracker.getVelocity(id, &vx, &vy);
77
78 vx = vx * units / 1000;
79 vy = vy * units / 1000;
80
81 if (vx > maxVelocity) {
82 vx = maxVelocity;
83 } else if (vx < -maxVelocity) {
84 vx = -maxVelocity;
85 }
86 if (vy > maxVelocity) {
87 vy = maxVelocity;
88 } else if (vy < -maxVelocity) {
89 vy = -maxVelocity;
90 }
91
92 Velocity& velocity = mCalculatedVelocity[index];
93 velocity.vx = vx;
94 velocity.vy = vy;
95 }
96}
97
98void VelocityTrackerState::getVelocity(int32_t id, float* outVx, float* outVy) {
99 if (id == ACTIVE_POINTER_ID) {
100 id = mVelocityTracker.getActivePointerId();
101 }
102
103 float vx, vy;
104 if (id >= 0 && id <= MAX_POINTER_ID && mCalculatedIdBits.hasBit(id)) {
105 uint32_t index = mCalculatedIdBits.getIndexOfBit(id);
106 const Velocity& velocity = mCalculatedVelocity[index];
107 vx = velocity.vx;
108 vy = velocity.vy;
109 } else {
110 vx = 0;
111 vy = 0;
112 }
113
114 if (outVx) {
115 *outVx = vx;
116 }
117 if (outVy) {
118 *outVy = vy;
119 }
120}
121
122
123// --- JNI Methods ---
124
125static jint android_view_VelocityTracker_nativeInitialize(JNIEnv* env, jclass clazz) {
126 return reinterpret_cast<jint>(new VelocityTrackerState());
127}
128
129static void android_view_VelocityTracker_nativeDispose(JNIEnv* env, jclass clazz, jint ptr) {
130 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
131 delete state;
132}
133
134static void android_view_VelocityTracker_nativeClear(JNIEnv* env, jclass clazz, jint ptr) {
135 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
136 state->clear();
137}
138
139static void android_view_VelocityTracker_nativeAddMovement(JNIEnv* env, jclass clazz, jint ptr,
140 jobject eventObj) {
141 const MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj);
142 if (!event) {
143 LOGW("nativeAddMovement failed because MotionEvent was finalized.");
144 return;
145 }
146
147 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
148 state->addMovement(event);
149}
150
151static void android_view_VelocityTracker_nativeComputeCurrentVelocity(JNIEnv* env, jclass clazz,
152 jint ptr, jint units, jfloat maxVelocity) {
153 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
154 state->computeCurrentVelocity(units, maxVelocity);
155}
156
157static jfloat android_view_VelocityTracker_nativeGetXVelocity(JNIEnv* env, jclass clazz,
158 jint ptr, jint id) {
159 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
160 float vx;
161 state->getVelocity(id, &vx, NULL);
162 return vx;
163}
164
165static jfloat android_view_VelocityTracker_nativeGetYVelocity(JNIEnv* env, jclass clazz,
166 jint ptr, jint id) {
167 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
168 float vy;
169 state->getVelocity(id, NULL, &vy);
170 return vy;
171}
172
173
174// --- JNI Registration ---
175
176static JNINativeMethod gVelocityTrackerMethods[] = {
177 /* name, signature, funcPtr */
178 { "nativeInitialize",
179 "()I",
180 (void*)android_view_VelocityTracker_nativeInitialize },
181 { "nativeDispose",
182 "(I)V",
183 (void*)android_view_VelocityTracker_nativeDispose },
184 { "nativeClear",
185 "(I)V",
186 (void*)android_view_VelocityTracker_nativeClear },
187 { "nativeAddMovement",
188 "(ILandroid/view/MotionEvent;)V",
189 (void*)android_view_VelocityTracker_nativeAddMovement },
190 { "nativeComputeCurrentVelocity",
191 "(IIF)V",
192 (void*)android_view_VelocityTracker_nativeComputeCurrentVelocity },
193 { "nativeGetXVelocity",
194 "(II)F",
195 (void*)android_view_VelocityTracker_nativeGetXVelocity },
196 { "nativeGetYVelocity",
197 "(II)F",
198 (void*)android_view_VelocityTracker_nativeGetYVelocity },
199};
200
201int register_android_view_VelocityTracker(JNIEnv* env) {
202 int res = jniRegisterNativeMethods(env, "android/view/VelocityTracker",
203 gVelocityTrackerMethods, NELEM(gVelocityTrackerMethods));
204 LOG_FATAL_IF(res < 0, "Unable to register native methods.");
205 return 0;
206}
207
208} // namespace android