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 <android-base/logging.h>
20 #include <android_runtime/AndroidRuntime.h>
21 #include <cutils/properties.h>
22 #include <input/Input.h>
23 #include <input/VelocityTracker.h>
24 #include <nativehelper/JNIHelp.h>
25 #include <nativehelper/ScopedUtfChars.h>
26
27 #include "android_view_MotionEvent.h"
28 #include "core_jni_helpers.h"
29
30 namespace android {
31
32 // Special constant to request the velocity of the active pointer.
33 static const int ACTIVE_POINTER_ID = -1;
34
35 // --- VelocityTrackerState ---
36
37 class VelocityTrackerState {
38 public:
39 explicit VelocityTrackerState(const VelocityTracker::Strategy strategy);
40
41 void clear();
42 void addMovement(const MotionEvent& event);
43 // TODO(b/32830165): consider supporting an overload that supports computing velocity only for
44 // a subset of the supported axes.
45 void computeCurrentVelocity(int32_t units, float maxVelocity);
46 float getVelocity(int32_t axis, int32_t id);
47
48 private:
49 VelocityTracker mVelocityTracker;
50 VelocityTracker::ComputedVelocity mComputedVelocity;
51 };
52
VelocityTrackerState(const VelocityTracker::Strategy strategy)53 VelocityTrackerState::VelocityTrackerState(const VelocityTracker::Strategy strategy)
54 : mVelocityTracker(strategy) {}
55
clear()56 void VelocityTrackerState::clear() {
57 mVelocityTracker.clear();
58 }
59
addMovement(const MotionEvent & event)60 void VelocityTrackerState::addMovement(const MotionEvent& event) {
61 mVelocityTracker.addMovement(event);
62 }
63
computeCurrentVelocity(int32_t units,float maxVelocity)64 void VelocityTrackerState::computeCurrentVelocity(int32_t units, float maxVelocity) {
65 mComputedVelocity = mVelocityTracker.getComputedVelocity(units, maxVelocity);
66 }
67
getVelocity(int32_t axis,int32_t id)68 float VelocityTrackerState::getVelocity(int32_t axis, int32_t id) {
69 if (id == ACTIVE_POINTER_ID) {
70 id = mVelocityTracker.getActivePointerId();
71 }
72
73 return mComputedVelocity.getVelocity(axis, id).value_or(0);
74 }
75
76 // Return a strategy enum from integer value.
getStrategyFromInt(const int32_t strategy)77 inline static VelocityTracker::Strategy getStrategyFromInt(const int32_t strategy) {
78 if (strategy < static_cast<int32_t>(VelocityTracker::Strategy::MIN) ||
79 strategy > static_cast<int32_t>(VelocityTracker::Strategy::MAX)) {
80 return VelocityTracker::Strategy::DEFAULT;
81 }
82 return static_cast<VelocityTracker::Strategy>(strategy);
83 }
84
85 // --- JNI Methods ---
86
android_view_VelocityTracker_nativeInitialize(JNIEnv * env,jclass clazz,jint strategy)87 static jlong android_view_VelocityTracker_nativeInitialize(JNIEnv* env, jclass clazz,
88 jint strategy) {
89 return reinterpret_cast<jlong>(new VelocityTrackerState(getStrategyFromInt(strategy)));
90 }
91
android_view_VelocityTracker_nativeDispose(JNIEnv * env,jclass clazz,jlong ptr)92 static void android_view_VelocityTracker_nativeDispose(JNIEnv* env, jclass clazz, jlong ptr) {
93 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
94 delete state;
95 }
96
android_view_VelocityTracker_nativeClear(JNIEnv * env,jclass clazz,jlong ptr)97 static void android_view_VelocityTracker_nativeClear(JNIEnv* env, jclass clazz, jlong ptr) {
98 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
99 state->clear();
100 }
101
android_view_VelocityTracker_nativeAddMovement(JNIEnv * env,jclass clazz,jlong ptr,jobject eventObj)102 static void android_view_VelocityTracker_nativeAddMovement(JNIEnv* env, jclass clazz, jlong ptr,
103 jobject eventObj) {
104 const MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj);
105 if (event == nullptr) {
106 LOG(WARNING) << "nativeAddMovement failed because MotionEvent was finalized.";
107 return;
108 }
109
110 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
111 state->addMovement(*event);
112 }
113
android_view_VelocityTracker_nativeComputeCurrentVelocity(JNIEnv * env,jclass clazz,jlong ptr,jint units,jfloat maxVelocity)114 static void android_view_VelocityTracker_nativeComputeCurrentVelocity(JNIEnv* env, jclass clazz,
115 jlong ptr, jint units, jfloat maxVelocity) {
116 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
117 state->computeCurrentVelocity(units, maxVelocity);
118 }
119
android_view_VelocityTracker_nativeGetVelocity(JNIEnv * env,jclass clazz,jlong ptr,jint axis,jint id)120 static jfloat android_view_VelocityTracker_nativeGetVelocity(JNIEnv* env, jclass clazz, jlong ptr,
121 jint axis, jint id) {
122 VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
123 return state->getVelocity(axis, id);
124 }
125
android_view_VelocityTracker_nativeIsAxisSupported(JNIEnv * env,jclass clazz,jint axis)126 static jboolean android_view_VelocityTracker_nativeIsAxisSupported(JNIEnv* env, jclass clazz,
127 jint axis) {
128 return VelocityTracker::isAxisSupported(axis);
129 }
130
131 // --- JNI Registration ---
132
133 static const JNINativeMethod gVelocityTrackerMethods[] = {
134 /* name, signature, funcPtr */
135 {"nativeInitialize", "(I)J", (void*)android_view_VelocityTracker_nativeInitialize},
136 {"nativeDispose", "(J)V", (void*)android_view_VelocityTracker_nativeDispose},
137 {"nativeClear", "(J)V", (void*)android_view_VelocityTracker_nativeClear},
138 {"nativeAddMovement", "(JLandroid/view/MotionEvent;)V",
139 (void*)android_view_VelocityTracker_nativeAddMovement},
140 {"nativeComputeCurrentVelocity", "(JIF)V",
141 (void*)android_view_VelocityTracker_nativeComputeCurrentVelocity},
142 {"nativeGetVelocity", "(JII)F", (void*)android_view_VelocityTracker_nativeGetVelocity},
143 {"nativeIsAxisSupported", "(I)Z",
144 (void*)android_view_VelocityTracker_nativeIsAxisSupported},
145 };
146
register_android_view_VelocityTracker(JNIEnv * env)147 int register_android_view_VelocityTracker(JNIEnv* env) {
148 return RegisterMethodsOrDie(env, "android/view/VelocityTracker", gVelocityTrackerMethods,
149 NELEM(gVelocityTrackerMethods));
150 }
151
152 } // namespace android
153