android_hardware_SensorManager.cpp revision ef0b88181e30252d07901976a81524fc8bb03066
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 <utils/Log.h> 20#include <utils/Looper.h> 21 22#include <gui/Sensor.h> 23#include <gui/SensorManager.h> 24#include <gui/SensorEventQueue.h> 25 26#include "jni.h" 27#include "JNIHelp.h" 28#include "android_os_MessageQueue.h" 29#include <android_runtime/AndroidRuntime.h> 30 31static struct { 32 jclass clazz; 33 jmethodID dispatchSensorEvent; 34 jmethodID dispatchFlushCompleteEvent; 35} gBaseEventQueueClassInfo; 36 37namespace android { 38 39struct SensorOffsets 40{ 41 jfieldID name; 42 jfieldID vendor; 43 jfieldID version; 44 jfieldID handle; 45 jfieldID type; 46 jfieldID range; 47 jfieldID resolution; 48 jfieldID power; 49 jfieldID minDelay; 50 jfieldID fifoReservedEventCount; 51 jfieldID fifoMaxEventCount; 52 jfieldID stringType; 53 jfieldID requiredPermission; 54} gSensorOffsets; 55 56 57/* 58 * The method below are not thread-safe and not intended to be 59 */ 60 61static void 62nativeClassInit (JNIEnv *_env, jclass _this) 63{ 64 jclass sensorClass = _env->FindClass("android/hardware/Sensor"); 65 SensorOffsets& sensorOffsets = gSensorOffsets; 66 sensorOffsets.name = _env->GetFieldID(sensorClass, "mName", "Ljava/lang/String;"); 67 sensorOffsets.vendor = _env->GetFieldID(sensorClass, "mVendor", "Ljava/lang/String;"); 68 sensorOffsets.version = _env->GetFieldID(sensorClass, "mVersion", "I"); 69 sensorOffsets.handle = _env->GetFieldID(sensorClass, "mHandle", "I"); 70 sensorOffsets.type = _env->GetFieldID(sensorClass, "mType", "I"); 71 sensorOffsets.range = _env->GetFieldID(sensorClass, "mMaxRange", "F"); 72 sensorOffsets.resolution = _env->GetFieldID(sensorClass, "mResolution","F"); 73 sensorOffsets.power = _env->GetFieldID(sensorClass, "mPower", "F"); 74 sensorOffsets.minDelay = _env->GetFieldID(sensorClass, "mMinDelay", "I"); 75 sensorOffsets.fifoReservedEventCount = 76 _env->GetFieldID(sensorClass, "mFifoReservedEventCount", "I"); 77 sensorOffsets.fifoMaxEventCount = _env->GetFieldID(sensorClass, "mFifoMaxEventCount", "I"); 78 sensorOffsets.stringType = _env->GetFieldID(sensorClass, "mStringType", "Ljava/lang/String;"); 79 sensorOffsets.requiredPermission = _env->GetFieldID(sensorClass, "mRequiredPermission", 80 "Ljava/lang/String;"); 81} 82 83static jint 84nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next) 85{ 86 SensorManager& mgr(SensorManager::getInstance()); 87 88 Sensor const* const* sensorList; 89 size_t count = mgr.getSensorList(&sensorList); 90 if (size_t(next) >= count) 91 return -1; 92 93 Sensor const* const list = sensorList[next]; 94 const SensorOffsets& sensorOffsets(gSensorOffsets); 95 jstring name = env->NewStringUTF(list->getName().string()); 96 jstring vendor = env->NewStringUTF(list->getVendor().string()); 97 jstring stringType = env->NewStringUTF(list->getStringType().string()); 98 jstring requiredPermission = env->NewStringUTF(list->getRequiredPermission().string()); 99 env->SetObjectField(sensor, sensorOffsets.name, name); 100 env->SetObjectField(sensor, sensorOffsets.vendor, vendor); 101 env->SetIntField(sensor, sensorOffsets.version, list->getVersion()); 102 env->SetIntField(sensor, sensorOffsets.handle, list->getHandle()); 103 env->SetIntField(sensor, sensorOffsets.type, list->getType()); 104 env->SetFloatField(sensor, sensorOffsets.range, list->getMaxValue()); 105 env->SetFloatField(sensor, sensorOffsets.resolution, list->getResolution()); 106 env->SetFloatField(sensor, sensorOffsets.power, list->getPowerUsage()); 107 env->SetIntField(sensor, sensorOffsets.minDelay, list->getMinDelay()); 108 env->SetIntField(sensor, sensorOffsets.fifoReservedEventCount, 109 list->getFifoReservedEventCount()); 110 env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount, 111 list->getFifoMaxEventCount()); 112 env->SetObjectField(sensor, sensorOffsets.stringType, stringType); 113 env->SetObjectField(sensor, sensorOffsets.requiredPermission, 114 requiredPermission); 115 next++; 116 return size_t(next) < count ? next : 0; 117} 118 119//---------------------------------------------------------------------------- 120 121class Receiver : public LooperCallback { 122 sp<SensorEventQueue> mSensorQueue; 123 sp<MessageQueue> mMessageQueue; 124 jobject mReceiverObject; 125 jfloatArray mScratch; 126public: 127 Receiver(const sp<SensorEventQueue>& sensorQueue, 128 const sp<MessageQueue>& messageQueue, 129 jobject receiverObject, jfloatArray scratch) { 130 JNIEnv* env = AndroidRuntime::getJNIEnv(); 131 mSensorQueue = sensorQueue; 132 mMessageQueue = messageQueue; 133 mReceiverObject = env->NewGlobalRef(receiverObject); 134 mScratch = (jfloatArray)env->NewGlobalRef(scratch); 135 } 136 ~Receiver() { 137 JNIEnv* env = AndroidRuntime::getJNIEnv(); 138 env->DeleteGlobalRef(mReceiverObject); 139 env->DeleteGlobalRef(mScratch); 140 } 141 sp<SensorEventQueue> getSensorEventQueue() const { 142 return mSensorQueue; 143 } 144 145 void destroy() { 146 mMessageQueue->getLooper()->removeFd( mSensorQueue->getFd() ); 147 } 148 149private: 150 virtual void onFirstRef() { 151 LooperCallback::onFirstRef(); 152 mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0, 153 ALOOPER_EVENT_INPUT, this, mSensorQueue.get()); 154 } 155 156 virtual int handleEvent(int fd, int events, void* data) { 157 JNIEnv* env = AndroidRuntime::getJNIEnv(); 158 sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data); 159 ssize_t n; 160 ASensorEvent buffer[16]; 161 while ((n = q->read(buffer, 16)) > 0) { 162 for (int i=0 ; i<n ; i++) { 163 if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) { 164 // step-counter returns a uint64, but the java API only deals with floats 165 float value = float(buffer[i].u64.step_counter); 166 env->SetFloatArrayRegion(mScratch, 0, 1, &value); 167 } else { 168 env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data); 169 } 170 171 if (buffer[i].type == SENSOR_TYPE_META_DATA) { 172 // This is a flush complete sensor event. Call dispatchFlushCompleteEvent 173 // method. 174 env->CallVoidMethod(mReceiverObject, 175 gBaseEventQueueClassInfo.dispatchFlushCompleteEvent, 176 buffer[i].meta_data.sensor); 177 } else { 178 int8_t status; 179 switch (buffer[i].type) { 180 case SENSOR_TYPE_ORIENTATION: 181 case SENSOR_TYPE_MAGNETIC_FIELD: 182 case SENSOR_TYPE_ACCELEROMETER: 183 case SENSOR_TYPE_GYROSCOPE: 184 status = buffer[i].vector.status; 185 break; 186 case SENSOR_TYPE_HEART_RATE: 187 status = buffer[i].heart_rate.status; 188 break; 189 default: 190 status = SENSOR_STATUS_ACCURACY_HIGH; 191 break; 192 } 193 env->CallVoidMethod(mReceiverObject, 194 gBaseEventQueueClassInfo.dispatchSensorEvent, 195 buffer[i].sensor, 196 mScratch, 197 status, 198 buffer[i].timestamp); 199 } 200 if (env->ExceptionCheck()) { 201 mSensorQueue->sendAck(buffer, n); 202 ALOGE("Exception dispatching input event."); 203 return 1; 204 } 205 } 206 mSensorQueue->sendAck(buffer, n); 207 } 208 if (n<0 && n != -EAGAIN) { 209 // FIXME: error receiving events, what to do in this case? 210 } 211 return 1; 212 } 213}; 214 215static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQ, jobject msgQ, jfloatArray scratch) { 216 SensorManager& mgr(SensorManager::getInstance()); 217 sp<SensorEventQueue> queue(mgr.createEventQueue()); 218 219 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ); 220 if (messageQueue == NULL) { 221 jniThrowRuntimeException(env, "MessageQueue is not initialized."); 222 return 0; 223 } 224 225 sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQ, scratch); 226 receiver->incStrong((void*)nativeInitSensorEventQueue); 227 return jlong(receiver.get()); 228} 229 230static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us, 231 jint maxBatchReportLatency, jint reservedFlags) { 232 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ)); 233 return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency, 234 reservedFlags); 235} 236 237static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle) { 238 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ)); 239 return receiver->getSensorEventQueue()->disableSensor(handle); 240} 241 242static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jlong eventQ, jint handle) { 243 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ)); 244 receiver->destroy(); 245 receiver->decStrong((void*)nativeInitSensorEventQueue); 246} 247 248static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jlong eventQ) { 249 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ)); 250 return receiver->getSensorEventQueue()->flush(); 251} 252 253//---------------------------------------------------------------------------- 254 255static JNINativeMethod gSystemSensorManagerMethods[] = { 256 {"nativeClassInit", 257 "()V", 258 (void*)nativeClassInit }, 259 260 {"nativeGetNextSensor", 261 "(Landroid/hardware/Sensor;I)I", 262 (void*)nativeGetNextSensor }, 263}; 264 265static JNINativeMethod gBaseEventQueueMethods[] = { 266 {"nativeInitBaseEventQueue", 267 "(Landroid/hardware/SystemSensorManager$BaseEventQueue;Landroid/os/MessageQueue;[F)J", 268 (void*)nativeInitSensorEventQueue }, 269 270 {"nativeEnableSensor", 271 "(JIIII)I", 272 (void*)nativeEnableSensor }, 273 274 {"nativeDisableSensor", 275 "(JI)I", 276 (void*)nativeDisableSensor }, 277 278 {"nativeDestroySensorEventQueue", 279 "(J)V", 280 (void*)nativeDestroySensorEventQueue }, 281 282 {"nativeFlushSensor", 283 "(J)I", 284 (void*)nativeFlushSensor }, 285}; 286 287}; // namespace android 288 289using namespace android; 290 291#define FIND_CLASS(var, className) \ 292 var = env->FindClass(className); \ 293 LOG_FATAL_IF(! var, "Unable to find class " className); \ 294 var = jclass(env->NewGlobalRef(var)); 295 296#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ 297 var = env->GetMethodID(clazz, methodName, methodDescriptor); \ 298 LOG_FATAL_IF(! var, "Unable to find method " methodName); 299 300int register_android_hardware_SensorManager(JNIEnv *env) 301{ 302 jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager", 303 gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods)); 304 305 jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager$BaseEventQueue", 306 gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods)); 307 308 FIND_CLASS(gBaseEventQueueClassInfo.clazz, "android/hardware/SystemSensorManager$BaseEventQueue"); 309 310 GET_METHOD_ID(gBaseEventQueueClassInfo.dispatchSensorEvent, 311 gBaseEventQueueClassInfo.clazz, 312 "dispatchSensorEvent", "(I[FIJ)V"); 313 314 GET_METHOD_ID(gBaseEventQueueClassInfo.dispatchFlushCompleteEvent, 315 gBaseEventQueueClassInfo.clazz, 316 "dispatchFlushCompleteEvent", "(I)V"); 317 318 return 0; 319} 320