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