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