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