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