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
nativeGetRuntimeSensors(JNIEnv * env,jclass clazz,jlong sensorManager,jint deviceId,jobject sensorList)246 static void nativeGetRuntimeSensors(JNIEnv *env, jclass clazz, jlong sensorManager, jint deviceId,
247 jobject sensorList) {
248 SensorManager *mgr = reinterpret_cast<SensorManager *>(sensorManager);
249 const ListOffsets &listOffsets(gListOffsets);
250
251 Vector<Sensor> nativeList;
252
253 mgr->getRuntimeSensorList(deviceId, nativeList);
254
255 ALOGI("DYNS native SensorManager.getRuntimeSensorList return %zu sensors", nativeList.size());
256 for (size_t i = 0; i < nativeList.size(); ++i) {
257 jobject sensor = translateNativeSensorToJavaSensor(env, NULL, nativeList[i]);
258 // add to list
259 env->CallBooleanMethod(sensorList, listOffsets.add, sensor);
260 }
261 }
262
nativeIsDataInjectionEnabled(JNIEnv * _env,jclass _this,jlong sensorManager)263 static jboolean nativeIsDataInjectionEnabled(JNIEnv *_env, jclass _this, jlong sensorManager) {
264 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
265 return mgr->isDataInjectionEnabled();
266 }
267
nativeCreateDirectChannel(JNIEnv * _env,jclass _this,jlong sensorManager,jint deviceId,jlong size,jint channelType,jint fd,jobject hardwareBufferObj)268 static jint nativeCreateDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
269 jint deviceId, jlong size, jint channelType, jint fd,
270 jobject hardwareBufferObj) {
271 const native_handle_t *nativeHandle = nullptr;
272 NATIVE_HANDLE_DECLARE_STORAGE(ashmemHandle, 1, 0);
273
274 if (channelType == SENSOR_DIRECT_MEM_TYPE_ASHMEM) {
275 native_handle_t *handle = native_handle_init(ashmemHandle, 1, 0);
276 handle->data[0] = fd;
277 nativeHandle = handle;
278 } else if (channelType == SENSOR_DIRECT_MEM_TYPE_GRALLOC) {
279 AHardwareBuffer *hardwareBuffer =
280 android_hardware_HardwareBuffer_getNativeHardwareBuffer(_env, hardwareBufferObj);
281 if (hardwareBuffer != nullptr) {
282 nativeHandle = AHardwareBuffer_getNativeHandle(hardwareBuffer);
283 }
284 }
285
286 if (nativeHandle == nullptr) {
287 return BAD_VALUE;
288 }
289
290 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
291 return mgr->createDirectChannel(deviceId, size, channelType, nativeHandle);
292 }
293
nativeDestroyDirectChannel(JNIEnv * _env,jclass _this,jlong sensorManager,jint channelHandle)294 static void nativeDestroyDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
295 jint channelHandle) {
296 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
297 mgr->destroyDirectChannel(channelHandle);
298 }
299
nativeConfigDirectChannel(JNIEnv * _env,jclass _this,jlong sensorManager,jint channelHandle,jint sensorHandle,jint rate)300 static jint nativeConfigDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
301 jint channelHandle, jint sensorHandle, jint rate) {
302 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
303 return mgr->configureDirectChannel(channelHandle, sensorHandle, rate);
304 }
305
nativeSetOperationParameter(JNIEnv * _env,jclass _this,jlong sensorManager,jint handle,jint type,jfloatArray floats,jintArray ints)306 static jint nativeSetOperationParameter(JNIEnv *_env, jclass _this, jlong sensorManager,
307 jint handle, jint type, jfloatArray floats, jintArray ints) {
308 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
309 Vector<float> floatVector;
310 Vector<int32_t> int32Vector;
311
312 if (floats != nullptr) {
313 floatVector.resize(_env->GetArrayLength(floats));
314 _env->GetFloatArrayRegion(floats, 0, _env->GetArrayLength(floats), floatVector.editArray());
315 }
316
317 if (ints != nullptr) {
318 int32Vector.resize(_env->GetArrayLength(ints));
319 _env->GetIntArrayRegion(ints, 0, _env->GetArrayLength(ints), int32Vector.editArray());
320 }
321
322 return mgr->setOperationParameter(handle, type, floatVector, int32Vector);
323 }
324
325 //----------------------------------------------------------------------------
326
327 class Receiver : public LooperCallback {
328 sp<SensorEventQueue> mSensorQueue;
329 sp<MessageQueue> mMessageQueue;
330 jobject mReceiverWeakGlobal;
331 jfloatArray mFloatScratch;
332 jintArray mIntScratch;
333 public:
Receiver(const sp<SensorEventQueue> & sensorQueue,const sp<MessageQueue> & messageQueue,jobject receiverWeak)334 Receiver(const sp<SensorEventQueue>& sensorQueue,
335 const sp<MessageQueue>& messageQueue,
336 jobject receiverWeak) {
337 JNIEnv* env = AndroidRuntime::getJNIEnv();
338 mSensorQueue = sensorQueue;
339 mMessageQueue = messageQueue;
340 mReceiverWeakGlobal = env->NewGlobalRef(receiverWeak);
341
342 mIntScratch = (jintArray) env->NewGlobalRef(env->NewIntArray(16));
343 mFloatScratch = (jfloatArray) env->NewGlobalRef(env->NewFloatArray(16));
344 }
~Receiver()345 ~Receiver() {
346 JNIEnv* env = AndroidRuntime::getJNIEnv();
347 env->DeleteGlobalRef(mReceiverWeakGlobal);
348 env->DeleteGlobalRef(mFloatScratch);
349 env->DeleteGlobalRef(mIntScratch);
350 }
getSensorEventQueue() const351 sp<SensorEventQueue> getSensorEventQueue() const {
352 return mSensorQueue;
353 }
354
destroy()355 void destroy() {
356 mMessageQueue->getLooper()->removeFd( mSensorQueue->getFd() );
357 }
358
359 private:
onFirstRef()360 virtual void onFirstRef() {
361 LooperCallback::onFirstRef();
362 mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
363 ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
364 }
365
handleEvent(int fd,int events,void * data)366 virtual int handleEvent(int fd, int events, void* data) {
367 JNIEnv* env = AndroidRuntime::getJNIEnv();
368 sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);
369 ScopedLocalRef<jobject> receiverObj(env, GetReferent(env, mReceiverWeakGlobal));
370
371 ssize_t n;
372 ASensorEvent buffer[16];
373 while ((n = q->read(buffer, 16)) > 0) {
374 for (int i=0 ; i<n ; i++) {
375 if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {
376 // step-counter returns a uint64, but the java API only deals with floats
377 float value = float(buffer[i].u64.step_counter);
378 env->SetFloatArrayRegion(mFloatScratch, 0, 1, &value);
379 } else if (buffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META) {
380 float value[2];
381 value[0] = buffer[i].dynamic_sensor_meta.connected ? 1.f: 0.f;
382 value[1] = float(buffer[i].dynamic_sensor_meta.handle);
383 env->SetFloatArrayRegion(mFloatScratch, 0, 2, value);
384 } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
385 env->SetIntArrayRegion(mIntScratch, 0, 14,
386 buffer[i].additional_info.data_int32);
387 env->SetFloatArrayRegion(mFloatScratch, 0, 14,
388 buffer[i].additional_info.data_float);
389 } else {
390 env->SetFloatArrayRegion(mFloatScratch, 0, 16, buffer[i].data);
391 }
392
393 if (buffer[i].type == SENSOR_TYPE_META_DATA) {
394 // This is a flush complete sensor event. Call dispatchFlushCompleteEvent
395 // method.
396 if (receiverObj.get()) {
397 env->CallVoidMethod(receiverObj.get(),
398 gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
399 buffer[i].meta_data.sensor);
400 }
401 } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
402 // This is a flush complete sensor event. Call dispatchAdditionalInfoEvent
403 // method.
404 if (receiverObj.get()) {
405 int type = buffer[i].additional_info.type;
406 int serial = buffer[i].additional_info.serial;
407 env->CallVoidMethod(receiverObj.get(),
408 gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent,
409 buffer[i].sensor,
410 type, serial,
411 mFloatScratch,
412 mIntScratch,
413 buffer[i].timestamp);
414 }
415 }else {
416 int8_t status;
417 switch (buffer[i].type) {
418 case SENSOR_TYPE_ORIENTATION:
419 case SENSOR_TYPE_MAGNETIC_FIELD:
420 case SENSOR_TYPE_ACCELEROMETER:
421 case SENSOR_TYPE_GYROSCOPE:
422 case SENSOR_TYPE_GRAVITY:
423 case SENSOR_TYPE_LINEAR_ACCELERATION:
424 status = buffer[i].vector.status;
425 break;
426 case SENSOR_TYPE_HEART_RATE:
427 status = buffer[i].heart_rate.status;
428 break;
429 default:
430 status = SENSOR_STATUS_ACCURACY_HIGH;
431 break;
432 }
433 if (receiverObj.get()) {
434 env->CallVoidMethod(receiverObj.get(),
435 gBaseEventQueueClassInfo.dispatchSensorEvent,
436 buffer[i].sensor,
437 mFloatScratch,
438 status,
439 buffer[i].timestamp);
440 }
441 }
442 if (env->ExceptionCheck()) {
443 mSensorQueue->sendAck(buffer, n);
444 ALOGE("Exception dispatching input event.");
445 return 1;
446 }
447 }
448 mSensorQueue->sendAck(buffer, n);
449 }
450 if (n<0 && n != -EAGAIN) {
451 // FIXME: error receiving events, what to do in this case?
452 }
453 return 1;
454 }
455 };
456
nativeInitSensorEventQueue(JNIEnv * env,jclass clazz,jlong sensorManager,jobject eventQWeak,jobject msgQ,jstring packageName,jint mode,jstring opPackageName,jstring attributionTag)457 static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
458 jobject eventQWeak, jobject msgQ, jstring packageName,
459 jint mode, jstring opPackageName, jstring attributionTag) {
460 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
461 ScopedUtfChars packageUtf(env, packageName);
462 String8 clientName(packageUtf.c_str());
463
464 String16 attributionTagName("");
465 if (attributionTag != nullptr) {
466 ScopedUtfChars attrUtf(env, attributionTag);
467 attributionTagName = String16(attrUtf.c_str());
468 }
469 sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode, attributionTagName));
470
471 if (queue == NULL) {
472 jniThrowRuntimeException(env, "Cannot construct native SensorEventQueue.");
473 return 0;
474 }
475
476 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
477 if (messageQueue == NULL) {
478 jniThrowRuntimeException(env, "MessageQueue is not initialized.");
479 return 0;
480 }
481
482 sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak);
483 receiver->incStrong((void*)nativeInitSensorEventQueue);
484 return jlong(receiver.get());
485 }
486
nativeEnableSensor(JNIEnv * env,jclass clazz,jlong eventQ,jint handle,jint rate_us,jint maxBatchReportLatency)487 static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us,
488 jint maxBatchReportLatency) {
489 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
490 return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency,
491 0);
492 }
493
nativeDisableSensor(JNIEnv * env,jclass clazz,jlong eventQ,jint handle)494 static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle) {
495 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
496 return receiver->getSensorEventQueue()->disableSensor(handle);
497 }
498
nativeDestroySensorEventQueue(JNIEnv * env,jclass clazz,jlong eventQ)499 static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jlong eventQ) {
500 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
501 receiver->destroy();
502 receiver->decStrong((void*)nativeInitSensorEventQueue);
503 }
504
nativeFlushSensor(JNIEnv * env,jclass clazz,jlong eventQ)505 static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jlong eventQ) {
506 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
507 return receiver->getSensorEventQueue()->flush();
508 }
509
nativeInjectSensorData(JNIEnv * env,jclass clazz,jlong eventQ,jint handle,jfloatArray values,jint accuracy,jlong timestamp)510 static jint nativeInjectSensorData(JNIEnv *env, jclass clazz, jlong eventQ, jint handle,
511 jfloatArray values, jint accuracy, jlong timestamp) {
512 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
513 // Create a sensor_event from the above data which can be injected into the HAL.
514 ASensorEvent sensor_event;
515 memset(&sensor_event, 0, sizeof(sensor_event));
516 sensor_event.sensor = handle;
517 sensor_event.timestamp = timestamp;
518 env->GetFloatArrayRegion(values, 0, env->GetArrayLength(values), sensor_event.data);
519 return receiver->getSensorEventQueue()->injectSensorEvent(sensor_event);
520 }
521 //----------------------------------------------------------------------------
522
523 static const JNINativeMethod gSystemSensorManagerMethods[] = {
524 {"nativeClassInit", "()V", (void *)nativeClassInit},
525 {"nativeCreate", "(Ljava/lang/String;)J", (void *)nativeCreate},
526
527 {"nativeGetSensorAtIndex", "(JLandroid/hardware/Sensor;I)Z",
528 (void *)nativeGetSensorAtIndex},
529
530 {"nativeGetDynamicSensors", "(JLjava/util/List;)V", (void *)nativeGetDynamicSensors},
531
532 {"nativeGetRuntimeSensors", "(JILjava/util/List;)V", (void *)nativeGetRuntimeSensors},
533
534 {"nativeIsDataInjectionEnabled", "(J)Z", (void *)nativeIsDataInjectionEnabled},
535
536 {"nativeCreateDirectChannel", "(JIJIILandroid/hardware/HardwareBuffer;)I",
537 (void *)nativeCreateDirectChannel},
538
539 {"nativeDestroyDirectChannel", "(JI)V", (void *)nativeDestroyDirectChannel},
540
541 {"nativeConfigDirectChannel", "(JIII)I", (void *)nativeConfigDirectChannel},
542
543 {"nativeSetOperationParameter", "(JII[F[I)I", (void *)nativeSetOperationParameter},
544 };
545
546 static const JNINativeMethod gBaseEventQueueMethods[] = {
547 {"nativeInitBaseEventQueue",
548 "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;Ljava/lang/String;ILjava/lang/"
549 "String;Ljava/lang/String;)J",
550 (void *)nativeInitSensorEventQueue},
551
552 {"nativeEnableSensor", "(JIII)I", (void *)nativeEnableSensor},
553
554 {"nativeDisableSensor", "(JI)I", (void *)nativeDisableSensor},
555
556 {"nativeDestroySensorEventQueue", "(J)V", (void *)nativeDestroySensorEventQueue},
557
558 {"nativeFlushSensor", "(J)I", (void *)nativeFlushSensor},
559
560 {"nativeInjectSensorData", "(JI[FIJ)I", (void *)nativeInjectSensorData},
561 };
562
563 } //unnamed namespace
564
register_android_hardware_SensorManager(JNIEnv * env)565 int register_android_hardware_SensorManager(JNIEnv *env)
566 {
567 RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager",
568 gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
569
570 RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager$BaseEventQueue",
571 gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));
572
573 gBaseEventQueueClassInfo.clazz = FindClassOrDie(env,
574 "android/hardware/SystemSensorManager$BaseEventQueue");
575
576 gBaseEventQueueClassInfo.dispatchSensorEvent = GetMethodIDOrDie(env,
577 gBaseEventQueueClassInfo.clazz, "dispatchSensorEvent", "(I[FIJ)V");
578
579 gBaseEventQueueClassInfo.dispatchFlushCompleteEvent = GetMethodIDOrDie(env,
580 gBaseEventQueueClassInfo.clazz, "dispatchFlushCompleteEvent", "(I)V");
581
582 gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent = GetMethodIDOrDie(env,
583 gBaseEventQueueClassInfo.clazz, "dispatchAdditionalInfoEvent", "(III[F[I)V");
584
585 return 0;
586 }
587