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