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