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 #define LOG_TAG "SensorManager"
17
18 #include "JNIHelp.h"
19 #include "android_os_MessageQueue.h"
20 #include "core_jni_helpers.h"
21 #include "jni.h"
22
23 #include <ScopedUtfChars.h>
24 #include <ScopedLocalRef.h>
25 #include <android_runtime/AndroidRuntime.h>
26 #include <gui/Sensor.h>
27 #include <gui/SensorEventQueue.h>
28 #include <gui/SensorManager.h>
29 #include <utils/Log.h>
30 #include <utils/Looper.h>
31 #include <utils/Vector.h>
32
33 #include <map>
34
35 namespace {
36
37 using namespace android;
38
39 struct {
40 jclass clazz;
41 jmethodID dispatchSensorEvent;
42 jmethodID dispatchFlushCompleteEvent;
43 jmethodID dispatchAdditionalInfoEvent;
44 } gBaseEventQueueClassInfo;
45
46 struct SensorOffsets
47 {
48 jclass clazz;
49 //fields
50 jfieldID name;
51 jfieldID vendor;
52 jfieldID version;
53 jfieldID handle;
54 jfieldID range;
55 jfieldID resolution;
56 jfieldID power;
57 jfieldID minDelay;
58 jfieldID fifoReservedEventCount;
59 jfieldID fifoMaxEventCount;
60 jfieldID stringType;
61 jfieldID requiredPermission;
62 jfieldID maxDelay;
63 jfieldID flags;
64 //methods
65 jmethodID setType;
66 jmethodID setUuid;
67 jmethodID init;
68 } gSensorOffsets;
69
70 struct ListOffsets {
71 jclass clazz;
72 jmethodID add;
73 } gListOffsets;
74
75 /*
76 * nativeClassInit is not inteneded to be thread-safe. It should be called before other native...
77 * functions (except nativeCreate).
78 */
79 static void
nativeClassInit(JNIEnv * _env,jclass _this)80 nativeClassInit (JNIEnv *_env, jclass _this)
81 {
82 //android.hardware.Sensor
83 SensorOffsets& sensorOffsets = gSensorOffsets;
84 jclass sensorClass = (jclass) _env->NewGlobalRef(_env->FindClass("android/hardware/Sensor"));
85 sensorOffsets.clazz = sensorClass;
86 sensorOffsets.name = _env->GetFieldID(sensorClass, "mName", "Ljava/lang/String;");
87 sensorOffsets.vendor = _env->GetFieldID(sensorClass, "mVendor", "Ljava/lang/String;");
88 sensorOffsets.version = _env->GetFieldID(sensorClass, "mVersion", "I");
89 sensorOffsets.handle = _env->GetFieldID(sensorClass, "mHandle", "I");
90 sensorOffsets.range = _env->GetFieldID(sensorClass, "mMaxRange", "F");
91 sensorOffsets.resolution = _env->GetFieldID(sensorClass, "mResolution","F");
92 sensorOffsets.power = _env->GetFieldID(sensorClass, "mPower", "F");
93 sensorOffsets.minDelay = _env->GetFieldID(sensorClass, "mMinDelay", "I");
94 sensorOffsets.fifoReservedEventCount =
95 _env->GetFieldID(sensorClass, "mFifoReservedEventCount", "I");
96 sensorOffsets.fifoMaxEventCount = _env->GetFieldID(sensorClass, "mFifoMaxEventCount", "I");
97 sensorOffsets.stringType = _env->GetFieldID(sensorClass, "mStringType", "Ljava/lang/String;");
98 sensorOffsets.requiredPermission = _env->GetFieldID(sensorClass, "mRequiredPermission",
99 "Ljava/lang/String;");
100 sensorOffsets.maxDelay = _env->GetFieldID(sensorClass, "mMaxDelay", "I");
101 sensorOffsets.flags = _env->GetFieldID(sensorClass, "mFlags", "I");
102
103 sensorOffsets.setType = _env->GetMethodID(sensorClass, "setType", "(I)Z");
104 sensorOffsets.setUuid = _env->GetMethodID(sensorClass, "setUuid", "(JJ)V");
105 sensorOffsets.init = _env->GetMethodID(sensorClass, "<init>", "()V");
106
107 // java.util.List;
108 ListOffsets& listOffsets = gListOffsets;
109 jclass listClass = (jclass) _env->NewGlobalRef(_env->FindClass("java/util/List"));
110 listOffsets.clazz = listClass;
111 listOffsets.add = _env->GetMethodID(listClass, "add", "(Ljava/lang/Object;)Z");
112 }
113
114 /**
115 * A key comparator predicate.
116 * It is used to intern strings associated with Sensor data.
117 * It defines a 'Strict weak ordering' for the interned strings.
118 */
119 class InternedStringCompare {
120 public:
operator ()(const String8 * string1,const String8 * string2) const121 bool operator()(const String8* string1, const String8* string2) const {
122 if (string1 == NULL) {
123 return string2 != NULL;
124 }
125 if (string2 == NULL) {
126 return false;
127 }
128 return string1->compare(*string2) < 0;
129 }
130 };
131
132 /**
133 * A localized interning mechanism for Sensor strings.
134 * We implement our own interning to avoid the overhead of using java.lang.String#intern().
135 * It is common that Vendor, StringType, and RequirePermission data is common between many of the
136 * Sensors, by interning the memory usage to represent Sensors is optimized.
137 */
138 static jstring
getInternedString(JNIEnv * env,const String8 * string)139 getInternedString(JNIEnv *env, const String8* string) {
140 static std::map<const String8*, jstring, InternedStringCompare> internedStrings;
141
142 jstring internedString;
143 std::map<const String8*, jstring>::iterator iterator = internedStrings.find(string);
144 if (iterator != internedStrings.end()) {
145 internedString = iterator->second;
146 } else {
147 jstring localString = env->NewStringUTF(string->string());
148 // we are implementing our own interning so expect these strings to be backed by global refs
149 internedString = (jstring) env->NewGlobalRef(localString);
150 internedStrings.insert(std::make_pair(string, internedString));
151 env->DeleteLocalRef(localString);
152 }
153 return internedString;
154 }
155
156 static jlong
nativeCreate(JNIEnv * env,jclass clazz,jstring opPackageName)157 nativeCreate
158 (JNIEnv *env, jclass clazz, jstring opPackageName)
159 {
160 ScopedUtfChars opPackageNameUtf(env, opPackageName);
161 return (jlong) &SensorManager::getInstanceForPackage(String16(opPackageNameUtf.c_str()));
162 }
163
164 static jobject
translateNativeSensorToJavaSensor(JNIEnv * env,jobject sensor,const Sensor & nativeSensor)165 translateNativeSensorToJavaSensor(JNIEnv *env, jobject sensor, const Sensor& nativeSensor) {
166 const SensorOffsets& sensorOffsets(gSensorOffsets);
167
168 if (sensor == NULL) {
169 // Sensor sensor = new Sensor();
170 sensor = env->NewObject(sensorOffsets.clazz, sensorOffsets.init, "");
171 }
172
173 if (sensor != NULL) {
174 jstring name = env->NewStringUTF(nativeSensor.getName().string());
175 jstring vendor = env->NewStringUTF(nativeSensor.getVendor().string());
176 jstring requiredPermission =
177 env->NewStringUTF(nativeSensor.getRequiredPermission().string());
178
179 env->SetObjectField(sensor, sensorOffsets.name, name);
180 env->SetObjectField(sensor, sensorOffsets.vendor, vendor);
181 env->SetIntField(sensor, sensorOffsets.version, nativeSensor.getVersion());
182 env->SetIntField(sensor, sensorOffsets.handle, nativeSensor.getHandle());
183 env->SetFloatField(sensor, sensorOffsets.range, nativeSensor.getMaxValue());
184 env->SetFloatField(sensor, sensorOffsets.resolution, nativeSensor.getResolution());
185 env->SetFloatField(sensor, sensorOffsets.power, nativeSensor.getPowerUsage());
186 env->SetIntField(sensor, sensorOffsets.minDelay, nativeSensor.getMinDelay());
187 env->SetIntField(sensor, sensorOffsets.fifoReservedEventCount,
188 nativeSensor.getFifoReservedEventCount());
189 env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount,
190 nativeSensor.getFifoMaxEventCount());
191 env->SetObjectField(sensor, sensorOffsets.requiredPermission,
192 requiredPermission);
193 env->SetIntField(sensor, sensorOffsets.maxDelay, nativeSensor.getMaxDelay());
194 env->SetIntField(sensor, sensorOffsets.flags, nativeSensor.getFlags());
195
196 if (env->CallBooleanMethod(sensor, sensorOffsets.setType, nativeSensor.getType())
197 == JNI_FALSE) {
198 jstring stringType = getInternedString(env, &nativeSensor.getStringType());
199 env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
200 }
201
202 // TODO(b/29547335): Rename "setUuid" method to "setId".
203 int64_t id = nativeSensor.getId();
204 env->CallVoidMethod(sensor, sensorOffsets.setUuid, id, 0);
205 }
206 return sensor;
207 }
208
209 static jboolean
nativeGetSensorAtIndex(JNIEnv * env,jclass clazz,jlong sensorManager,jobject sensor,jint index)210 nativeGetSensorAtIndex(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensor, jint index)
211 {
212 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
213
214 Sensor const* const* sensorList;
215 ssize_t count = mgr->getSensorList(&sensorList);
216 if (ssize_t(index) >= count) {
217 return false;
218 }
219
220 return translateNativeSensorToJavaSensor(env, sensor, *sensorList[index]) != NULL;
221 }
222
223 static void
nativeGetDynamicSensors(JNIEnv * env,jclass clazz,jlong sensorManager,jobject sensorList)224 nativeGetDynamicSensors(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensorList) {
225
226 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
227 const ListOffsets& listOffsets(gListOffsets);
228
229 Vector<Sensor> nativeList;
230
231 mgr->getDynamicSensorList(nativeList);
232
233 ALOGI("DYNS native SensorManager.getDynamicSensorList return %d sensors", nativeList.size());
234 for (size_t i = 0; i < nativeList.size(); ++i) {
235 jobject sensor = translateNativeSensorToJavaSensor(env, NULL, nativeList[i]);
236 // add to list
237 env->CallBooleanMethod(sensorList, listOffsets.add, sensor);
238 }
239 }
240
nativeIsDataInjectionEnabled(JNIEnv * _env,jclass _this,jlong sensorManager)241 static jboolean nativeIsDataInjectionEnabled(JNIEnv *_env, jclass _this, jlong sensorManager) {
242 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
243 return mgr->isDataInjectionEnabled();
244 }
245
246 //----------------------------------------------------------------------------
247
248 class Receiver : public LooperCallback {
249 sp<SensorEventQueue> mSensorQueue;
250 sp<MessageQueue> mMessageQueue;
251 jobject mReceiverWeakGlobal;
252 jfloatArray mFloatScratch;
253 jintArray mIntScratch;
254 public:
Receiver(const sp<SensorEventQueue> & sensorQueue,const sp<MessageQueue> & messageQueue,jobject receiverWeak)255 Receiver(const sp<SensorEventQueue>& sensorQueue,
256 const sp<MessageQueue>& messageQueue,
257 jobject receiverWeak) {
258 JNIEnv* env = AndroidRuntime::getJNIEnv();
259 mSensorQueue = sensorQueue;
260 mMessageQueue = messageQueue;
261 mReceiverWeakGlobal = env->NewGlobalRef(receiverWeak);
262
263 mIntScratch = (jintArray) env->NewGlobalRef(env->NewIntArray(16));
264 mFloatScratch = (jfloatArray) env->NewGlobalRef(env->NewFloatArray(16));
265 }
~Receiver()266 ~Receiver() {
267 JNIEnv* env = AndroidRuntime::getJNIEnv();
268 env->DeleteGlobalRef(mReceiverWeakGlobal);
269 env->DeleteGlobalRef(mFloatScratch);
270 env->DeleteGlobalRef(mIntScratch);
271 }
getSensorEventQueue() const272 sp<SensorEventQueue> getSensorEventQueue() const {
273 return mSensorQueue;
274 }
275
destroy()276 void destroy() {
277 mMessageQueue->getLooper()->removeFd( mSensorQueue->getFd() );
278 }
279
280 private:
onFirstRef()281 virtual void onFirstRef() {
282 LooperCallback::onFirstRef();
283 mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
284 ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
285 }
286
handleEvent(int fd,int events,void * data)287 virtual int handleEvent(int fd, int events, void* data) {
288 JNIEnv* env = AndroidRuntime::getJNIEnv();
289 sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);
290 ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
291
292 ssize_t n;
293 ASensorEvent buffer[16];
294 while ((n = q->read(buffer, 16)) > 0) {
295 for (int i=0 ; i<n ; i++) {
296 if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {
297 // step-counter returns a uint64, but the java API only deals with floats
298 float value = float(buffer[i].u64.step_counter);
299 env->SetFloatArrayRegion(mFloatScratch, 0, 1, &value);
300 } else if (buffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META) {
301 float value[2];
302 value[0] = buffer[i].dynamic_sensor_meta.connected ? 1.f: 0.f;
303 value[1] = float(buffer[i].dynamic_sensor_meta.handle);
304 env->SetFloatArrayRegion(mFloatScratch, 0, 2, value);
305 } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
306 env->SetIntArrayRegion(mIntScratch, 0, 14,
307 buffer[i].additional_info.data_int32);
308 env->SetFloatArrayRegion(mFloatScratch, 0, 14,
309 buffer[i].additional_info.data_float);
310 } else {
311 env->SetFloatArrayRegion(mFloatScratch, 0, 16, buffer[i].data);
312 }
313
314 if (buffer[i].type == SENSOR_TYPE_META_DATA) {
315 // This is a flush complete sensor event. Call dispatchFlushCompleteEvent
316 // method.
317 if (receiverObj.get()) {
318 env->CallVoidMethod(receiverObj.get(),
319 gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
320 buffer[i].meta_data.sensor);
321 }
322 } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
323 // This is a flush complete sensor event. Call dispatchAdditionalInfoEvent
324 // method.
325 if (receiverObj.get()) {
326 int type = buffer[i].additional_info.type;
327 int serial = buffer[i].additional_info.serial;
328 env->CallVoidMethod(receiverObj.get(),
329 gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent,
330 buffer[i].sensor,
331 type, serial,
332 mFloatScratch,
333 mIntScratch,
334 buffer[i].timestamp);
335 }
336 }else {
337 int8_t status;
338 switch (buffer[i].type) {
339 case SENSOR_TYPE_ORIENTATION:
340 case SENSOR_TYPE_MAGNETIC_FIELD:
341 case SENSOR_TYPE_ACCELEROMETER:
342 case SENSOR_TYPE_GYROSCOPE:
343 case SENSOR_TYPE_GRAVITY:
344 case SENSOR_TYPE_LINEAR_ACCELERATION:
345 status = buffer[i].vector.status;
346 break;
347 case SENSOR_TYPE_HEART_RATE:
348 status = buffer[i].heart_rate.status;
349 break;
350 default:
351 status = SENSOR_STATUS_ACCURACY_HIGH;
352 break;
353 }
354 if (receiverObj.get()) {
355 env->CallVoidMethod(receiverObj.get(),
356 gBaseEventQueueClassInfo.dispatchSensorEvent,
357 buffer[i].sensor,
358 mFloatScratch,
359 status,
360 buffer[i].timestamp);
361 }
362 }
363 if (env->ExceptionCheck()) {
364 mSensorQueue->sendAck(buffer, n);
365 ALOGE("Exception dispatching input event.");
366 return 1;
367 }
368 }
369 mSensorQueue->sendAck(buffer, n);
370 }
371 if (n<0 && n != -EAGAIN) {
372 // FIXME: error receiving events, what to do in this case?
373 }
374 return 1;
375 }
376 };
377
nativeInitSensorEventQueue(JNIEnv * env,jclass clazz,jlong sensorManager,jobject eventQWeak,jobject msgQ,jstring packageName,jint mode)378 static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
379 jobject eventQWeak, jobject msgQ, jstring packageName, jint mode) {
380 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
381 ScopedUtfChars packageUtf(env, packageName);
382 String8 clientName(packageUtf.c_str());
383 sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode));
384
385 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
386 if (messageQueue == NULL) {
387 jniThrowRuntimeException(env, "MessageQueue is not initialized.");
388 return 0;
389 }
390
391 sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak);
392 receiver->incStrong((void*)nativeInitSensorEventQueue);
393 return jlong(receiver.get());
394 }
395
nativeEnableSensor(JNIEnv * env,jclass clazz,jlong eventQ,jint handle,jint rate_us,jint maxBatchReportLatency)396 static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us,
397 jint maxBatchReportLatency) {
398 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
399 return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency,
400 0);
401 }
402
nativeDisableSensor(JNIEnv * env,jclass clazz,jlong eventQ,jint handle)403 static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle) {
404 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
405 return receiver->getSensorEventQueue()->disableSensor(handle);
406 }
407
nativeDestroySensorEventQueue(JNIEnv * env,jclass clazz,jlong eventQ)408 static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jlong eventQ) {
409 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
410 receiver->destroy();
411 receiver->decStrong((void*)nativeInitSensorEventQueue);
412 }
413
nativeFlushSensor(JNIEnv * env,jclass clazz,jlong eventQ)414 static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jlong eventQ) {
415 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
416 return receiver->getSensorEventQueue()->flush();
417 }
418
nativeInjectSensorData(JNIEnv * env,jclass clazz,jlong eventQ,jint handle,jfloatArray values,jint accuracy,jlong timestamp)419 static jint nativeInjectSensorData(JNIEnv *env, jclass clazz, jlong eventQ, jint handle,
420 jfloatArray values, jint accuracy, jlong timestamp) {
421 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
422 // Create a sensor_event from the above data which can be injected into the HAL.
423 ASensorEvent sensor_event;
424 memset(&sensor_event, 0, sizeof(sensor_event));
425 sensor_event.sensor = handle;
426 sensor_event.timestamp = timestamp;
427 env->GetFloatArrayRegion(values, 0, env->GetArrayLength(values), sensor_event.data);
428 return receiver->getSensorEventQueue()->injectSensorEvent(sensor_event);
429 }
430 //----------------------------------------------------------------------------
431
432 static const JNINativeMethod gSystemSensorManagerMethods[] = {
433 {"nativeClassInit",
434 "()V",
435 (void*)nativeClassInit },
436 {"nativeCreate",
437 "(Ljava/lang/String;)J",
438 (void*)nativeCreate },
439
440 {"nativeGetSensorAtIndex",
441 "(JLandroid/hardware/Sensor;I)Z",
442 (void*)nativeGetSensorAtIndex },
443
444 {"nativeGetDynamicSensors",
445 "(JLjava/util/List;)V",
446 (void*)nativeGetDynamicSensors },
447
448 {"nativeIsDataInjectionEnabled",
449 "(J)Z",
450 (void*)nativeIsDataInjectionEnabled},
451 };
452
453 static const JNINativeMethod gBaseEventQueueMethods[] = {
454 {"nativeInitBaseEventQueue",
455 "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;Ljava/lang/String;ILjava/lang/String;)J",
456 (void*)nativeInitSensorEventQueue },
457
458 {"nativeEnableSensor",
459 "(JIII)I",
460 (void*)nativeEnableSensor },
461
462 {"nativeDisableSensor",
463 "(JI)I",
464 (void*)nativeDisableSensor },
465
466 {"nativeDestroySensorEventQueue",
467 "(J)V",
468 (void*)nativeDestroySensorEventQueue },
469
470 {"nativeFlushSensor",
471 "(J)I",
472 (void*)nativeFlushSensor },
473
474 {"nativeInjectSensorData",
475 "(JI[FIJ)I",
476 (void*)nativeInjectSensorData },
477 };
478
479 } //unnamed namespace
480
register_android_hardware_SensorManager(JNIEnv * env)481 int register_android_hardware_SensorManager(JNIEnv *env)
482 {
483 RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager",
484 gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
485
486 RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager$BaseEventQueue",
487 gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));
488
489 gBaseEventQueueClassInfo.clazz = FindClassOrDie(env,
490 "android/hardware/SystemSensorManager$BaseEventQueue");
491
492 gBaseEventQueueClassInfo.dispatchSensorEvent = GetMethodIDOrDie(env,
493 gBaseEventQueueClassInfo.clazz, "dispatchSensorEvent", "(I[FIJ)V");
494
495 gBaseEventQueueClassInfo.dispatchFlushCompleteEvent = GetMethodIDOrDie(env,
496 gBaseEventQueueClassInfo.clazz, "dispatchFlushCompleteEvent", "(I)V");
497
498 gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent = GetMethodIDOrDie(env,
499 gBaseEventQueueClassInfo.clazz, "dispatchAdditionalInfoEvent", "(III[F[I)V");
500
501 return 0;
502 }
503