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