12ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown/*
22ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown * Copyright (C) 2011 The Android Open Source Project
32ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown *
42ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
52ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown * you may not use this file except in compliance with the License.
62ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown * You may obtain a copy of the License at
72ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown *
82ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
92ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown *
102ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown * Unless required by applicable law or agreed to in writing, software
112ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
122ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown * See the License for the specific language governing permissions and
142ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown * limitations under the License.
152ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown */
162ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
172ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown#define LOG_TAG "VelocityTracker-JNI"
182ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
192ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown#include "JNIHelp.h"
202ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
212ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown#include <android_runtime/AndroidRuntime.h>
222ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown#include <utils/Log.h>
232ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown#include <ui/Input.h>
242ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown#include "android_view_MotionEvent.h"
252ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
262ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
272ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownnamespace android {
282ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
292ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown// Special constant to request the velocity of the active pointer.
302ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownstatic const int ACTIVE_POINTER_ID = -1;
312ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
32b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brownstatic struct {
33b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    jfieldID xCoeff;
34b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    jfieldID yCoeff;
35b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    jfieldID degree;
36b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    jfieldID confidence;
37b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown} gEstimatorClassInfo;
38b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
39b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
402ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown// --- VelocityTrackerState ---
412ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
422ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownclass VelocityTrackerState {
432ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownpublic:
442ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    VelocityTrackerState();
452ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
462ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    void clear();
472ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    void addMovement(const MotionEvent* event);
482ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    void computeCurrentVelocity(int32_t units, float maxVelocity);
492ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    void getVelocity(int32_t id, float* outVx, float* outVy);
50b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    bool getEstimator(int32_t id, uint32_t degree, nsecs_t horizon,
51b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            VelocityTracker::Estimator* outEstimator);
522ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
532ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownprivate:
542ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    struct Velocity {
552ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        float vx, vy;
562ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    };
572ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
582ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    VelocityTracker mVelocityTracker;
592ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    int32_t mActivePointerId;
602ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    BitSet32 mCalculatedIdBits;
612ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    Velocity mCalculatedVelocity[MAX_POINTERS];
622ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown};
632ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
642ed2462aa29c564f5231f317c27b3188da875e52Jeff BrownVelocityTrackerState::VelocityTrackerState() : mActivePointerId(-1) {
652ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
662ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
672ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownvoid VelocityTrackerState::clear() {
682ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    mVelocityTracker.clear();
692ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    mActivePointerId = -1;
702ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    mCalculatedIdBits.clear();
712ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
722ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
732ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownvoid VelocityTrackerState::addMovement(const MotionEvent* event) {
742ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    mVelocityTracker.addMovement(event);
752ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
762ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
772ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownvoid VelocityTrackerState::computeCurrentVelocity(int32_t units, float maxVelocity) {
782ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    BitSet32 idBits(mVelocityTracker.getCurrentPointerIdBits());
792ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    mCalculatedIdBits = idBits;
802ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
812ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    for (uint32_t index = 0; !idBits.isEmpty(); index++) {
82be1aa8250cee7819c49741e819e81659d1d03823Jeff Brown        uint32_t id = idBits.clearFirstMarkedBit();
832ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
842ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        float vx, vy;
852ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        mVelocityTracker.getVelocity(id, &vx, &vy);
862ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
872ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        vx = vx * units / 1000;
882ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        vy = vy * units / 1000;
892ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
902ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        if (vx > maxVelocity) {
912ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            vx = maxVelocity;
922ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        } else if (vx < -maxVelocity) {
932ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            vx = -maxVelocity;
942ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        }
952ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        if (vy > maxVelocity) {
962ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            vy = maxVelocity;
972ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        } else if (vy < -maxVelocity) {
982ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            vy = -maxVelocity;
992ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        }
1002ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
1012ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        Velocity& velocity = mCalculatedVelocity[index];
1022ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        velocity.vx = vx;
1032ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        velocity.vy = vy;
1042ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
1052ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
1062ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
1072ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownvoid VelocityTrackerState::getVelocity(int32_t id, float* outVx, float* outVy) {
1082ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    if (id == ACTIVE_POINTER_ID) {
1092ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        id = mVelocityTracker.getActivePointerId();
1102ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
1112ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
1122ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    float vx, vy;
1132ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    if (id >= 0 && id <= MAX_POINTER_ID && mCalculatedIdBits.hasBit(id)) {
1142ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        uint32_t index = mCalculatedIdBits.getIndexOfBit(id);
1152ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        const Velocity& velocity = mCalculatedVelocity[index];
1162ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        vx = velocity.vx;
1172ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        vy = velocity.vy;
1182ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    } else {
1192ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        vx = 0;
1202ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        vy = 0;
1212ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
1222ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
1232ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    if (outVx) {
1242ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        *outVx = vx;
1252ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
1262ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    if (outVy) {
1272ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        *outVy = vy;
1282ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
1292ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
1302ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
131b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brownbool VelocityTrackerState::getEstimator(int32_t id, uint32_t degree, nsecs_t horizon,
132b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        VelocityTracker::Estimator* outEstimator) {
133b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    return mVelocityTracker.getEstimator(id, degree, horizon, outEstimator);
134b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown}
135b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
1362ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
1372ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown// --- JNI Methods ---
1382ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
1392ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownstatic jint android_view_VelocityTracker_nativeInitialize(JNIEnv* env, jclass clazz) {
1402ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    return reinterpret_cast<jint>(new VelocityTrackerState());
1412ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
1422ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
1432ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownstatic void android_view_VelocityTracker_nativeDispose(JNIEnv* env, jclass clazz, jint ptr) {
1442ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
1452ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    delete state;
1462ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
1472ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
1482ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownstatic void android_view_VelocityTracker_nativeClear(JNIEnv* env, jclass clazz, jint ptr) {
1492ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
1502ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    state->clear();
1512ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
1522ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
1532ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownstatic void android_view_VelocityTracker_nativeAddMovement(JNIEnv* env, jclass clazz, jint ptr,
1542ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        jobject eventObj) {
1552ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    const MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj);
1562ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    if (!event) {
1572ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        LOGW("nativeAddMovement failed because MotionEvent was finalized.");
1582ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        return;
1592ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
1602ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
1612ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
1622ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    state->addMovement(event);
1632ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
1642ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
1652ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownstatic void android_view_VelocityTracker_nativeComputeCurrentVelocity(JNIEnv* env, jclass clazz,
1662ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        jint ptr, jint units, jfloat maxVelocity) {
1672ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
1682ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    state->computeCurrentVelocity(units, maxVelocity);
1692ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
1702ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
1712ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownstatic jfloat android_view_VelocityTracker_nativeGetXVelocity(JNIEnv* env, jclass clazz,
1722ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        jint ptr, jint id) {
1732ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
1742ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    float vx;
1752ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    state->getVelocity(id, &vx, NULL);
1762ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    return vx;
1772ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
1782ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
1792ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownstatic jfloat android_view_VelocityTracker_nativeGetYVelocity(JNIEnv* env, jclass clazz,
1802ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        jint ptr, jint id) {
1812ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
1822ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    float vy;
1832ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    state->getVelocity(id, NULL, &vy);
1842ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    return vy;
1852ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
1862ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
187b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brownstatic jboolean android_view_VelocityTracker_nativeGetEstimator(JNIEnv* env, jclass clazz,
188b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        jint ptr, jint id, jint degree, jint horizonMillis, jobject outEstimatorObj) {
189b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
190b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    VelocityTracker::Estimator estimator;
191b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    bool result = state->getEstimator(id,
192b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            degree < 0 ? VelocityTracker::DEFAULT_DEGREE : uint32_t(degree),
193b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            horizonMillis < 0 ? VelocityTracker::DEFAULT_HORIZON :
194b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                    nsecs_t(horizonMillis) * 1000000L,
195b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            &estimator);
196b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
197b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    jfloatArray xCoeffObj = jfloatArray(env->GetObjectField(outEstimatorObj,
198b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            gEstimatorClassInfo.xCoeff));
199b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    jfloatArray yCoeffObj = jfloatArray(env->GetObjectField(outEstimatorObj,
200b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            gEstimatorClassInfo.yCoeff));
201b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
202b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    env->SetFloatArrayRegion(xCoeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
203b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            estimator.xCoeff);
204b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    env->SetFloatArrayRegion(yCoeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
205b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            estimator.yCoeff);
206b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    env->SetIntField(outEstimatorObj, gEstimatorClassInfo.degree, estimator.degree);
207b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    env->SetFloatField(outEstimatorObj, gEstimatorClassInfo.confidence, estimator.confidence);
208b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    return result;
209b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown}
210b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
2112ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
2122ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown// --- JNI Registration ---
2132ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
2142ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownstatic JNINativeMethod gVelocityTrackerMethods[] = {
2152ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    /* name, signature, funcPtr */
2162ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    { "nativeInitialize",
2172ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            "()I",
2182ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            (void*)android_view_VelocityTracker_nativeInitialize },
2192ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    { "nativeDispose",
2202ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            "(I)V",
2212ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            (void*)android_view_VelocityTracker_nativeDispose },
2222ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    { "nativeClear",
2232ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            "(I)V",
2242ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            (void*)android_view_VelocityTracker_nativeClear },
2252ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    { "nativeAddMovement",
2262ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            "(ILandroid/view/MotionEvent;)V",
2272ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            (void*)android_view_VelocityTracker_nativeAddMovement },
2282ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    { "nativeComputeCurrentVelocity",
2292ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            "(IIF)V",
2302ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            (void*)android_view_VelocityTracker_nativeComputeCurrentVelocity },
2312ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    { "nativeGetXVelocity",
2322ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            "(II)F",
2332ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            (void*)android_view_VelocityTracker_nativeGetXVelocity },
2342ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    { "nativeGetYVelocity",
2352ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            "(II)F",
2362ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            (void*)android_view_VelocityTracker_nativeGetYVelocity },
237b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    { "nativeGetEstimator",
238b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            "(IIIILandroid/view/VelocityTracker$Estimator;)Z",
239b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            (void*)android_view_VelocityTracker_nativeGetEstimator },
2402ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown};
2412ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
242b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#define FIND_CLASS(var, className) \
243b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        var = env->FindClass(className); \
244b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        LOG_FATAL_IF(! var, "Unable to find class " className);
245b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
246b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
247b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
248b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
249b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
2502ed2462aa29c564f5231f317c27b3188da875e52Jeff Brownint register_android_view_VelocityTracker(JNIEnv* env) {
2512ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    int res = jniRegisterNativeMethods(env, "android/view/VelocityTracker",
2522ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            gVelocityTrackerMethods, NELEM(gVelocityTrackerMethods));
2532ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
254b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
255b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    jclass clazz;
256b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    FIND_CLASS(clazz, "android/view/VelocityTracker$Estimator");
257b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
258b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    GET_FIELD_ID(gEstimatorClassInfo.xCoeff, clazz,
259b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            "xCoeff", "[F");
260b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    GET_FIELD_ID(gEstimatorClassInfo.yCoeff, clazz,
261b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            "yCoeff", "[F");
262b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    GET_FIELD_ID(gEstimatorClassInfo.degree, clazz,
263b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            "degree", "I");
264b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    GET_FIELD_ID(gEstimatorClassInfo.confidence, clazz,
265b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            "confidence", "F");
2662ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    return 0;
2672ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown}
2682ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
2692ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown} // namespace android
270