android_hardware_SensorManager.cpp revision 80ba0a6baec17d5ac5a1e6f9e4b84f7d013d07e6
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} gBaseEventQueueClassInfo; 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 if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) { 146 // step-counter returns a uint64, but the java API only deals with floats 147 float value = float(buffer[i].u64.step_counter); 148 env->SetFloatArrayRegion(mScratch, 0, 1, &value); 149 } else { 150 env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data); 151 } 152 153 env->CallVoidMethod(mReceiverObject, 154 gBaseEventQueueClassInfo.dispatchSensorEvent, 155 buffer[i].sensor, 156 mScratch, 157 buffer[i].vector.status, 158 buffer[i].timestamp); 159 160 if (env->ExceptionCheck()) { 161 ALOGE("Exception dispatching input event."); 162 return 1; 163 } 164 } 165 } 166 if (n<0 && n != -EAGAIN) { 167 // FIXME: error receiving events, what to do in this case? 168 } 169 170 return 1; 171 } 172}; 173 174static jint nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jobject eventQ, jobject msgQ, jfloatArray scratch) { 175 SensorManager& mgr(SensorManager::getInstance()); 176 sp<SensorEventQueue> queue(mgr.createEventQueue()); 177 178 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ); 179 if (messageQueue == NULL) { 180 jniThrowRuntimeException(env, "MessageQueue is not initialized."); 181 return 0; 182 } 183 184 sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQ, scratch); 185 receiver->incStrong((void*)nativeInitSensorEventQueue); 186 return jint(receiver.get()); 187} 188 189static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jint eventQ, jint handle, jint us) { 190 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ)); 191 return receiver->getSensorEventQueue()->enableSensor(handle, us); 192} 193 194static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jint eventQ, jint handle) { 195 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ)); 196 return receiver->getSensorEventQueue()->disableSensor(handle); 197} 198 199static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jint eventQ, jint handle) { 200 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ)); 201 receiver->destroy(); 202 receiver->decStrong((void*)nativeInitSensorEventQueue); 203} 204 205 206//---------------------------------------------------------------------------- 207 208static JNINativeMethod gSystemSensorManagerMethods[] = { 209 {"nativeClassInit", 210 "()V", 211 (void*)nativeClassInit }, 212 213 {"nativeGetNextSensor", 214 "(Landroid/hardware/Sensor;I)I", 215 (void*)nativeGetNextSensor }, 216}; 217 218static JNINativeMethod gBaseEventQueueMethods[] = { 219 {"nativeInitBaseEventQueue", 220 "(Landroid/hardware/SystemSensorManager$BaseEventQueue;Landroid/os/MessageQueue;[F)I", 221 (void*)nativeInitSensorEventQueue }, 222 223 {"nativeEnableSensor", 224 "(III)I", 225 (void*)nativeEnableSensor }, 226 227 {"nativeDisableSensor", 228 "(II)I", 229 (void*)nativeDisableSensor }, 230 231 {"nativeDestroySensorEventQueue", 232 "(I)V", 233 (void*)nativeDestroySensorEventQueue }, 234}; 235 236}; // namespace android 237 238using namespace android; 239 240#define FIND_CLASS(var, className) \ 241 var = env->FindClass(className); \ 242 LOG_FATAL_IF(! var, "Unable to find class " className); \ 243 var = jclass(env->NewGlobalRef(var)); 244 245#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ 246 var = env->GetMethodID(clazz, methodName, methodDescriptor); \ 247 LOG_FATAL_IF(! var, "Unable to find method " methodName); 248 249int register_android_hardware_SensorManager(JNIEnv *env) 250{ 251 jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager", 252 gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods)); 253 254 jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager$BaseEventQueue", 255 gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods)); 256 257 FIND_CLASS(gBaseEventQueueClassInfo.clazz, "android/hardware/SystemSensorManager$BaseEventQueue"); 258 259 GET_METHOD_ID(gBaseEventQueueClassInfo.dispatchSensorEvent, 260 gBaseEventQueueClassInfo.clazz, 261 "dispatchSensorEvent", "(I[FIJ)V"); 262 263 return 0; 264} 265