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