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