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