2 * Copyright 2008, The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #define LOG_TAG "SensorManager"
19 #include <utils/Log.h>
20 #include <utils/Looper.h>
22 #include <gui/Sensor.h>
23 #include <gui/SensorManager.h>
24 #include <gui/SensorEventQueue.h>
28 #include "android_os_MessageQueue.h"
29 #include <android_runtime/AndroidRuntime.h>
33 jmethodID dispatchSensorEvent;
34 jmethodID dispatchFlushCompleteEvent;
35 } gBaseEventQueueClassInfo;
50 jfieldID fifoReservedEventCount;
51 jfieldID fifoMaxEventCount;
53 jfieldID requiredPermission;
60 * The method below are not thread-safe and not intended to be
64 nativeClassInit (JNIEnv *_env, jclass _this)
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");
88 nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next)
90 SensorManager& mgr(SensorManager::getInstance());
92 Sensor const* const* sensorList;
93 size_t count = mgr.getSensorList(&sensorList);
94 if (size_t(next) >= count)
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,
119 env->SetIntField(sensor, sensorOffsets.maxDelay, list->getMaxDelay());
120 env->SetIntField(sensor, sensorOffsets.flags, list->getFlags());
122 return size_t(next) < count ? next : 0;
125 //----------------------------------------------------------------------------
127 class Receiver : public LooperCallback {
128 sp<SensorEventQueue> mSensorQueue;
129 sp<MessageQueue> mMessageQueue;
130 jobject mReceiverObject;
131 jfloatArray mScratch;
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);
143 JNIEnv* env = AndroidRuntime::getJNIEnv();
144 env->DeleteGlobalRef(mReceiverObject);
145 env->DeleteGlobalRef(mScratch);
147 sp<SensorEventQueue> getSensorEventQueue() const {
152 mMessageQueue->getLooper()->removeFd( mSensorQueue->getFd() );
156 virtual void onFirstRef() {
157 LooperCallback::onFirstRef();
158 mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
159 ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
162 virtual int handleEvent(int fd, int events, void* data) {
163 JNIEnv* env = AndroidRuntime::getJNIEnv();
164 sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);
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);
174 env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);
177 if (buffer[i].type == SENSOR_TYPE_META_DATA) {
178 // This is a flush complete sensor event. Call dispatchFlushCompleteEvent
180 env->CallVoidMethod(mReceiverObject,
181 gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
182 buffer[i].meta_data.sensor);
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;
192 case SENSOR_TYPE_HEART_RATE:
193 status = buffer[i].heart_rate.status;
196 status = SENSOR_STATUS_ACCURACY_HIGH;
199 env->CallVoidMethod(mReceiverObject,
200 gBaseEventQueueClassInfo.dispatchSensorEvent,
204 buffer[i].timestamp);
206 if (env->ExceptionCheck()) {
207 mSensorQueue->sendAck(buffer, n);
208 ALOGE("Exception dispatching input event.");
212 mSensorQueue->sendAck(buffer, n);
214 if (n<0 && n != -EAGAIN) {
215 // FIXME: error receiving events, what to do in this case?
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());
225 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
226 if (messageQueue == NULL) {
227 jniThrowRuntimeException(env, "MessageQueue is not initialized.");
231 sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQ, scratch);
232 receiver->incStrong((void*)nativeInitSensorEventQueue);
233 return jlong(receiver.get());
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,
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);
248 static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jlong eventQ, jint handle) {
249 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
251 receiver->decStrong((void*)nativeInitSensorEventQueue);
254 static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jlong eventQ) {
255 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
256 return receiver->getSensorEventQueue()->flush();
259 //----------------------------------------------------------------------------
261 static JNINativeMethod gSystemSensorManagerMethods[] = {
264 (void*)nativeClassInit },
266 {"nativeGetNextSensor",
267 "(Landroid/hardware/Sensor;I)I",
268 (void*)nativeGetNextSensor },
271 static JNINativeMethod gBaseEventQueueMethods[] = {
272 {"nativeInitBaseEventQueue",
273 "(Landroid/hardware/SystemSensorManager$BaseEventQueue;Landroid/os/MessageQueue;[F)J",
274 (void*)nativeInitSensorEventQueue },
276 {"nativeEnableSensor",
278 (void*)nativeEnableSensor },
280 {"nativeDisableSensor",
282 (void*)nativeDisableSensor },
284 {"nativeDestroySensorEventQueue",
286 (void*)nativeDestroySensorEventQueue },
288 {"nativeFlushSensor",
290 (void*)nativeFlushSensor },
293 }; // namespace android
295 using namespace android;
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));
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);
306 int register_android_hardware_SensorManager(JNIEnv *env)
308 jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager",
309 gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
311 jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager$BaseEventQueue",
312 gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));
314 FIND_CLASS(gBaseEventQueueClassInfo.clazz, "android/hardware/SystemSensorManager$BaseEventQueue");
316 GET_METHOD_ID(gBaseEventQueueClassInfo.dispatchSensorEvent,
317 gBaseEventQueueClassInfo.clazz,
318 "dispatchSensorEvent", "(I[FIJ)V");
320 GET_METHOD_ID(gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
321 gBaseEventQueueClassInfo.clazz,
322 "dispatchFlushCompleteEvent", "(I)V");