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