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 } gBaseEventQueueClassInfo; 35 36 namespace android { 37 38 struct 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 56 static void 57 nativeClassInit (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 72 static jint 73 nativeGetNextSensor(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 102 class Receiver : public LooperCallback { 103 sp<SensorEventQueue> mSensorQueue; 104 sp<MessageQueue> mMessageQueue; 105 jobject mReceiverObject; 106 jfloatArray mScratch; 107 public: 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 130 private: 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 gBaseEventQueueClassInfo.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 168 static 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 183 static 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 188 static 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 193 static 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 202 static JNINativeMethod gSystemSensorManagerMethods[] = { 203 {"nativeClassInit", 204 "()V", 205 (void*)nativeClassInit }, 206 207 {"nativeGetNextSensor", 208 "(Landroid/hardware/Sensor;I)I", 209 (void*)nativeGetNextSensor }, 210 }; 211 212 static JNINativeMethod gBaseEventQueueMethods[] = { 213 {"nativeInitBaseEventQueue", 214 "(Landroid/hardware/SystemSensorManager$BaseEventQueue;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 232 using 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 243 int register_android_hardware_SensorManager(JNIEnv *env) 244 { 245 jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager", 246 gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods)); 247 248 jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager$BaseEventQueue", 249 gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods)); 250 251 FIND_CLASS(gBaseEventQueueClassInfo.clazz, "android/hardware/SystemSensorManager$BaseEventQueue"); 252 253 GET_METHOD_ID(gBaseEventQueueClassInfo.dispatchSensorEvent, 254 gBaseEventQueueClassInfo.clazz, 255 "dispatchSensorEvent", "(I[FIJ)V"); 256 257 return 0; 258 } 259