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