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