/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "VelocityTracker-JNI" #include "JNIHelp.h" #include #include #include #include "android_view_MotionEvent.h" namespace android { // Special constant to request the velocity of the active pointer. static const int ACTIVE_POINTER_ID = -1; // --- VelocityTrackerState --- class VelocityTrackerState { public: VelocityTrackerState(); void clear(); void addMovement(const MotionEvent* event); void computeCurrentVelocity(int32_t units, float maxVelocity); void getVelocity(int32_t id, float* outVx, float* outVy); private: struct Velocity { float vx, vy; }; VelocityTracker mVelocityTracker; int32_t mActivePointerId; BitSet32 mCalculatedIdBits; Velocity mCalculatedVelocity[MAX_POINTERS]; }; VelocityTrackerState::VelocityTrackerState() : mActivePointerId(-1) { } void VelocityTrackerState::clear() { mVelocityTracker.clear(); mActivePointerId = -1; mCalculatedIdBits.clear(); } void VelocityTrackerState::addMovement(const MotionEvent* event) { mVelocityTracker.addMovement(event); } void VelocityTrackerState::computeCurrentVelocity(int32_t units, float maxVelocity) { BitSet32 idBits(mVelocityTracker.getCurrentPointerIdBits()); mCalculatedIdBits = idBits; for (uint32_t index = 0; !idBits.isEmpty(); index++) { uint32_t id = idBits.firstMarkedBit(); idBits.clearBit(id); float vx, vy; mVelocityTracker.getVelocity(id, &vx, &vy); vx = vx * units / 1000; vy = vy * units / 1000; if (vx > maxVelocity) { vx = maxVelocity; } else if (vx < -maxVelocity) { vx = -maxVelocity; } if (vy > maxVelocity) { vy = maxVelocity; } else if (vy < -maxVelocity) { vy = -maxVelocity; } Velocity& velocity = mCalculatedVelocity[index]; velocity.vx = vx; velocity.vy = vy; } } void VelocityTrackerState::getVelocity(int32_t id, float* outVx, float* outVy) { if (id == ACTIVE_POINTER_ID) { id = mVelocityTracker.getActivePointerId(); } float vx, vy; if (id >= 0 && id <= MAX_POINTER_ID && mCalculatedIdBits.hasBit(id)) { uint32_t index = mCalculatedIdBits.getIndexOfBit(id); const Velocity& velocity = mCalculatedVelocity[index]; vx = velocity.vx; vy = velocity.vy; } else { vx = 0; vy = 0; } if (outVx) { *outVx = vx; } if (outVy) { *outVy = vy; } } // --- JNI Methods --- static jint android_view_VelocityTracker_nativeInitialize(JNIEnv* env, jclass clazz) { return reinterpret_cast(new VelocityTrackerState()); } static void android_view_VelocityTracker_nativeDispose(JNIEnv* env, jclass clazz, jint ptr) { VelocityTrackerState* state = reinterpret_cast(ptr); delete state; } static void android_view_VelocityTracker_nativeClear(JNIEnv* env, jclass clazz, jint ptr) { VelocityTrackerState* state = reinterpret_cast(ptr); state->clear(); } static void android_view_VelocityTracker_nativeAddMovement(JNIEnv* env, jclass clazz, jint ptr, jobject eventObj) { const MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj); if (!event) { LOGW("nativeAddMovement failed because MotionEvent was finalized."); return; } VelocityTrackerState* state = reinterpret_cast(ptr); state->addMovement(event); } static void android_view_VelocityTracker_nativeComputeCurrentVelocity(JNIEnv* env, jclass clazz, jint ptr, jint units, jfloat maxVelocity) { VelocityTrackerState* state = reinterpret_cast(ptr); state->computeCurrentVelocity(units, maxVelocity); } static jfloat android_view_VelocityTracker_nativeGetXVelocity(JNIEnv* env, jclass clazz, jint ptr, jint id) { VelocityTrackerState* state = reinterpret_cast(ptr); float vx; state->getVelocity(id, &vx, NULL); return vx; } static jfloat android_view_VelocityTracker_nativeGetYVelocity(JNIEnv* env, jclass clazz, jint ptr, jint id) { VelocityTrackerState* state = reinterpret_cast(ptr); float vy; state->getVelocity(id, NULL, &vy); return vy; } // --- JNI Registration --- static JNINativeMethod gVelocityTrackerMethods[] = { /* name, signature, funcPtr */ { "nativeInitialize", "()I", (void*)android_view_VelocityTracker_nativeInitialize }, { "nativeDispose", "(I)V", (void*)android_view_VelocityTracker_nativeDispose }, { "nativeClear", "(I)V", (void*)android_view_VelocityTracker_nativeClear }, { "nativeAddMovement", "(ILandroid/view/MotionEvent;)V", (void*)android_view_VelocityTracker_nativeAddMovement }, { "nativeComputeCurrentVelocity", "(IIF)V", (void*)android_view_VelocityTracker_nativeComputeCurrentVelocity }, { "nativeGetXVelocity", "(II)F", (void*)android_view_VelocityTracker_nativeGetXVelocity }, { "nativeGetYVelocity", "(II)F", (void*)android_view_VelocityTracker_nativeGetYVelocity }, }; int register_android_view_VelocityTracker(JNIEnv* env) { int res = jniRegisterNativeMethods(env, "android/view/VelocityTracker", gVelocityTrackerMethods, NELEM(gVelocityTrackerMethods)); LOG_FATAL_IF(res < 0, "Unable to register native methods."); return 0; } } // namespace android