android_view_VelocityTracker.cpp revision 2ed2462aa29c564f5231f317c27b3188da875e52
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.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 209