android_view_VelocityTracker.cpp revision be1aa8250cee7819c49741e819e81659d1d03823
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 <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.clearFirstMarkedBit(); 73 74 float vx, vy; 75 mVelocityTracker.getVelocity(id, &vx, &vy); 76 77 vx = vx * units / 1000; 78 vy = vy * units / 1000; 79 80 if (vx > maxVelocity) { 81 vx = maxVelocity; 82 } else if (vx < -maxVelocity) { 83 vx = -maxVelocity; 84 } 85 if (vy > maxVelocity) { 86 vy = maxVelocity; 87 } else if (vy < -maxVelocity) { 88 vy = -maxVelocity; 89 } 90 91 Velocity& velocity = mCalculatedVelocity[index]; 92 velocity.vx = vx; 93 velocity.vy = vy; 94 } 95} 96 97void VelocityTrackerState::getVelocity(int32_t id, float* outVx, float* outVy) { 98 if (id == ACTIVE_POINTER_ID) { 99 id = mVelocityTracker.getActivePointerId(); 100 } 101 102 float vx, vy; 103 if (id >= 0 && id <= MAX_POINTER_ID && mCalculatedIdBits.hasBit(id)) { 104 uint32_t index = mCalculatedIdBits.getIndexOfBit(id); 105 const Velocity& velocity = mCalculatedVelocity[index]; 106 vx = velocity.vx; 107 vy = velocity.vy; 108 } else { 109 vx = 0; 110 vy = 0; 111 } 112 113 if (outVx) { 114 *outVx = vx; 115 } 116 if (outVy) { 117 *outVy = vy; 118 } 119} 120 121 122// --- JNI Methods --- 123 124static jint android_view_VelocityTracker_nativeInitialize(JNIEnv* env, jclass clazz) { 125 return reinterpret_cast<jint>(new VelocityTrackerState()); 126} 127 128static void android_view_VelocityTracker_nativeDispose(JNIEnv* env, jclass clazz, jint ptr) { 129 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr); 130 delete state; 131} 132 133static void android_view_VelocityTracker_nativeClear(JNIEnv* env, jclass clazz, jint ptr) { 134 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr); 135 state->clear(); 136} 137 138static void android_view_VelocityTracker_nativeAddMovement(JNIEnv* env, jclass clazz, jint ptr, 139 jobject eventObj) { 140 const MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj); 141 if (!event) { 142 LOGW("nativeAddMovement failed because MotionEvent was finalized."); 143 return; 144 } 145 146 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr); 147 state->addMovement(event); 148} 149 150static void android_view_VelocityTracker_nativeComputeCurrentVelocity(JNIEnv* env, jclass clazz, 151 jint ptr, jint units, jfloat maxVelocity) { 152 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr); 153 state->computeCurrentVelocity(units, maxVelocity); 154} 155 156static jfloat android_view_VelocityTracker_nativeGetXVelocity(JNIEnv* env, jclass clazz, 157 jint ptr, jint id) { 158 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr); 159 float vx; 160 state->getVelocity(id, &vx, NULL); 161 return vx; 162} 163 164static jfloat android_view_VelocityTracker_nativeGetYVelocity(JNIEnv* env, jclass clazz, 165 jint ptr, jint id) { 166 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr); 167 float vy; 168 state->getVelocity(id, NULL, &vy); 169 return vy; 170} 171 172 173// --- JNI Registration --- 174 175static JNINativeMethod gVelocityTrackerMethods[] = { 176 /* name, signature, funcPtr */ 177 { "nativeInitialize", 178 "()I", 179 (void*)android_view_VelocityTracker_nativeInitialize }, 180 { "nativeDispose", 181 "(I)V", 182 (void*)android_view_VelocityTracker_nativeDispose }, 183 { "nativeClear", 184 "(I)V", 185 (void*)android_view_VelocityTracker_nativeClear }, 186 { "nativeAddMovement", 187 "(ILandroid/view/MotionEvent;)V", 188 (void*)android_view_VelocityTracker_nativeAddMovement }, 189 { "nativeComputeCurrentVelocity", 190 "(IIF)V", 191 (void*)android_view_VelocityTracker_nativeComputeCurrentVelocity }, 192 { "nativeGetXVelocity", 193 "(II)F", 194 (void*)android_view_VelocityTracker_nativeGetXVelocity }, 195 { "nativeGetYVelocity", 196 "(II)F", 197 (void*)android_view_VelocityTracker_nativeGetYVelocity }, 198}; 199 200int register_android_view_VelocityTracker(JNIEnv* env) { 201 int res = jniRegisterNativeMethods(env, "android/view/VelocityTracker", 202 gVelocityTrackerMethods, NELEM(gVelocityTrackerMethods)); 203 LOG_FATAL_IF(res < 0, "Unable to register native methods."); 204 return 0; 205} 206 207} // namespace android 208