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