Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright 2008, 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 #define LOG_TAG "SensorManager"
     17 
     18 #include "JNIHelp.h"
     19 #include "android_os_MessageQueue.h"
     20 #include "core_jni_helpers.h"
     21 #include "jni.h"
     22 
     23 #include <ScopedUtfChars.h>
     24 #include <ScopedLocalRef.h>
     25 #include <android_runtime/AndroidRuntime.h>
     26 #include <gui/Sensor.h>
     27 #include <gui/SensorEventQueue.h>
     28 #include <gui/SensorManager.h>
     29 #include <utils/Log.h>
     30 #include <utils/Looper.h>
     31 #include <utils/Vector.h>
     32 
     33 #include <map>
     34 
     35 namespace {
     36 
     37 using namespace android;
     38 
     39 struct {
     40     jclass clazz;
     41     jmethodID dispatchSensorEvent;
     42     jmethodID dispatchFlushCompleteEvent;
     43     jmethodID dispatchAdditionalInfoEvent;
     44 } gBaseEventQueueClassInfo;
     45 
     46 struct SensorOffsets
     47 {
     48     jclass      clazz;
     49     //fields
     50     jfieldID    name;
     51     jfieldID    vendor;
     52     jfieldID    version;
     53     jfieldID    handle;
     54     jfieldID    range;
     55     jfieldID    resolution;
     56     jfieldID    power;
     57     jfieldID    minDelay;
     58     jfieldID    fifoReservedEventCount;
     59     jfieldID    fifoMaxEventCount;
     60     jfieldID    stringType;
     61     jfieldID    requiredPermission;
     62     jfieldID    maxDelay;
     63     jfieldID    flags;
     64     //methods
     65     jmethodID   setType;
     66     jmethodID   setUuid;
     67     jmethodID   init;
     68 } gSensorOffsets;
     69 
     70 struct ListOffsets {
     71     jclass      clazz;
     72     jmethodID   add;
     73 } gListOffsets;
     74 
     75 /*
     76  * nativeClassInit is not inteneded to be thread-safe. It should be called before other native...
     77  * functions (except nativeCreate).
     78  */
     79 static void
     80 nativeClassInit (JNIEnv *_env, jclass _this)
     81 {
     82     //android.hardware.Sensor
     83     SensorOffsets& sensorOffsets = gSensorOffsets;
     84     jclass sensorClass = (jclass) _env->NewGlobalRef(_env->FindClass("android/hardware/Sensor"));
     85     sensorOffsets.clazz       = sensorClass;
     86     sensorOffsets.name        = _env->GetFieldID(sensorClass, "mName",      "Ljava/lang/String;");
     87     sensorOffsets.vendor      = _env->GetFieldID(sensorClass, "mVendor",    "Ljava/lang/String;");
     88     sensorOffsets.version     = _env->GetFieldID(sensorClass, "mVersion",   "I");
     89     sensorOffsets.handle      = _env->GetFieldID(sensorClass, "mHandle",    "I");
     90     sensorOffsets.range       = _env->GetFieldID(sensorClass, "mMaxRange",  "F");
     91     sensorOffsets.resolution  = _env->GetFieldID(sensorClass, "mResolution","F");
     92     sensorOffsets.power       = _env->GetFieldID(sensorClass, "mPower",     "F");
     93     sensorOffsets.minDelay    = _env->GetFieldID(sensorClass, "mMinDelay",  "I");
     94     sensorOffsets.fifoReservedEventCount =
     95             _env->GetFieldID(sensorClass, "mFifoReservedEventCount",  "I");
     96     sensorOffsets.fifoMaxEventCount = _env->GetFieldID(sensorClass, "mFifoMaxEventCount",  "I");
     97     sensorOffsets.stringType = _env->GetFieldID(sensorClass, "mStringType", "Ljava/lang/String;");
     98     sensorOffsets.requiredPermission = _env->GetFieldID(sensorClass, "mRequiredPermission",
     99                                                         "Ljava/lang/String;");
    100     sensorOffsets.maxDelay    = _env->GetFieldID(sensorClass, "mMaxDelay",  "I");
    101     sensorOffsets.flags = _env->GetFieldID(sensorClass, "mFlags",  "I");
    102 
    103     sensorOffsets.setType = _env->GetMethodID(sensorClass, "setType", "(I)Z");
    104     sensorOffsets.setUuid = _env->GetMethodID(sensorClass, "setUuid", "(JJ)V");
    105     sensorOffsets.init = _env->GetMethodID(sensorClass, "<init>", "()V");
    106 
    107     // java.util.List;
    108     ListOffsets& listOffsets = gListOffsets;
    109     jclass listClass = (jclass) _env->NewGlobalRef(_env->FindClass("java/util/List"));
    110     listOffsets.clazz = listClass;
    111     listOffsets.add = _env->GetMethodID(listClass, "add", "(Ljava/lang/Object;)Z");
    112 }
    113 
    114 /**
    115  * A key comparator predicate.
    116  * It is used to intern strings associated with Sensor data.
    117  * It defines a 'Strict weak ordering' for the interned strings.
    118  */
    119 class InternedStringCompare {
    120 public:
    121     bool operator()(const String8* string1, const String8* string2) const {
    122         if (string1 == NULL) {
    123             return string2 != NULL;
    124         }
    125         if (string2 == NULL) {
    126             return false;
    127         }
    128         return string1->compare(*string2) < 0;
    129     }
    130 };
    131 
    132 /**
    133  * A localized interning mechanism for Sensor strings.
    134  * We implement our own interning to avoid the overhead of using java.lang.String#intern().
    135  * It is common that Vendor, StringType, and RequirePermission data is common between many of the
    136  * Sensors, by interning the memory usage to represent Sensors is optimized.
    137  */
    138 static jstring
    139 getInternedString(JNIEnv *env, const String8* string) {
    140     static std::map<const String8*, jstring, InternedStringCompare> internedStrings;
    141 
    142     jstring internedString;
    143     std::map<const String8*, jstring>::iterator iterator = internedStrings.find(string);
    144     if (iterator != internedStrings.end()) {
    145         internedString = iterator->second;
    146     } else {
    147         jstring localString = env->NewStringUTF(string->string());
    148         // we are implementing our own interning so expect these strings to be backed by global refs
    149         internedString = (jstring) env->NewGlobalRef(localString);
    150         internedStrings.insert(std::make_pair(string, internedString));
    151         env->DeleteLocalRef(localString);
    152     }
    153     return internedString;
    154 }
    155 
    156 static jlong
    157 nativeCreate
    158 (JNIEnv *env, jclass clazz, jstring opPackageName)
    159 {
    160     ScopedUtfChars opPackageNameUtf(env, opPackageName);
    161     return (jlong) &SensorManager::getInstanceForPackage(String16(opPackageNameUtf.c_str()));
    162 }
    163 
    164 static jobject
    165 translateNativeSensorToJavaSensor(JNIEnv *env, jobject sensor, const Sensor& nativeSensor) {
    166     const SensorOffsets& sensorOffsets(gSensorOffsets);
    167 
    168     if (sensor == NULL) {
    169         // Sensor sensor = new Sensor();
    170         sensor = env->NewObject(sensorOffsets.clazz, sensorOffsets.init, "");
    171     }
    172 
    173     if (sensor != NULL) {
    174         jstring name = env->NewStringUTF(nativeSensor.getName().string());
    175         jstring vendor = env->NewStringUTF(nativeSensor.getVendor().string());
    176         jstring requiredPermission =
    177                 env->NewStringUTF(nativeSensor.getRequiredPermission().string());
    178 
    179         env->SetObjectField(sensor, sensorOffsets.name,      name);
    180         env->SetObjectField(sensor, sensorOffsets.vendor,    vendor);
    181         env->SetIntField(sensor, sensorOffsets.version,      nativeSensor.getVersion());
    182         env->SetIntField(sensor, sensorOffsets.handle,       nativeSensor.getHandle());
    183         env->SetFloatField(sensor, sensorOffsets.range,      nativeSensor.getMaxValue());
    184         env->SetFloatField(sensor, sensorOffsets.resolution, nativeSensor.getResolution());
    185         env->SetFloatField(sensor, sensorOffsets.power,      nativeSensor.getPowerUsage());
    186         env->SetIntField(sensor, sensorOffsets.minDelay,     nativeSensor.getMinDelay());
    187         env->SetIntField(sensor, sensorOffsets.fifoReservedEventCount,
    188                          nativeSensor.getFifoReservedEventCount());
    189         env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount,
    190                          nativeSensor.getFifoMaxEventCount());
    191         env->SetObjectField(sensor, sensorOffsets.requiredPermission,
    192                             requiredPermission);
    193         env->SetIntField(sensor, sensorOffsets.maxDelay, nativeSensor.getMaxDelay());
    194         env->SetIntField(sensor, sensorOffsets.flags, nativeSensor.getFlags());
    195 
    196         if (env->CallBooleanMethod(sensor, sensorOffsets.setType, nativeSensor.getType())
    197                 == JNI_FALSE) {
    198             jstring stringType = getInternedString(env, &nativeSensor.getStringType());
    199             env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
    200         }
    201 
    202         // TODO(b/29547335): Rename "setUuid" method to "setId".
    203         int64_t id = nativeSensor.getId();
    204         env->CallVoidMethod(sensor, sensorOffsets.setUuid, id, 0);
    205     }
    206     return sensor;
    207 }
    208 
    209 static jboolean
    210 nativeGetSensorAtIndex(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensor, jint index)
    211 {
    212     SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
    213 
    214     Sensor const* const* sensorList;
    215     ssize_t count = mgr->getSensorList(&sensorList);
    216     if (ssize_t(index) >= count) {
    217         return false;
    218     }
    219 
    220     return translateNativeSensorToJavaSensor(env, sensor, *sensorList[index]) != NULL;
    221 }
    222 
    223 static void
    224 nativeGetDynamicSensors(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensorList) {
    225 
    226     SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
    227     const ListOffsets& listOffsets(gListOffsets);
    228 
    229     Vector<Sensor> nativeList;
    230 
    231     mgr->getDynamicSensorList(nativeList);
    232 
    233     ALOGI("DYNS native SensorManager.getDynamicSensorList return %d sensors", nativeList.size());
    234     for (size_t i = 0; i < nativeList.size(); ++i) {
    235         jobject sensor = translateNativeSensorToJavaSensor(env, NULL, nativeList[i]);
    236         // add to list
    237         env->CallBooleanMethod(sensorList, listOffsets.add, sensor);
    238     }
    239 }
    240 
    241 static jboolean nativeIsDataInjectionEnabled(JNIEnv *_env, jclass _this, jlong sensorManager) {
    242     SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
    243     return mgr->isDataInjectionEnabled();
    244 }
    245 
    246 //----------------------------------------------------------------------------
    247 
    248 class Receiver : public LooperCallback {
    249     sp<SensorEventQueue> mSensorQueue;
    250     sp<MessageQueue> mMessageQueue;
    251     jobject mReceiverWeakGlobal;
    252     jfloatArray mFloatScratch;
    253     jintArray   mIntScratch;
    254 public:
    255     Receiver(const sp<SensorEventQueue>& sensorQueue,
    256             const sp<MessageQueue>& messageQueue,
    257             jobject receiverWeak) {
    258         JNIEnv* env = AndroidRuntime::getJNIEnv();
    259         mSensorQueue = sensorQueue;
    260         mMessageQueue = messageQueue;
    261         mReceiverWeakGlobal = env->NewGlobalRef(receiverWeak);
    262 
    263         mIntScratch = (jintArray) env->NewGlobalRef(env->NewIntArray(16));
    264         mFloatScratch = (jfloatArray) env->NewGlobalRef(env->NewFloatArray(16));
    265     }
    266     ~Receiver() {
    267         JNIEnv* env = AndroidRuntime::getJNIEnv();
    268         env->DeleteGlobalRef(mReceiverWeakGlobal);
    269         env->DeleteGlobalRef(mFloatScratch);
    270         env->DeleteGlobalRef(mIntScratch);
    271     }
    272     sp<SensorEventQueue> getSensorEventQueue() const {
    273         return mSensorQueue;
    274     }
    275 
    276     void destroy() {
    277         mMessageQueue->getLooper()->removeFd( mSensorQueue->getFd() );
    278     }
    279 
    280 private:
    281     virtual void onFirstRef() {
    282         LooperCallback::onFirstRef();
    283         mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
    284                 ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
    285     }
    286 
    287     virtual int handleEvent(int fd, int events, void* data) {
    288         JNIEnv* env = AndroidRuntime::getJNIEnv();
    289         sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);
    290         ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
    291 
    292         ssize_t n;
    293         ASensorEvent buffer[16];
    294         while ((n = q->read(buffer, 16)) > 0) {
    295             for (int i=0 ; i<n ; i++) {
    296                 if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {
    297                     // step-counter returns a uint64, but the java API only deals with floats
    298                     float value = float(buffer[i].u64.step_counter);
    299                     env->SetFloatArrayRegion(mFloatScratch, 0, 1, &value);
    300                 } else if (buffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META) {
    301                     float value[2];
    302                     value[0] = buffer[i].dynamic_sensor_meta.connected ? 1.f: 0.f;
    303                     value[1] = float(buffer[i].dynamic_sensor_meta.handle);
    304                     env->SetFloatArrayRegion(mFloatScratch, 0, 2, value);
    305                 } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
    306                     env->SetIntArrayRegion(mIntScratch, 0, 14,
    307                                            buffer[i].additional_info.data_int32);
    308                     env->SetFloatArrayRegion(mFloatScratch, 0, 14,
    309                                              buffer[i].additional_info.data_float);
    310                 } else {
    311                     env->SetFloatArrayRegion(mFloatScratch, 0, 16, buffer[i].data);
    312                 }
    313 
    314                 if (buffer[i].type == SENSOR_TYPE_META_DATA) {
    315                     // This is a flush complete sensor event. Call dispatchFlushCompleteEvent
    316                     // method.
    317                     if (receiverObj.get()) {
    318                         env->CallVoidMethod(receiverObj.get(),
    319                                             gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
    320                                             buffer[i].meta_data.sensor);
    321                     }
    322                 } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
    323                     // This is a flush complete sensor event. Call dispatchAdditionalInfoEvent
    324                     // method.
    325                     if (receiverObj.get()) {
    326                         int type = buffer[i].additional_info.type;
    327                         int serial = buffer[i].additional_info.serial;
    328                         env->CallVoidMethod(receiverObj.get(),
    329                                             gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent,
    330                                             buffer[i].sensor,
    331                                             type, serial,
    332                                             mFloatScratch,
    333                                             mIntScratch,
    334                                             buffer[i].timestamp);
    335                     }
    336                 }else {
    337                     int8_t status;
    338                     switch (buffer[i].type) {
    339                     case SENSOR_TYPE_ORIENTATION:
    340                     case SENSOR_TYPE_MAGNETIC_FIELD:
    341                     case SENSOR_TYPE_ACCELEROMETER:
    342                     case SENSOR_TYPE_GYROSCOPE:
    343                     case SENSOR_TYPE_GRAVITY:
    344                     case SENSOR_TYPE_LINEAR_ACCELERATION:
    345                         status = buffer[i].vector.status;
    346                         break;
    347                     case SENSOR_TYPE_HEART_RATE:
    348                         status = buffer[i].heart_rate.status;
    349                         break;
    350                     default:
    351                         status = SENSOR_STATUS_ACCURACY_HIGH;
    352                         break;
    353                     }
    354                     if (receiverObj.get()) {
    355                         env->CallVoidMethod(receiverObj.get(),
    356                                             gBaseEventQueueClassInfo.dispatchSensorEvent,
    357                                             buffer[i].sensor,
    358                                             mFloatScratch,
    359                                             status,
    360                                             buffer[i].timestamp);
    361                     }
    362                 }
    363                 if (env->ExceptionCheck()) {
    364                     mSensorQueue->sendAck(buffer, n);
    365                     ALOGE("Exception dispatching input event.");
    366                     return 1;
    367                 }
    368             }
    369             mSensorQueue->sendAck(buffer, n);
    370         }
    371         if (n<0 && n != -EAGAIN) {
    372             // FIXME: error receiving events, what to do in this case?
    373         }
    374         return 1;
    375     }
    376 };
    377 
    378 static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
    379         jobject eventQWeak, jobject msgQ, jstring packageName, jint mode) {
    380     SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
    381     ScopedUtfChars packageUtf(env, packageName);
    382     String8 clientName(packageUtf.c_str());
    383     sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode));
    384 
    385     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
    386     if (messageQueue == NULL) {
    387         jniThrowRuntimeException(env, "MessageQueue is not initialized.");
    388         return 0;
    389     }
    390 
    391     sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak);
    392     receiver->incStrong((void*)nativeInitSensorEventQueue);
    393     return jlong(receiver.get());
    394 }
    395 
    396 static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us,
    397                                jint maxBatchReportLatency) {
    398     sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
    399     return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency,
    400                                                          0);
    401 }
    402 
    403 static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle) {
    404     sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
    405     return receiver->getSensorEventQueue()->disableSensor(handle);
    406 }
    407 
    408 static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jlong eventQ) {
    409     sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
    410     receiver->destroy();
    411     receiver->decStrong((void*)nativeInitSensorEventQueue);
    412 }
    413 
    414 static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jlong eventQ) {
    415     sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
    416     return receiver->getSensorEventQueue()->flush();
    417 }
    418 
    419 static jint nativeInjectSensorData(JNIEnv *env, jclass clazz, jlong eventQ, jint handle,
    420         jfloatArray values, jint accuracy, jlong timestamp) {
    421     sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
    422     // Create a sensor_event from the above data which can be injected into the HAL.
    423     ASensorEvent sensor_event;
    424     memset(&sensor_event, 0, sizeof(sensor_event));
    425     sensor_event.sensor = handle;
    426     sensor_event.timestamp = timestamp;
    427     env->GetFloatArrayRegion(values, 0, env->GetArrayLength(values), sensor_event.data);
    428     return receiver->getSensorEventQueue()->injectSensorEvent(sensor_event);
    429 }
    430 //----------------------------------------------------------------------------
    431 
    432 static const JNINativeMethod gSystemSensorManagerMethods[] = {
    433     {"nativeClassInit",
    434             "()V",
    435             (void*)nativeClassInit },
    436     {"nativeCreate",
    437              "(Ljava/lang/String;)J",
    438              (void*)nativeCreate },
    439 
    440     {"nativeGetSensorAtIndex",
    441             "(JLandroid/hardware/Sensor;I)Z",
    442             (void*)nativeGetSensorAtIndex },
    443 
    444     {"nativeGetDynamicSensors",
    445             "(JLjava/util/List;)V",
    446             (void*)nativeGetDynamicSensors },
    447 
    448     {"nativeIsDataInjectionEnabled",
    449             "(J)Z",
    450             (void*)nativeIsDataInjectionEnabled},
    451 };
    452 
    453 static const JNINativeMethod gBaseEventQueueMethods[] = {
    454     {"nativeInitBaseEventQueue",
    455              "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;Ljava/lang/String;ILjava/lang/String;)J",
    456              (void*)nativeInitSensorEventQueue },
    457 
    458     {"nativeEnableSensor",
    459             "(JIII)I",
    460             (void*)nativeEnableSensor },
    461 
    462     {"nativeDisableSensor",
    463             "(JI)I",
    464             (void*)nativeDisableSensor },
    465 
    466     {"nativeDestroySensorEventQueue",
    467             "(J)V",
    468             (void*)nativeDestroySensorEventQueue },
    469 
    470     {"nativeFlushSensor",
    471             "(J)I",
    472             (void*)nativeFlushSensor },
    473 
    474     {"nativeInjectSensorData",
    475             "(JI[FIJ)I",
    476             (void*)nativeInjectSensorData },
    477 };
    478 
    479 } //unnamed namespace
    480 
    481 int register_android_hardware_SensorManager(JNIEnv *env)
    482 {
    483     RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager",
    484             gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
    485 
    486     RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager$BaseEventQueue",
    487             gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));
    488 
    489     gBaseEventQueueClassInfo.clazz = FindClassOrDie(env,
    490             "android/hardware/SystemSensorManager$BaseEventQueue");
    491 
    492     gBaseEventQueueClassInfo.dispatchSensorEvent = GetMethodIDOrDie(env,
    493             gBaseEventQueueClassInfo.clazz, "dispatchSensorEvent", "(I[FIJ)V");
    494 
    495     gBaseEventQueueClassInfo.dispatchFlushCompleteEvent = GetMethodIDOrDie(env,
    496             gBaseEventQueueClassInfo.clazz, "dispatchFlushCompleteEvent", "(I)V");
    497 
    498     gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent = GetMethodIDOrDie(env,
    499             gBaseEventQueueClassInfo.clazz, "dispatchAdditionalInfoEvent", "(III[F[I)V");
    500 
    501     return 0;
    502 }
    503