android_hardware_SensorManager.cpp revision 270e87f71abc2edf446dbec20c725c823e8c7f37
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#define LOG_NDEBUG 0
20#include "utils/Log.h"
21
22#include <hardware/sensors.h>
23#include <cutils/native_handle.h>
24
25#include "jni.h"
26#include "JNIHelp.h"
27
28
29namespace android {
30
31struct SensorOffsets
32{
33    jfieldID    name;
34    jfieldID    vendor;
35    jfieldID    version;
36    jfieldID    handle;
37    jfieldID    type;
38    jfieldID    range;
39    jfieldID    resolution;
40    jfieldID    power;
41} gSensorOffsets;
42
43/*
44 * The method below are not thread-safe and not intended to be
45 */
46
47static sensors_module_t* sSensorModule = 0;
48static sensors_data_device_t* sSensorDevice = 0;
49
50static jint
51sensors_module_init(JNIEnv *env, jclass clazz)
52{
53    int err = 0;
54    sensors_module_t const* module;
55    err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t **)&module);
56    if (err == 0)
57        sSensorModule = (sensors_module_t*)module;
58    return err;
59}
60
61static jint
62sensors_module_get_next_sensor(JNIEnv *env, jobject clazz, jobject sensor, jint next)
63{
64    if (sSensorModule == NULL)
65        return 0;
66
67    SensorOffsets& sensorOffsets = gSensorOffsets;
68    const struct sensor_t* list;
69    int count = sSensorModule->get_sensors_list(sSensorModule, &list);
70    if (next >= count)
71        return -1;
72
73    list += next;
74
75    jstring name = env->NewStringUTF(list->name);
76    jstring vendor = env->NewStringUTF(list->vendor);
77    env->SetObjectField(sensor, sensorOffsets.name,      name);
78    env->SetObjectField(sensor, sensorOffsets.vendor,    vendor);
79    env->SetIntField(sensor, sensorOffsets.version,      list->version);
80    env->SetIntField(sensor, sensorOffsets.handle,       list->handle);
81    env->SetIntField(sensor, sensorOffsets.type,         list->type);
82    env->SetFloatField(sensor, sensorOffsets.range,      list->maxRange);
83    env->SetFloatField(sensor, sensorOffsets.resolution, list->resolution);
84    env->SetFloatField(sensor, sensorOffsets.power,      list->power);
85
86    next++;
87    return next<count ? next : 0;
88}
89
90//----------------------------------------------------------------------------
91static jint
92sensors_data_init(JNIEnv *env, jclass clazz)
93{
94    if (sSensorModule == NULL)
95        return -1;
96    int err = sensors_data_open(&sSensorModule->common, &sSensorDevice);
97    return err;
98}
99
100static jint
101sensors_data_uninit(JNIEnv *env, jclass clazz)
102{
103    int err = 0;
104    if (sSensorDevice) {
105        err = sensors_data_close(sSensorDevice);
106        if (err == 0)
107            sSensorDevice = 0;
108    }
109    return err;
110}
111
112static jint
113sensors_data_open(JNIEnv *env, jclass clazz, jobjectArray fdArray, jintArray intArray)
114{
115    jclass FileDescriptor = env->FindClass("java/io/FileDescriptor");
116    jfieldID fieldOffset = env->GetFieldID(FileDescriptor, "descriptor", "I");
117    int numFds = (fdArray ? env->GetArrayLength(fdArray) : 0);
118    int numInts = (intArray ? env->GetArrayLength(intArray) : 0);
119    native_handle_t* handle = native_handle_create(numFds, numInts);
120    int offset = 0;
121
122    for (int i = 0; i < numFds; i++) {
123        jobject fdo = env->GetObjectArrayElement(fdArray, i);
124        if (fdo) {
125            handle->data[offset++] = env->GetIntField(fdo, fieldOffset);
126        } else {
127            handle->data[offset++] = -1;
128        }
129    }
130    if (numInts > 0) {
131        jint* ints = env->GetIntArrayElements(intArray, 0);
132        for (int i = 0; i < numInts; i++) {
133            handle->data[offset++] = ints[i];
134        }
135        env->ReleaseIntArrayElements(intArray, ints, 0);
136    }
137
138    // doesn't take ownership of the native handle
139    return sSensorDevice->data_open(sSensorDevice, handle);
140}
141
142static jint
143sensors_data_close(JNIEnv *env, jclass clazz)
144{
145    return sSensorDevice->data_close(sSensorDevice);
146}
147
148static jint
149sensors_data_poll(JNIEnv *env, jclass clazz,
150        jfloatArray values, jintArray status, jlongArray timestamp)
151{
152    sensors_data_t data;
153    int res = sSensorDevice->poll(sSensorDevice, &data);
154    if (res >= 0) {
155        jint accuracy = data.vector.status;
156        env->SetFloatArrayRegion(values, 0, 3, data.vector.v);
157        env->SetIntArrayRegion(status, 0, 1, &accuracy);
158        env->SetLongArrayRegion(timestamp, 0, 1, &data.time);
159    }
160    return res;
161}
162
163static void
164nativeClassInit (JNIEnv *_env, jclass _this)
165{
166    jclass sensorClass = _env->FindClass("android/hardware/Sensor");
167    SensorOffsets& sensorOffsets = gSensorOffsets;
168    sensorOffsets.name        = _env->GetFieldID(sensorClass, "mName",      "Ljava/lang/String;");
169    sensorOffsets.vendor      = _env->GetFieldID(sensorClass, "mVendor",    "Ljava/lang/String;");
170    sensorOffsets.version     = _env->GetFieldID(sensorClass, "mVersion",   "I");
171    sensorOffsets.handle      = _env->GetFieldID(sensorClass, "mHandle",    "I");
172    sensorOffsets.type        = _env->GetFieldID(sensorClass, "mType",      "I");
173    sensorOffsets.range       = _env->GetFieldID(sensorClass, "mMaxRange",  "F");
174    sensorOffsets.resolution  = _env->GetFieldID(sensorClass, "mResolution","F");
175    sensorOffsets.power       = _env->GetFieldID(sensorClass, "mPower",     "F");
176}
177
178static JNINativeMethod gMethods[] = {
179    {"nativeClassInit", "()V",              (void*)nativeClassInit },
180    {"sensors_module_init","()I",           (void*)sensors_module_init },
181    {"sensors_module_get_next_sensor","(Landroid/hardware/Sensor;I)I",
182                                            (void*)sensors_module_get_next_sensor },
183    {"sensors_data_init", "()I",            (void*)sensors_data_init },
184    {"sensors_data_uninit", "()I",          (void*)sensors_data_uninit },
185    {"sensors_data_open",  "([Ljava/io/FileDescriptor;[I)I",  (void*)sensors_data_open },
186    {"sensors_data_close", "()I",           (void*)sensors_data_close },
187    {"sensors_data_poll",  "([F[I[J)I",     (void*)sensors_data_poll },
188};
189
190}; // namespace android
191
192using namespace android;
193
194int register_android_hardware_SensorManager(JNIEnv *env)
195{
196    return jniRegisterNativeMethods(env, "android/hardware/SensorManager",
197            gMethods, NELEM(gMethods));
198}
199