Home | History | Annotate | Download | only in jni
      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 <nativehelper/JNIHelp.h>
     20 
     21 #include <android_runtime/AndroidRuntime.h>
     22 #include <utils/Log.h>
     23 #include <input/Input.h>
     24 #include <input/VelocityTracker.h>
     25 #include "android_view_MotionEvent.h"
     26 
     27 #include <nativehelper/ScopedUtfChars.h>
     28 
     29 #include "core_jni_helpers.h"
     30 
     31 namespace android {
     32 
     33 // Special constant to request the velocity of the active pointer.
     34 static const int ACTIVE_POINTER_ID = -1;
     35 
     36 static struct {
     37     jfieldID xCoeff;
     38     jfieldID yCoeff;
     39     jfieldID degree;
     40     jfieldID confidence;
     41 } gEstimatorClassInfo;
     42 
     43 
     44 // --- VelocityTrackerState ---
     45 
     46 class VelocityTrackerState {
     47 public:
     48     explicit VelocityTrackerState(const char* strategy);
     49 
     50     void clear();
     51     void addMovement(const MotionEvent* event);
     52     void computeCurrentVelocity(int32_t units, float maxVelocity);
     53     void getVelocity(int32_t id, float* outVx, float* outVy);
     54     bool getEstimator(int32_t id, VelocityTracker::Estimator* outEstimator);
     55 
     56 private:
     57     struct Velocity {
     58         float vx, vy;
     59     };
     60 
     61     VelocityTracker mVelocityTracker;
     62     int32_t mActivePointerId;
     63     BitSet32 mCalculatedIdBits;
     64     Velocity mCalculatedVelocity[MAX_POINTERS];
     65 };
     66 
     67 VelocityTrackerState::VelocityTrackerState(const char* strategy) :
     68         mVelocityTracker(strategy), mActivePointerId(-1) {
     69 }
     70 
     71 void VelocityTrackerState::clear() {
     72     mVelocityTracker.clear();
     73     mActivePointerId = -1;
     74     mCalculatedIdBits.clear();
     75 }
     76 
     77 void VelocityTrackerState::addMovement(const MotionEvent* event) {
     78     mVelocityTracker.addMovement(event);
     79 }
     80 
     81 void VelocityTrackerState::computeCurrentVelocity(int32_t units, float maxVelocity) {
     82     BitSet32 idBits(mVelocityTracker.getCurrentPointerIdBits());
     83     mCalculatedIdBits = idBits;
     84 
     85     for (uint32_t index = 0; !idBits.isEmpty(); index++) {
     86         uint32_t id = idBits.clearFirstMarkedBit();
     87 
     88         float vx, vy;
     89         mVelocityTracker.getVelocity(id, &vx, &vy);
     90 
     91         vx = vx * units / 1000;
     92         vy = vy * units / 1000;
     93 
     94         if (vx > maxVelocity) {
     95             vx = maxVelocity;
     96         } else if (vx < -maxVelocity) {
     97             vx = -maxVelocity;
     98         }
     99         if (vy > maxVelocity) {
    100             vy = maxVelocity;
    101         } else if (vy < -maxVelocity) {
    102             vy = -maxVelocity;
    103         }
    104 
    105         Velocity& velocity = mCalculatedVelocity[index];
    106         velocity.vx = vx;
    107         velocity.vy = vy;
    108     }
    109 }
    110 
    111 void VelocityTrackerState::getVelocity(int32_t id, float* outVx, float* outVy) {
    112     if (id == ACTIVE_POINTER_ID) {
    113         id = mVelocityTracker.getActivePointerId();
    114     }
    115 
    116     float vx, vy;
    117     if (id >= 0 && id <= MAX_POINTER_ID && mCalculatedIdBits.hasBit(id)) {
    118         uint32_t index = mCalculatedIdBits.getIndexOfBit(id);
    119         const Velocity& velocity = mCalculatedVelocity[index];
    120         vx = velocity.vx;
    121         vy = velocity.vy;
    122     } else {
    123         vx = 0;
    124         vy = 0;
    125     }
    126 
    127     if (outVx) {
    128         *outVx = vx;
    129     }
    130     if (outVy) {
    131         *outVy = vy;
    132     }
    133 }
    134 
    135 bool VelocityTrackerState::getEstimator(int32_t id, VelocityTracker::Estimator* outEstimator) {
    136     return mVelocityTracker.getEstimator(id, outEstimator);
    137 }
    138 
    139 
    140 // --- JNI Methods ---
    141 
    142 static jlong android_view_VelocityTracker_nativeInitialize(JNIEnv* env, jclass clazz,
    143         jstring strategyStr) {
    144     if (strategyStr) {
    145         ScopedUtfChars strategy(env, strategyStr);
    146         return reinterpret_cast<jlong>(new VelocityTrackerState(strategy.c_str()));
    147     }
    148     return reinterpret_cast<jlong>(new VelocityTrackerState(NULL));
    149 }
    150 
    151 static void android_view_VelocityTracker_nativeDispose(JNIEnv* env, jclass clazz, jlong ptr) {
    152     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
    153     delete state;
    154 }
    155 
    156 static void android_view_VelocityTracker_nativeClear(JNIEnv* env, jclass clazz, jlong ptr) {
    157     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
    158     state->clear();
    159 }
    160 
    161 static void android_view_VelocityTracker_nativeAddMovement(JNIEnv* env, jclass clazz, jlong ptr,
    162         jobject eventObj) {
    163     const MotionEvent* event = android_view_MotionEvent_getNativePtr(env, eventObj);
    164     if (!event) {
    165         ALOGW("nativeAddMovement failed because MotionEvent was finalized.");
    166         return;
    167     }
    168 
    169     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
    170     state->addMovement(event);
    171 }
    172 
    173 static void android_view_VelocityTracker_nativeComputeCurrentVelocity(JNIEnv* env, jclass clazz,
    174         jlong ptr, jint units, jfloat maxVelocity) {
    175     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
    176     state->computeCurrentVelocity(units, maxVelocity);
    177 }
    178 
    179 static jfloat android_view_VelocityTracker_nativeGetXVelocity(JNIEnv* env, jclass clazz,
    180         jlong ptr, jint id) {
    181     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
    182     float vx;
    183     state->getVelocity(id, &vx, NULL);
    184     return vx;
    185 }
    186 
    187 static jfloat android_view_VelocityTracker_nativeGetYVelocity(JNIEnv* env, jclass clazz,
    188         jlong ptr, jint id) {
    189     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
    190     float vy;
    191     state->getVelocity(id, NULL, &vy);
    192     return vy;
    193 }
    194 
    195 static jboolean android_view_VelocityTracker_nativeGetEstimator(JNIEnv* env, jclass clazz,
    196         jlong ptr, jint id, jobject outEstimatorObj) {
    197     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
    198     VelocityTracker::Estimator estimator;
    199     bool result = state->getEstimator(id, &estimator);
    200 
    201     jfloatArray xCoeffObj = jfloatArray(env->GetObjectField(outEstimatorObj,
    202             gEstimatorClassInfo.xCoeff));
    203     jfloatArray yCoeffObj = jfloatArray(env->GetObjectField(outEstimatorObj,
    204             gEstimatorClassInfo.yCoeff));
    205 
    206     env->SetFloatArrayRegion(xCoeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
    207             estimator.xCoeff);
    208     env->SetFloatArrayRegion(yCoeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
    209             estimator.yCoeff);
    210     env->SetIntField(outEstimatorObj, gEstimatorClassInfo.degree, estimator.degree);
    211     env->SetFloatField(outEstimatorObj, gEstimatorClassInfo.confidence, estimator.confidence);
    212     return result;
    213 }
    214 
    215 
    216 // --- JNI Registration ---
    217 
    218 static const JNINativeMethod gVelocityTrackerMethods[] = {
    219     /* name, signature, funcPtr */
    220     { "nativeInitialize",
    221             "(Ljava/lang/String;)J",
    222             (void*)android_view_VelocityTracker_nativeInitialize },
    223     { "nativeDispose",
    224             "(J)V",
    225             (void*)android_view_VelocityTracker_nativeDispose },
    226     { "nativeClear",
    227             "(J)V",
    228             (void*)android_view_VelocityTracker_nativeClear },
    229     { "nativeAddMovement",
    230             "(JLandroid/view/MotionEvent;)V",
    231             (void*)android_view_VelocityTracker_nativeAddMovement },
    232     { "nativeComputeCurrentVelocity",
    233             "(JIF)V",
    234             (void*)android_view_VelocityTracker_nativeComputeCurrentVelocity },
    235     { "nativeGetXVelocity",
    236             "(JI)F",
    237             (void*)android_view_VelocityTracker_nativeGetXVelocity },
    238     { "nativeGetYVelocity",
    239             "(JI)F",
    240             (void*)android_view_VelocityTracker_nativeGetYVelocity },
    241     { "nativeGetEstimator",
    242             "(JILandroid/view/VelocityTracker$Estimator;)Z",
    243             (void*)android_view_VelocityTracker_nativeGetEstimator },
    244 };
    245 
    246 int register_android_view_VelocityTracker(JNIEnv* env) {
    247     int res = RegisterMethodsOrDie(env, "android/view/VelocityTracker", gVelocityTrackerMethods,
    248                                    NELEM(gVelocityTrackerMethods));
    249 
    250     jclass clazz = FindClassOrDie(env, "android/view/VelocityTracker$Estimator");
    251 
    252     gEstimatorClassInfo.xCoeff = GetFieldIDOrDie(env, clazz, "xCoeff", "[F");
    253     gEstimatorClassInfo.yCoeff = GetFieldIDOrDie(env, clazz, "yCoeff", "[F");
    254     gEstimatorClassInfo.degree = GetFieldIDOrDie(env, clazz, "degree", "I");
    255     gEstimatorClassInfo.confidence = GetFieldIDOrDie(env, clazz, "confidence", "F");
    256 
    257     return res;
    258 }
    259 
    260 } // namespace android
    261