xref: /aosp_15_r20/frameworks/base/core/jni/android_hardware_SensorManager.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
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