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 jmethodID dispatchFlushCompleteEvent;
35 } gBaseEventQueueClassInfo;
36
37 namespace android {
38
39 struct SensorOffsets
40 {
41 jfieldID name;
42 jfieldID vendor;
43 jfieldID version;
44 jfieldID handle;
45 jfieldID type;
46 jfieldID range;
47 jfieldID resolution;
48 jfieldID power;
49 jfieldID minDelay;
50 jfieldID fifoReservedEventCount;
51 jfieldID fifoMaxEventCount;
52 jfieldID stringType;
53 jfieldID requiredPermission;
54 jfieldID maxDelay;
55 jfieldID flags;
56 } gSensorOffsets;
57
58
59 /*
60 * The method below are not thread-safe and not intended to be
61 */
62
63 static void
nativeClassInit(JNIEnv * _env,jclass _this)64 nativeClassInit (JNIEnv *_env, jclass _this)
65 {
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");
85 }
86
87 static jint
nativeGetNextSensor(JNIEnv * env,jclass clazz,jobject sensor,jint next)88 nativeGetNextSensor(JNIEnv *env, jclass clazz, jobject sensor, jint next)
89 {
90 SensorManager& mgr(SensorManager::getInstance());
91
92 Sensor const* const* sensorList;
93 size_t count = mgr.getSensorList(&sensorList);
94 if (size_t(next) >= count)
95 return -1;
96
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,
118 requiredPermission);
119 env->SetIntField(sensor, sensorOffsets.maxDelay, list->getMaxDelay());
120 env->SetIntField(sensor, sensorOffsets.flags, list->getFlags());
121 next++;
122 return size_t(next) < count ? next : 0;
123 }
124
125 //----------------------------------------------------------------------------
126
127 class Receiver : public LooperCallback {
128 sp<SensorEventQueue> mSensorQueue;
129 sp<MessageQueue> mMessageQueue;
130 jobject mReceiverObject;
131 jfloatArray mScratch;
132 public:
Receiver(const sp<SensorEventQueue> & sensorQueue,const sp<MessageQueue> & messageQueue,jobject receiverObject,jfloatArray scratch)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);
141 }
~Receiver()142 ~Receiver() {
143 JNIEnv* env = AndroidRuntime::getJNIEnv();
144 env->DeleteGlobalRef(mReceiverObject);
145 env->DeleteGlobalRef(mScratch);
146 }
getSensorEventQueue() const147 sp<SensorEventQueue> getSensorEventQueue() const {
148 return mSensorQueue;
149 }
150
destroy()151 void destroy() {
152 mMessageQueue->getLooper()->removeFd( mSensorQueue->getFd() );
153 }
154
155 private:
onFirstRef()156 virtual void onFirstRef() {
157 LooperCallback::onFirstRef();
158 mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
159 ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
160 }
161
handleEvent(int fd,int events,void * data)162 virtual int handleEvent(int fd, int events, void* data) {
163 JNIEnv* env = AndroidRuntime::getJNIEnv();
164 sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);
165 ssize_t n;
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);
173 } else {
174 env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);
175 }
176
177 if (buffer[i].type == SENSOR_TYPE_META_DATA) {
178 // This is a flush complete sensor event. Call dispatchFlushCompleteEvent
179 // method.
180 env->CallVoidMethod(mReceiverObject,
181 gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
182 buffer[i].meta_data.sensor);
183 } else {
184 int8_t status;
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;
191 break;
192 case SENSOR_TYPE_HEART_RATE:
193 status = buffer[i].heart_rate.status;
194 break;
195 default:
196 status = SENSOR_STATUS_ACCURACY_HIGH;
197 break;
198 }
199 env->CallVoidMethod(mReceiverObject,
200 gBaseEventQueueClassInfo.dispatchSensorEvent,
201 buffer[i].sensor,
202 mScratch,
203 status,
204 buffer[i].timestamp);
205 }
206 if (env->ExceptionCheck()) {
207 mSensorQueue->sendAck(buffer, n);
208 ALOGE("Exception dispatching input event.");
209 return 1;
210 }
211 }
212 mSensorQueue->sendAck(buffer, n);
213 }
214 if (n<0 && n != -EAGAIN) {
215 // FIXME: error receiving events, what to do in this case?
216 }
217 return 1;
218 }
219 };
220
nativeInitSensorEventQueue(JNIEnv * env,jclass clazz,jobject eventQ,jobject msgQ,jfloatArray scratch)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());
224
225 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
226 if (messageQueue == NULL) {
227 jniThrowRuntimeException(env, "MessageQueue is not initialized.");
228 return 0;
229 }
230
231 sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQ, scratch);
232 receiver->incStrong((void*)nativeInitSensorEventQueue);
233 return jlong(receiver.get());
234 }
235
nativeEnableSensor(JNIEnv * env,jclass clazz,jlong eventQ,jint handle,jint rate_us,jint maxBatchReportLatency,jint reservedFlags)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,
240 reservedFlags);
241 }
242
nativeDisableSensor(JNIEnv * env,jclass clazz,jlong eventQ,jint handle)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);
246 }
247
nativeDestroySensorEventQueue(JNIEnv * env,jclass clazz,jlong eventQ,jint handle)248 static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jlong eventQ, jint handle) {
249 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
250 receiver->destroy();
251 receiver->decStrong((void*)nativeInitSensorEventQueue);
252 }
253
nativeFlushSensor(JNIEnv * env,jclass clazz,jlong eventQ)254 static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jlong eventQ) {
255 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
256 return receiver->getSensorEventQueue()->flush();
257 }
258
259 //----------------------------------------------------------------------------
260
261 static JNINativeMethod gSystemSensorManagerMethods[] = {
262 {"nativeClassInit",
263 "()V",
264 (void*)nativeClassInit },
265
266 {"nativeGetNextSensor",
267 "(Landroid/hardware/Sensor;I)I",
268 (void*)nativeGetNextSensor },
269 };
270
271 static JNINativeMethod gBaseEventQueueMethods[] = {
272 {"nativeInitBaseEventQueue",
273 "(Landroid/hardware/SystemSensorManager$BaseEventQueue;Landroid/os/MessageQueue;[F)J",
274 (void*)nativeInitSensorEventQueue },
275
276 {"nativeEnableSensor",
277 "(JIIII)I",
278 (void*)nativeEnableSensor },
279
280 {"nativeDisableSensor",
281 "(JI)I",
282 (void*)nativeDisableSensor },
283
284 {"nativeDestroySensorEventQueue",
285 "(J)V",
286 (void*)nativeDestroySensorEventQueue },
287
288 {"nativeFlushSensor",
289 "(J)I",
290 (void*)nativeFlushSensor },
291 };
292
293 }; // namespace android
294
295 using namespace android;
296
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));
301
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);
305
register_android_hardware_SensorManager(JNIEnv * env)306 int register_android_hardware_SensorManager(JNIEnv *env)
307 {
308 jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager",
309 gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
310
311 jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager$BaseEventQueue",
312 gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));
313
314 FIND_CLASS(gBaseEventQueueClassInfo.clazz, "android/hardware/SystemSensorManager$BaseEventQueue");
315
316 GET_METHOD_ID(gBaseEventQueueClassInfo.dispatchSensorEvent,
317 gBaseEventQueueClassInfo.clazz,
318 "dispatchSensorEvent", "(I[FIJ)V");
319
320 GET_METHOD_ID(gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
321 gBaseEventQueueClassInfo.clazz,
322 "dispatchFlushCompleteEvent", "(I)V");
323
324 return 0;
325 }
326