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 <nativehelper/JNIHelp.h>
19 #include "android_os_MessageQueue.h"
20 #include "core_jni_helpers.h"
21 #include "jni.h"
22
23 #include <nativehelper/ScopedUtfChars.h>
24 #include <nativehelper/ScopedLocalRef.h>
25 #include <android_runtime/AndroidRuntime.h>
26 #include <android_runtime/android_hardware_HardwareBuffer.h>
27 #include <vndk/hardware_buffer.h>
28 #include <sensor/Sensor.h>
29 #include <sensor/SensorEventQueue.h>
30 #include <sensor/SensorManager.h>
31 #include <cutils/native_handle.h>
32 #include <utils/Log.h>
33 #include <utils/Looper.h>
34 #include <utils/Vector.h>
35
36 #include <map>
37
38 namespace {
39
40 using namespace android;
41
42 struct {
43 jclass clazz;
44 jmethodID dispatchSensorEvent;
45 jmethodID dispatchFlushCompleteEvent;
46 jmethodID dispatchAdditionalInfoEvent;
47 } gBaseEventQueueClassInfo;
48
49 struct SensorOffsets
50 {
51 jclass clazz;
52 //fields
53 jfieldID name;
54 jfieldID vendor;
55 jfieldID version;
56 jfieldID handle;
57 jfieldID range;
58 jfieldID resolution;
59 jfieldID power;
60 jfieldID minDelay;
61 jfieldID fifoReservedEventCount;
62 jfieldID fifoMaxEventCount;
63 jfieldID stringType;
64 jfieldID requiredPermission;
65 jfieldID maxDelay;
66 jfieldID flags;
67 //methods
68 jmethodID setType;
69 jmethodID setId;
70 jmethodID setUuid;
71 jmethodID init;
72 } gSensorOffsets;
73
74 struct ListOffsets {
75 jclass clazz;
76 jmethodID add;
77 } gListOffsets;
78
79 struct StringOffsets {
80 jclass clazz;
81 jmethodID intern;
82 jstring emptyString;
83 } gStringOffsets;
84
85 /*
86 * nativeClassInit is not inteneded to be thread-safe. It should be called before other native...
87 * functions (except nativeCreate).
88 */
89 static void
nativeClassInit(JNIEnv * _env,jclass _this)90 nativeClassInit (JNIEnv *_env, jclass _this)
91 {
92 //android.hardware.Sensor
93 SensorOffsets& sensorOffsets = gSensorOffsets;
94 jclass sensorClass = (jclass)
95 MakeGlobalRefOrDie(_env, FindClassOrDie(_env, "android/hardware/Sensor"));
96 sensorOffsets.clazz = sensorClass;
97 sensorOffsets.name = GetFieldIDOrDie(_env, sensorClass, "mName", "Ljava/lang/String;");
98 sensorOffsets.vendor = GetFieldIDOrDie(_env, sensorClass, "mVendor", "Ljava/lang/String;");
99 sensorOffsets.version = GetFieldIDOrDie(_env, sensorClass, "mVersion", "I");
100 sensorOffsets.handle = GetFieldIDOrDie(_env, sensorClass, "mHandle", "I");
101 sensorOffsets.range = GetFieldIDOrDie(_env, sensorClass, "mMaxRange", "F");
102 sensorOffsets.resolution = GetFieldIDOrDie(_env, sensorClass, "mResolution","F");
103 sensorOffsets.power = GetFieldIDOrDie(_env, sensorClass, "mPower", "F");
104 sensorOffsets.minDelay = GetFieldIDOrDie(_env, sensorClass, "mMinDelay", "I");
105 sensorOffsets.fifoReservedEventCount =
106 GetFieldIDOrDie(_env,sensorClass, "mFifoReservedEventCount", "I");
107 sensorOffsets.fifoMaxEventCount = GetFieldIDOrDie(_env,sensorClass, "mFifoMaxEventCount", "I");
108 sensorOffsets.stringType =
109 GetFieldIDOrDie(_env,sensorClass, "mStringType", "Ljava/lang/String;");
110 sensorOffsets.requiredPermission =
111 GetFieldIDOrDie(_env,sensorClass, "mRequiredPermission", "Ljava/lang/String;");
112 sensorOffsets.maxDelay = GetFieldIDOrDie(_env,sensorClass, "mMaxDelay", "I");
113 sensorOffsets.flags = GetFieldIDOrDie(_env,sensorClass, "mFlags", "I");
114
115 sensorOffsets.setType = GetMethodIDOrDie(_env,sensorClass, "setType", "(I)Z");
116 sensorOffsets.setId = GetMethodIDOrDie(_env,sensorClass, "setId", "(I)V");
117 sensorOffsets.setUuid = GetMethodIDOrDie(_env,sensorClass, "setUuid", "(JJ)V");
118 sensorOffsets.init = GetMethodIDOrDie(_env,sensorClass, "<init>", "()V");
119
120 // java.util.List;
121 ListOffsets& listOffsets = gListOffsets;
122 jclass listClass = (jclass) MakeGlobalRefOrDie(_env, FindClassOrDie(_env, "java/util/List"));
123 listOffsets.clazz = listClass;
124 listOffsets.add = GetMethodIDOrDie(_env,listClass, "add", "(Ljava/lang/Object;)Z");
125
126 // initialize java.lang.String and empty string intern
127 StringOffsets& stringOffsets = gStringOffsets;
128 stringOffsets.clazz = MakeGlobalRefOrDie(_env, FindClassOrDie(_env, "java/lang/String"));
129 stringOffsets.intern =
130 GetMethodIDOrDie(_env, stringOffsets.clazz, "intern", "()Ljava/lang/String;");
131 ScopedLocalRef<jstring> empty(_env, _env->NewStringUTF(""));
132 stringOffsets.emptyString = (jstring)
133 MakeGlobalRefOrDie(_env, _env->CallObjectMethod(empty.get(), stringOffsets.intern));
134 }
135
htonll(uint64_t ll)136 uint64_t htonll(uint64_t ll) {
137 constexpr uint32_t kBytesToTest = 0x12345678;
138 constexpr uint8_t kFirstByte = (const uint8_t &)kBytesToTest;
139 constexpr bool kIsLittleEndian = kFirstByte == 0x78;
140
141 if constexpr (kIsLittleEndian) {
142 return static_cast<uint64_t>(htonl(ll & 0xffffffff)) << 32 | htonl(ll >> 32);
143 } else {
144 return ll;
145 }
146 }
147
getJavaInternedString(JNIEnv * env,const String8 & string)148 static jstring getJavaInternedString(JNIEnv *env, const String8 &string) {
149 if (string == "") {
150 return gStringOffsets.emptyString;
151 }
152
153 ScopedLocalRef<jstring> javaString(env, env->NewStringUTF(string.string()));
154 jstring internedString = (jstring)
155 env->CallObjectMethod(javaString.get(), gStringOffsets.intern);
156 return internedString;
157 }
158
159 static jlong
nativeCreate(JNIEnv * env,jclass clazz,jstring opPackageName)160 nativeCreate
161 (JNIEnv *env, jclass clazz, jstring opPackageName)
162 {
163 ScopedUtfChars opPackageNameUtf(env, opPackageName);
164 return (jlong) &SensorManager::getInstanceForPackage(String16(opPackageNameUtf.c_str()));
165 }
166
167 static jobject
translateNativeSensorToJavaSensor(JNIEnv * env,jobject sensor,const Sensor & nativeSensor)168 translateNativeSensorToJavaSensor(JNIEnv *env, jobject sensor, const Sensor& nativeSensor) {
169 const SensorOffsets& sensorOffsets(gSensorOffsets);
170
171 if (sensor == NULL) {
172 // Sensor sensor = new Sensor();
173 sensor = env->NewObject(sensorOffsets.clazz, sensorOffsets.init, "");
174 }
175
176 if (sensor != NULL) {
177 jstring name = getJavaInternedString(env, nativeSensor.getName());
178 jstring vendor = getJavaInternedString(env, nativeSensor.getVendor());
179 jstring requiredPermission =
180 getJavaInternedString(env, nativeSensor.getRequiredPermission());
181
182 env->SetObjectField(sensor, sensorOffsets.name, name);
183 env->SetObjectField(sensor, sensorOffsets.vendor, vendor);
184 env->SetIntField(sensor, sensorOffsets.version, nativeSensor.getVersion());
185 env->SetIntField(sensor, sensorOffsets.handle, nativeSensor.getHandle());
186 env->SetFloatField(sensor, sensorOffsets.range, nativeSensor.getMaxValue());
187 env->SetFloatField(sensor, sensorOffsets.resolution, nativeSensor.getResolution());
188 env->SetFloatField(sensor, sensorOffsets.power, nativeSensor.getPowerUsage());
189 env->SetIntField(sensor, sensorOffsets.minDelay, nativeSensor.getMinDelay());
190 env->SetIntField(sensor, sensorOffsets.fifoReservedEventCount,
191 nativeSensor.getFifoReservedEventCount());
192 env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount,
193 nativeSensor.getFifoMaxEventCount());
194 env->SetObjectField(sensor, sensorOffsets.requiredPermission,
195 requiredPermission);
196 env->SetIntField(sensor, sensorOffsets.maxDelay, nativeSensor.getMaxDelay());
197 env->SetIntField(sensor, sensorOffsets.flags, nativeSensor.getFlags());
198
199 if (env->CallBooleanMethod(sensor, sensorOffsets.setType, nativeSensor.getType())
200 == JNI_FALSE) {
201 jstring stringType = getJavaInternedString(env, nativeSensor.getStringType());
202 env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
203 }
204
205 int32_t id = nativeSensor.getId();
206 env->CallVoidMethod(sensor, sensorOffsets.setId, id);
207 Sensor::uuid_t uuid = nativeSensor.getUuid();
208 env->CallVoidMethod(sensor, sensorOffsets.setUuid, htonll(uuid.i64[0]),
209 htonll(uuid.i64[1]));
210 }
211 return sensor;
212 }
213
214 static jboolean
nativeGetSensorAtIndex(JNIEnv * env,jclass clazz,jlong sensorManager,jobject sensor,jint index)215 nativeGetSensorAtIndex(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensor, jint index)
216 {
217 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
218
219 Sensor const* const* sensorList;
220 ssize_t count = mgr->getSensorList(&sensorList);
221 if (ssize_t(index) >= count) {
222 return false;
223 }
224
225 return translateNativeSensorToJavaSensor(env, sensor, *sensorList[index]) != NULL;
226 }
227
228 static void
nativeGetDynamicSensors(JNIEnv * env,jclass clazz,jlong sensorManager,jobject sensorList)229 nativeGetDynamicSensors(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensorList) {
230
231 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
232 const ListOffsets& listOffsets(gListOffsets);
233
234 Vector<Sensor> nativeList;
235
236 mgr->getDynamicSensorList(nativeList);
237
238 ALOGI("DYNS native SensorManager.getDynamicSensorList return %zu sensors", nativeList.size());
239 for (size_t i = 0; i < nativeList.size(); ++i) {
240 jobject sensor = translateNativeSensorToJavaSensor(env, NULL, nativeList[i]);
241 // add to list
242 env->CallBooleanMethod(sensorList, listOffsets.add, sensor);
243 }
244 }
245
nativeIsDataInjectionEnabled(JNIEnv * _env,jclass _this,jlong sensorManager)246 static jboolean nativeIsDataInjectionEnabled(JNIEnv *_env, jclass _this, jlong sensorManager) {
247 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
248 return mgr->isDataInjectionEnabled();
249 }
250
nativeCreateDirectChannel(JNIEnv * _env,jclass _this,jlong sensorManager,jlong size,jint channelType,jint fd,jobject hardwareBufferObj)251 static jint nativeCreateDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
252 jlong size, jint channelType, jint fd, jobject hardwareBufferObj) {
253 const native_handle_t *nativeHandle = nullptr;
254 NATIVE_HANDLE_DECLARE_STORAGE(ashmemHandle, 1, 0);
255
256 if (channelType == SENSOR_DIRECT_MEM_TYPE_ASHMEM) {
257 native_handle_t *handle = native_handle_init(ashmemHandle, 1, 0);
258 handle->data[0] = fd;
259 nativeHandle = handle;
260 } else if (channelType == SENSOR_DIRECT_MEM_TYPE_GRALLOC) {
261 AHardwareBuffer *hardwareBuffer =
262 android_hardware_HardwareBuffer_getNativeHardwareBuffer(_env, hardwareBufferObj);
263 if (hardwareBuffer != nullptr) {
264 nativeHandle = AHardwareBuffer_getNativeHandle(hardwareBuffer);
265 }
266 }
267
268 if (nativeHandle == nullptr) {
269 return BAD_VALUE;
270 }
271
272 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
273 return mgr->createDirectChannel(size, channelType, nativeHandle);
274 }
275
nativeDestroyDirectChannel(JNIEnv * _env,jclass _this,jlong sensorManager,jint channelHandle)276 static void nativeDestroyDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
277 jint channelHandle) {
278 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
279 mgr->destroyDirectChannel(channelHandle);
280 }
281
nativeConfigDirectChannel(JNIEnv * _env,jclass _this,jlong sensorManager,jint channelHandle,jint sensorHandle,jint rate)282 static jint nativeConfigDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
283 jint channelHandle, jint sensorHandle, jint rate) {
284 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
285 return mgr->configureDirectChannel(channelHandle, sensorHandle, rate);
286 }
287
nativeSetOperationParameter(JNIEnv * _env,jclass _this,jlong sensorManager,jint handle,jint type,jfloatArray floats,jintArray ints)288 static jint nativeSetOperationParameter(JNIEnv *_env, jclass _this, jlong sensorManager,
289 jint handle, jint type, jfloatArray floats, jintArray ints) {
290 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
291 Vector<float> floatVector;
292 Vector<int32_t> int32Vector;
293
294 if (floats != nullptr) {
295 floatVector.resize(_env->GetArrayLength(floats));
296 _env->GetFloatArrayRegion(floats, 0, _env->GetArrayLength(floats), floatVector.editArray());
297 }
298
299 if (ints != nullptr) {
300 int32Vector.resize(_env->GetArrayLength(ints));
301 _env->GetIntArrayRegion(ints, 0, _env->GetArrayLength(ints), int32Vector.editArray());
302 }
303
304 return mgr->setOperationParameter(handle, type, floatVector, int32Vector);
305 }
306
307 //----------------------------------------------------------------------------
308
309 class Receiver : public LooperCallback {
310 sp<SensorEventQueue> mSensorQueue;
311 sp<MessageQueue> mMessageQueue;
312 jobject mReceiverWeakGlobal;
313 jfloatArray mFloatScratch;
314 jintArray mIntScratch;
315 public:
Receiver(const sp<SensorEventQueue> & sensorQueue,const sp<MessageQueue> & messageQueue,jobject receiverWeak)316 Receiver(const sp<SensorEventQueue>& sensorQueue,
317 const sp<MessageQueue>& messageQueue,
318 jobject receiverWeak) {
319 JNIEnv* env = AndroidRuntime::getJNIEnv();
320 mSensorQueue = sensorQueue;
321 mMessageQueue = messageQueue;
322 mReceiverWeakGlobal = env->NewGlobalRef(receiverWeak);
323
324 mIntScratch = (jintArray) env->NewGlobalRef(env->NewIntArray(16));
325 mFloatScratch = (jfloatArray) env->NewGlobalRef(env->NewFloatArray(16));
326 }
~Receiver()327 ~Receiver() {
328 JNIEnv* env = AndroidRuntime::getJNIEnv();
329 env->DeleteGlobalRef(mReceiverWeakGlobal);
330 env->DeleteGlobalRef(mFloatScratch);
331 env->DeleteGlobalRef(mIntScratch);
332 }
getSensorEventQueue() const333 sp<SensorEventQueue> getSensorEventQueue() const {
334 return mSensorQueue;
335 }
336
destroy()337 void destroy() {
338 mMessageQueue->getLooper()->removeFd( mSensorQueue->getFd() );
339 }
340
341 private:
onFirstRef()342 virtual void onFirstRef() {
343 LooperCallback::onFirstRef();
344 mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
345 ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
346 }
347
handleEvent(int fd,int events,void * data)348 virtual int handleEvent(int fd, int events, void* data) {
349 JNIEnv* env = AndroidRuntime::getJNIEnv();
350 sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);
351 ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
352
353 ssize_t n;
354 ASensorEvent buffer[16];
355 while ((n = q->read(buffer, 16)) > 0) {
356 for (int i=0 ; i<n ; i++) {
357 if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {
358 // step-counter returns a uint64, but the java API only deals with floats
359 float value = float(buffer[i].u64.step_counter);
360 env->SetFloatArrayRegion(mFloatScratch, 0, 1, &value);
361 } else if (buffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META) {
362 float value[2];
363 value[0] = buffer[i].dynamic_sensor_meta.connected ? 1.f: 0.f;
364 value[1] = float(buffer[i].dynamic_sensor_meta.handle);
365 env->SetFloatArrayRegion(mFloatScratch, 0, 2, value);
366 } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
367 env->SetIntArrayRegion(mIntScratch, 0, 14,
368 buffer[i].additional_info.data_int32);
369 env->SetFloatArrayRegion(mFloatScratch, 0, 14,
370 buffer[i].additional_info.data_float);
371 } else {
372 env->SetFloatArrayRegion(mFloatScratch, 0, 16, buffer[i].data);
373 }
374
375 if (buffer[i].type == SENSOR_TYPE_META_DATA) {
376 // This is a flush complete sensor event. Call dispatchFlushCompleteEvent
377 // method.
378 if (receiverObj.get()) {
379 env->CallVoidMethod(receiverObj.get(),
380 gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
381 buffer[i].meta_data.sensor);
382 }
383 } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
384 // This is a flush complete sensor event. Call dispatchAdditionalInfoEvent
385 // method.
386 if (receiverObj.get()) {
387 int type = buffer[i].additional_info.type;
388 int serial = buffer[i].additional_info.serial;
389 env->CallVoidMethod(receiverObj.get(),
390 gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent,
391 buffer[i].sensor,
392 type, serial,
393 mFloatScratch,
394 mIntScratch,
395 buffer[i].timestamp);
396 }
397 }else {
398 int8_t status;
399 switch (buffer[i].type) {
400 case SENSOR_TYPE_ORIENTATION:
401 case SENSOR_TYPE_MAGNETIC_FIELD:
402 case SENSOR_TYPE_ACCELEROMETER:
403 case SENSOR_TYPE_GYROSCOPE:
404 case SENSOR_TYPE_GRAVITY:
405 case SENSOR_TYPE_LINEAR_ACCELERATION:
406 status = buffer[i].vector.status;
407 break;
408 case SENSOR_TYPE_HEART_RATE:
409 status = buffer[i].heart_rate.status;
410 break;
411 default:
412 status = SENSOR_STATUS_ACCURACY_HIGH;
413 break;
414 }
415 if (receiverObj.get()) {
416 env->CallVoidMethod(receiverObj.get(),
417 gBaseEventQueueClassInfo.dispatchSensorEvent,
418 buffer[i].sensor,
419 mFloatScratch,
420 status,
421 buffer[i].timestamp);
422 }
423 }
424 if (env->ExceptionCheck()) {
425 mSensorQueue->sendAck(buffer, n);
426 ALOGE("Exception dispatching input event.");
427 return 1;
428 }
429 }
430 mSensorQueue->sendAck(buffer, n);
431 }
432 if (n<0 && n != -EAGAIN) {
433 // FIXME: error receiving events, what to do in this case?
434 }
435 return 1;
436 }
437 };
438
nativeInitSensorEventQueue(JNIEnv * env,jclass clazz,jlong sensorManager,jobject eventQWeak,jobject msgQ,jstring packageName,jint mode,jstring opPackageName,jstring attributionTag)439 static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
440 jobject eventQWeak, jobject msgQ, jstring packageName,
441 jint mode, jstring opPackageName, jstring attributionTag) {
442 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
443 ScopedUtfChars packageUtf(env, packageName);
444 String8 clientName(packageUtf.c_str());
445
446 String16 attributionTagName("");
447 if (attributionTag != nullptr) {
448 ScopedUtfChars attrUtf(env, attributionTag);
449 attributionTagName = String16(attrUtf.c_str());
450 }
451 sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode, attributionTagName));
452
453 if (queue == NULL) {
454 jniThrowRuntimeException(env, "Cannot construct native SensorEventQueue.");
455 return 0;
456 }
457
458 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
459 if (messageQueue == NULL) {
460 jniThrowRuntimeException(env, "MessageQueue is not initialized.");
461 return 0;
462 }
463
464 sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak);
465 receiver->incStrong((void*)nativeInitSensorEventQueue);
466 return jlong(receiver.get());
467 }
468
nativeEnableSensor(JNIEnv * env,jclass clazz,jlong eventQ,jint handle,jint rate_us,jint maxBatchReportLatency)469 static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us,
470 jint maxBatchReportLatency) {
471 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
472 return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency,
473 0);
474 }
475
nativeDisableSensor(JNIEnv * env,jclass clazz,jlong eventQ,jint handle)476 static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle) {
477 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
478 return receiver->getSensorEventQueue()->disableSensor(handle);
479 }
480
nativeDestroySensorEventQueue(JNIEnv * env,jclass clazz,jlong eventQ)481 static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jlong eventQ) {
482 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
483 receiver->destroy();
484 receiver->decStrong((void*)nativeInitSensorEventQueue);
485 }
486
nativeFlushSensor(JNIEnv * env,jclass clazz,jlong eventQ)487 static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jlong eventQ) {
488 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
489 return receiver->getSensorEventQueue()->flush();
490 }
491
nativeInjectSensorData(JNIEnv * env,jclass clazz,jlong eventQ,jint handle,jfloatArray values,jint accuracy,jlong timestamp)492 static jint nativeInjectSensorData(JNIEnv *env, jclass clazz, jlong eventQ, jint handle,
493 jfloatArray values, jint accuracy, jlong timestamp) {
494 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
495 // Create a sensor_event from the above data which can be injected into the HAL.
496 ASensorEvent sensor_event;
497 memset(&sensor_event, 0, sizeof(sensor_event));
498 sensor_event.sensor = handle;
499 sensor_event.timestamp = timestamp;
500 env->GetFloatArrayRegion(values, 0, env->GetArrayLength(values), sensor_event.data);
501 return receiver->getSensorEventQueue()->injectSensorEvent(sensor_event);
502 }
503 //----------------------------------------------------------------------------
504
505 static const JNINativeMethod gSystemSensorManagerMethods[] = {
506 {"nativeClassInit",
507 "()V",
508 (void*)nativeClassInit },
509 {"nativeCreate",
510 "(Ljava/lang/String;)J",
511 (void*)nativeCreate },
512
513 {"nativeGetSensorAtIndex",
514 "(JLandroid/hardware/Sensor;I)Z",
515 (void*)nativeGetSensorAtIndex },
516
517 {"nativeGetDynamicSensors",
518 "(JLjava/util/List;)V",
519 (void*)nativeGetDynamicSensors },
520
521 {"nativeIsDataInjectionEnabled",
522 "(J)Z",
523 (void*)nativeIsDataInjectionEnabled },
524
525 {"nativeCreateDirectChannel",
526 "(JJIILandroid/hardware/HardwareBuffer;)I",
527 (void*)nativeCreateDirectChannel },
528
529 {"nativeDestroyDirectChannel",
530 "(JI)V",
531 (void*)nativeDestroyDirectChannel },
532
533 {"nativeConfigDirectChannel",
534 "(JIII)I",
535 (void*)nativeConfigDirectChannel },
536
537 {"nativeSetOperationParameter",
538 "(JII[F[I)I",
539 (void*)nativeSetOperationParameter },
540 };
541
542 static const JNINativeMethod gBaseEventQueueMethods[] = {
543 {"nativeInitBaseEventQueue",
544 "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;Ljava/lang/String;ILjava/lang/"
545 "String;Ljava/lang/String;)J",
546 (void *)nativeInitSensorEventQueue},
547
548 {"nativeEnableSensor", "(JIII)I", (void *)nativeEnableSensor},
549
550 {"nativeDisableSensor", "(JI)I", (void *)nativeDisableSensor},
551
552 {"nativeDestroySensorEventQueue", "(J)V", (void *)nativeDestroySensorEventQueue},
553
554 {"nativeFlushSensor", "(J)I", (void *)nativeFlushSensor},
555
556 {"nativeInjectSensorData", "(JI[FIJ)I", (void *)nativeInjectSensorData},
557 };
558
559 } //unnamed namespace
560
register_android_hardware_SensorManager(JNIEnv * env)561 int register_android_hardware_SensorManager(JNIEnv *env)
562 {
563 RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager",
564 gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
565
566 RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager$BaseEventQueue",
567 gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));
568
569 gBaseEventQueueClassInfo.clazz = FindClassOrDie(env,
570 "android/hardware/SystemSensorManager$BaseEventQueue");
571
572 gBaseEventQueueClassInfo.dispatchSensorEvent = GetMethodIDOrDie(env,
573 gBaseEventQueueClassInfo.clazz, "dispatchSensorEvent", "(I[FIJ)V");
574
575 gBaseEventQueueClassInfo.dispatchFlushCompleteEvent = GetMethodIDOrDie(env,
576 gBaseEventQueueClassInfo.clazz, "dispatchFlushCompleteEvent", "(I)V");
577
578 gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent = GetMethodIDOrDie(env,
579 gBaseEventQueueClassInfo.clazz, "dispatchAdditionalInfoEvent", "(III[F[I)V");
580
581 return 0;
582 }
583