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