/* * 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 #include #include #include #include #include #include #include "android_view_MotionEvent.h" #include "core_jni_helpers.h" namespace android { // Special constant to request the velocity of the active pointer. static const int ACTIVE_POINTER_ID = -1; // --- VelocityTrackerState --- class VelocityTrackerState { public: explicit VelocityTrackerState(const VelocityTracker::Strategy strategy); void clear(); void addMovement(const MotionEvent& event); // TODO(b/32830165): consider supporting an overload that supports computing velocity only for // a subset of the supported axes. void computeCurrentVelocity(int32_t units, float maxVelocity); float getVelocity(int32_t axis, int32_t id); private: VelocityTracker mVelocityTracker; VelocityTracker::ComputedVelocity mComputedVelocity; }; VelocityTrackerState::VelocityTrackerState(const VelocityTracker::Strategy strategy) : mVelocityTracker(strategy) {} void VelocityTrackerState::clear() { mVelocityTracker.clear(); } void VelocityTrackerState::addMovement(const MotionEvent& event) { mVelocityTracker.addMovement(event); } void VelocityTrackerState::computeCurrentVelocity(int32_t units, float maxVelocity) { mComputedVelocity = mVelocityTracker.getComputedVelocity(units, maxVelocity); } float VelocityTrackerState::getVelocity(int32_t axis, int32_t id) { if (id == ACTIVE_POINTER_ID) { id = mVelocityTracker.getActivePointerId(); } return mComputedVelocity.getVelocity(axis, id).value_or(0); } // Return a strategy enum from integer value. inline static VelocityTracker::Strategy getStrategyFromInt(const int32_t strategy) { if (strategy < static_cast(VelocityTracker::Strategy::MIN) || strategy > static_cast(VelocityTracker::Strategy::MAX)) { return VelocityTracker::Strategy::DEFAULT; } return static_cast(strategy); } // --- JNI Methods --- static jlong android_view_VelocityTracker_nativeInitialize(JNIEnv* env, jclass clazz, jint strategy) { return reinterpret_cast(new VelocityTrackerState(getStrategyFromInt(strategy))); } static void android_view_VelocityTracker_nativeDispose(JNIEnv* env, jclass clazz, jlong ptr) { VelocityTrackerState* state = reinterpret_cast(ptr); delete state; } static void android_view_VelocityTracker_nativeClear(JNIEnv* env, jclass clazz, jlong ptr) { VelocityTrackerState* state = reinterpret_cast(ptr); state->clear(); } static void android_view_VelocityTracker_nativeAddMovement(JNIEnv* env, jclass clazz, jlong ptr, jobject eventObj) { const MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj); if (event == nullptr) { LOG(WARNING) << "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, jlong ptr, jint units, jfloat maxVelocity) { VelocityTrackerState* state = reinterpret_cast(ptr); state->computeCurrentVelocity(units, maxVelocity); } static jfloat android_view_VelocityTracker_nativeGetVelocity(JNIEnv* env, jclass clazz, jlong ptr, jint axis, jint id) { VelocityTrackerState* state = reinterpret_cast(ptr); return state->getVelocity(axis, id); } static jboolean android_view_VelocityTracker_nativeIsAxisSupported(JNIEnv* env, jclass clazz, jint axis) { return VelocityTracker::isAxisSupported(axis); } // --- JNI Registration --- static const JNINativeMethod gVelocityTrackerMethods[] = { /* name, signature, funcPtr */ {"nativeInitialize", "(I)J", (void*)android_view_VelocityTracker_nativeInitialize}, {"nativeDispose", "(J)V", (void*)android_view_VelocityTracker_nativeDispose}, {"nativeClear", "(J)V", (void*)android_view_VelocityTracker_nativeClear}, {"nativeAddMovement", "(JLandroid/view/MotionEvent;)V", (void*)android_view_VelocityTracker_nativeAddMovement}, {"nativeComputeCurrentVelocity", "(JIF)V", (void*)android_view_VelocityTracker_nativeComputeCurrentVelocity}, {"nativeGetVelocity", "(JII)F", (void*)android_view_VelocityTracker_nativeGetVelocity}, {"nativeIsAxisSupported", "(I)Z", (void*)android_view_VelocityTracker_nativeIsAxisSupported}, }; int register_android_view_VelocityTracker(JNIEnv* env) { return RegisterMethodsOrDie(env, "android/view/VelocityTracker", gVelocityTrackerMethods, NELEM(gVelocityTrackerMethods)); } } // namespace android