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