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