blob: 5b327d40ac69d6e1b07a4acf689c5c5ccb613911 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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 */
Mike Lockwood270e87f2009-05-22 10:02:14 -040016#define LOG_TAG "SensorManager"
17
Steven Moreland2279b252017-07-19 09:50:45 -070018#include <nativehelper/JNIHelp.h>
Peng Xud5ec5f92016-04-27 14:49:25 -070019#include "android_os_MessageQueue.h"
20#include "core_jni_helpers.h"
21#include "jni.h"
destradaa9ba7c1c2015-02-10 15:04:43 -080022
Steven Moreland2279b252017-07-19 09:50:45 -070023#include <nativehelper/ScopedUtfChars.h>
24#include <nativehelper/ScopedLocalRef.h>
Peng Xud5ec5f92016-04-27 14:49:25 -070025#include <android_runtime/AndroidRuntime.h>
Peng Xu7d96fa02017-03-04 16:15:45 -080026#include <android_runtime/android_hardware_HardwareBuffer.h>
Jesse Hall5f73ab72017-04-17 08:54:43 -070027#include <vndk/hardware_buffer.h>
Mathias Agopiancaf89302017-03-06 16:06:49 -080028#include <sensor/Sensor.h>
29#include <sensor/SensorEventQueue.h>
30#include <sensor/SensorManager.h>
Peng Xufa2672b2016-12-07 03:54:44 -080031#include <cutils/native_handle.h>
Mathias Agopiandb772d82013-01-31 19:31:12 -080032#include <utils/Log.h>
33#include <utils/Looper.h>
Peng Xua35b5532016-01-20 00:05:45 -080034#include <utils/Vector.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035
Peng Xud5ec5f92016-04-27 14:49:25 -070036#include <map>
Andreas Gampe987f79f2014-11-18 17:29:46 -080037
Peng Xu4a4baef2016-03-16 16:56:39 -070038namespace {
39
40using namespace android;
41
42struct {
Mathias Agopiandb772d82013-01-31 19:31:12 -080043 jclass clazz;
44 jmethodID dispatchSensorEvent;
Aravind Akellab4c76b12013-06-27 12:04:16 -070045 jmethodID dispatchFlushCompleteEvent;
Peng Xua2958352016-01-26 18:42:17 -080046 jmethodID dispatchAdditionalInfoEvent;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -080047} gBaseEventQueueClassInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049struct SensorOffsets
50{
Peng Xua35b5532016-01-20 00:05:45 -080051 jclass clazz;
Peng Xub85b1fe2016-04-20 21:28:33 -070052 //fields
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 jfieldID name;
54 jfieldID vendor;
55 jfieldID version;
56 jfieldID handle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057 jfieldID range;
58 jfieldID resolution;
59 jfieldID power;
Mathias Agopian050b5622010-07-29 16:51:38 -070060 jfieldID minDelay;
Aravind Akellab4c76b12013-06-27 12:04:16 -070061 jfieldID fifoReservedEventCount;
62 jfieldID fifoMaxEventCount;
Aravind Akellacd9a7bb2014-04-07 22:55:21 +000063 jfieldID stringType;
64 jfieldID requiredPermission;
Aravind Akella2f8b9142014-05-12 14:39:29 -070065 jfieldID maxDelay;
Aravind Akella27900352014-06-03 19:20:42 -070066 jfieldID flags;
Peng Xub85b1fe2016-04-20 21:28:33 -070067 //methods
destradaa9ba7c1c2015-02-10 15:04:43 -080068 jmethodID setType;
Peng Xub85b1fe2016-04-20 21:28:33 -070069 jmethodID setUuid;
Peng Xua35b5532016-01-20 00:05:45 -080070 jmethodID init;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071} gSensorOffsets;
72
Peng Xua35b5532016-01-20 00:05:45 -080073struct ListOffsets {
74 jclass clazz;
75 jmethodID add;
76} gListOffsets;
Mathias Agopiandb772d82013-01-31 19:31:12 -080077
Peng Xu3e132042017-04-17 17:45:24 -070078struct StringOffsets {
79 jclass clazz;
80 jmethodID intern;
81 jstring emptyString;
82} gStringOffsets;
83
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084/*
Peng Xu4a4baef2016-03-16 16:56:39 -070085 * nativeClassInit is not inteneded to be thread-safe. It should be called before other native...
86 * functions (except nativeCreate).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 */
Mathias Agopiandb772d82013-01-31 19:31:12 -080088static void
89nativeClassInit (JNIEnv *_env, jclass _this)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090{
Peng Xua35b5532016-01-20 00:05:45 -080091 //android.hardware.Sensor
Mathias Agopiandb772d82013-01-31 19:31:12 -080092 SensorOffsets& sensorOffsets = gSensorOffsets;
Peng Xu3e132042017-04-17 17:45:24 -070093 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");
Aravind Akellab4c76b12013-06-27 12:04:16 -0700104 sensorOffsets.fifoReservedEventCount =
Peng Xu3e132042017-04-17 17:45:24 -0700105 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");
Peng Xua35b5532016-01-20 00:05:45 -0800113
Peng Xu3e132042017-04-17 17:45:24 -0700114 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");
Peng Xua35b5532016-01-20 00:05:45 -0800117
118 // java.util.List;
119 ListOffsets& listOffsets = gListOffsets;
Peng Xu3e132042017-04-17 17:45:24 -0700120 jclass listClass = (jclass) MakeGlobalRefOrDie(_env, FindClassOrDie(_env, "java/util/List"));
Peng Xua35b5532016-01-20 00:05:45 -0800121 listOffsets.clazz = listClass;
Peng Xu3e132042017-04-17 17:45:24 -0700122 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));
destradaa9ba7c1c2015-02-10 15:04:43 -0800132}
133
Peng Xu3e132042017-04-17 17:45:24 -0700134static jstring getJavaInternedString(JNIEnv *env, const String8 &string) {
135 if (string == "") {
136 return gStringOffsets.emptyString;
destradaa9ba7c1c2015-02-10 15:04:43 -0800137 }
destradaa9ba7c1c2015-02-10 15:04:43 -0800138
Peng Xu3e132042017-04-17 17:45:24 -0700139 ScopedLocalRef<jstring> javaString(env, env->NewStringUTF(string.string()));
140 jstring internedString = (jstring)
141 env->CallObjectMethod(javaString.get(), gStringOffsets.intern);
destradaa9ba7c1c2015-02-10 15:04:43 -0800142 return internedString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143}
144
Svet Ganovb9d71a62015-04-30 10:38:13 -0700145static jlong
146nativeCreate
147(JNIEnv *env, jclass clazz, jstring opPackageName)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148{
Svet Ganovb9d71a62015-04-30 10:38:13 -0700149 ScopedUtfChars opPackageNameUtf(env, opPackageName);
Aravind Akella2af91d02015-07-29 18:39:52 -0700150 return (jlong) &SensorManager::getInstanceForPackage(String16(opPackageNameUtf.c_str()));
Svet Ganovb9d71a62015-04-30 10:38:13 -0700151}
152
Peng Xua35b5532016-01-20 00:05:45 -0800153static jobject
154translateNativeSensorToJavaSensor(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) {
Peng Xu3e132042017-04-17 17:45:24 -0700163 jstring name = getJavaInternedString(env, nativeSensor.getName());
164 jstring vendor = getJavaInternedString(env, nativeSensor.getVendor());
Peng Xua35b5532016-01-20 00:05:45 -0800165 jstring requiredPermission =
Peng Xu3e132042017-04-17 17:45:24 -0700166 getJavaInternedString(env, nativeSensor.getRequiredPermission());
Peng Xua35b5532016-01-20 00:05:45 -0800167
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());
Peng Xub85b1fe2016-04-20 21:28:33 -0700184
Peng Xua35b5532016-01-20 00:05:45 -0800185 if (env->CallBooleanMethod(sensor, sensorOffsets.setType, nativeSensor.getType())
186 == JNI_FALSE) {
Peng Xu3e132042017-04-17 17:45:24 -0700187 jstring stringType = getJavaInternedString(env, nativeSensor.getStringType());
Peng Xua35b5532016-01-20 00:05:45 -0800188 env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
189 }
Peng Xub85b1fe2016-04-20 21:28:33 -0700190
Peng Xu716866d2016-05-25 21:10:00 -0700191 // TODO(b/29547335): Rename "setUuid" method to "setId".
192 int64_t id = nativeSensor.getId();
193 env->CallVoidMethod(sensor, sensorOffsets.setUuid, id, 0);
Peng Xua35b5532016-01-20 00:05:45 -0800194 }
195 return sensor;
196}
197
Aravind Akella516e40e2015-07-01 16:54:24 -0700198static jboolean
199nativeGetSensorAtIndex(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensor, jint index)
Svet Ganovb9d71a62015-04-30 10:38:13 -0700200{
201 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202
Mathias Agopian1bf79782010-07-14 23:41:37 -0700203 Sensor const* const* sensorList;
Peng Xua08c9f52016-02-04 22:27:20 -0800204 ssize_t count = mgr->getSensorList(&sensorList);
205 if (ssize_t(index) >= count) {
Aravind Akella516e40e2015-07-01 16:54:24 -0700206 return false;
destradaa9ba7c1c2015-02-10 15:04:43 -0800207 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700208
Peng Xub85b1fe2016-04-20 21:28:33 -0700209 return translateNativeSensorToJavaSensor(env, sensor, *sensorList[index]) != NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210}
211
Peng Xua35b5532016-01-20 00:05:45 -0800212static void
213nativeGetDynamicSensors(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
Ben Wagner85ea32b2016-03-16 17:10:42 -0400222 ALOGI("DYNS native SensorManager.getDynamicSensorList return %zu sensors", nativeList.size());
Peng Xua35b5532016-01-20 00:05:45 -0800223 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
Aravind Akellad123b512015-06-29 12:35:51 -0700230static jboolean nativeIsDataInjectionEnabled(JNIEnv *_env, jclass _this, jlong sensorManager) {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700231 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
Aravind Akellad123b512015-06-29 12:35:51 -0700232 return mgr->isDataInjectionEnabled();
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700233}
234
Peng Xufa2672b2016-12-07 03:54:44 -0800235static jint nativeCreateDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
Peng Xu7d96fa02017-03-04 16:15:45 -0800236 jlong size, jint channelType, jint fd, jobject hardwareBufferObj) {
237 const native_handle_t *nativeHandle = nullptr;
238 NATIVE_HANDLE_DECLARE_STORAGE(ashmemHandle, 1, 0);
Peng Xufa2672b2016-12-07 03:54:44 -0800239
Peng Xu7d96fa02017-03-04 16:15:45 -0800240 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);
Peng Xufa2672b2016-12-07 03:54:44 -0800249 }
250 }
Peng Xu7d96fa02017-03-04 16:15:45 -0800251
252 if (nativeHandle == nullptr) {
253 return BAD_VALUE;
254 }
255
256 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
257 return mgr->createDirectChannel(size, channelType, nativeHandle);
Peng Xufa2672b2016-12-07 03:54:44 -0800258}
259
260static void nativeDestroyDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
261 jint channelHandle) {
262 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
263 mgr->destroyDirectChannel(channelHandle);
264}
265
266static 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
Peng Xu1cfde252017-01-19 17:10:09 -0800272static jint nativeSetOperationParameter(JNIEnv *_env, jclass _this, jlong sensorManager,
Alexey Polyudov5b5e11c2017-05-23 19:54:26 -0700273 jint handle, jint type, jfloatArray floats, jintArray ints) {
Peng Xu1cfde252017-01-19 17:10:09 -0800274 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
Alexey Polyudov5b5e11c2017-05-23 19:54:26 -0700288 return mgr->setOperationParameter(handle, type, floatVector, int32Vector);
Peng Xu1cfde252017-01-19 17:10:09 -0800289}
290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291//----------------------------------------------------------------------------
Mathias Agopiandb772d82013-01-31 19:31:12 -0800292
293class Receiver : public LooperCallback {
294 sp<SensorEventQueue> mSensorQueue;
295 sp<MessageQueue> mMessageQueue;
Jeff Brown3b4049e2015-04-17 15:22:27 -0700296 jobject mReceiverWeakGlobal;
Peng Xua2958352016-01-26 18:42:17 -0800297 jfloatArray mFloatScratch;
298 jintArray mIntScratch;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800299public:
300 Receiver(const sp<SensorEventQueue>& sensorQueue,
301 const sp<MessageQueue>& messageQueue,
Peng Xua2958352016-01-26 18:42:17 -0800302 jobject receiverWeak) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800303 JNIEnv* env = AndroidRuntime::getJNIEnv();
304 mSensorQueue = sensorQueue;
305 mMessageQueue = messageQueue;
Jeff Brown3b4049e2015-04-17 15:22:27 -0700306 mReceiverWeakGlobal = env->NewGlobalRef(receiverWeak);
Peng Xua2958352016-01-26 18:42:17 -0800307
308 mIntScratch = (jintArray) env->NewGlobalRef(env->NewIntArray(16));
309 mFloatScratch = (jfloatArray) env->NewGlobalRef(env->NewFloatArray(16));
Mathias Agopiandb772d82013-01-31 19:31:12 -0800310 }
311 ~Receiver() {
312 JNIEnv* env = AndroidRuntime::getJNIEnv();
Jeff Brown3b4049e2015-04-17 15:22:27 -0700313 env->DeleteGlobalRef(mReceiverWeakGlobal);
Peng Xua2958352016-01-26 18:42:17 -0800314 env->DeleteGlobalRef(mFloatScratch);
315 env->DeleteGlobalRef(mIntScratch);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800316 }
317 sp<SensorEventQueue> getSensorEventQueue() const {
318 return mSensorQueue;
319 }
320
321 void destroy() {
322 mMessageQueue->getLooper()->removeFd( mSensorQueue->getFd() );
323 }
324
325private:
326 virtual void onFirstRef() {
327 LooperCallback::onFirstRef();
328 mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
329 ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
330 }
331
332 virtual int handleEvent(int fd, int events, void* data) {
333 JNIEnv* env = AndroidRuntime::getJNIEnv();
334 sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);
Jeff Brown3b4049e2015-04-17 15:22:27 -0700335 ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
336
Mathias Agopiandb772d82013-01-31 19:31:12 -0800337 ssize_t n;
338 ASensorEvent buffer[16];
339 while ((n = q->read(buffer, 16)) > 0) {
340 for (int i=0 ; i<n ; i++) {
Aravind Akella0288ca62014-07-28 14:53:44 -0700341 if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {
Jean-Baptiste Queru3c9c0912013-08-05 11:03:28 -0700342 // step-counter returns a uint64, but the java API only deals with floats
343 float value = float(buffer[i].u64.step_counter);
Peng Xua2958352016-01-26 18:42:17 -0800344 env->SetFloatArrayRegion(mFloatScratch, 0, 1, &value);
Peng Xua35b5532016-01-20 00:05:45 -0800345 } 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);
Peng Xua2958352016-01-26 18:42:17 -0800349 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);
Jean-Baptiste Queru3c9c0912013-08-05 11:03:28 -0700355 } else {
Peng Xua2958352016-01-26 18:42:17 -0800356 env->SetFloatArrayRegion(mFloatScratch, 0, 16, buffer[i].data);
Jean-Baptiste Queru3c9c0912013-08-05 11:03:28 -0700357 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800358
Aravind Akellab4c76b12013-06-27 12:04:16 -0700359 if (buffer[i].type == SENSOR_TYPE_META_DATA) {
360 // This is a flush complete sensor event. Call dispatchFlushCompleteEvent
361 // method.
Jeff Brown3b4049e2015-04-17 15:22:27 -0700362 if (receiverObj.get()) {
363 env->CallVoidMethod(receiverObj.get(),
364 gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
365 buffer[i].meta_data.sensor);
366 }
Peng Xua2958352016-01-26 18:42:17 -0800367 } 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 {
Etienne Le Grandaf805102014-05-16 12:21:41 -0700382 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:
Aravind Akellaf38226a2015-06-23 10:32:16 -0700388 case SENSOR_TYPE_GRAVITY:
389 case SENSOR_TYPE_LINEAR_ACCELERATION:
Etienne Le Grandaf805102014-05-16 12:21:41 -0700390 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 }
Jeff Brown3b4049e2015-04-17 15:22:27 -0700399 if (receiverObj.get()) {
400 env->CallVoidMethod(receiverObj.get(),
401 gBaseEventQueueClassInfo.dispatchSensorEvent,
402 buffer[i].sensor,
Peng Xua2958352016-01-26 18:42:17 -0800403 mFloatScratch,
Jeff Brown3b4049e2015-04-17 15:22:27 -0700404 status,
405 buffer[i].timestamp);
406 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700407 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800408 if (env->ExceptionCheck()) {
Aravind Akella35187bd2014-02-11 18:44:42 -0800409 mSensorQueue->sendAck(buffer, n);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800410 ALOGE("Exception dispatching input event.");
411 return 1;
412 }
413 }
Aravind Akella35187bd2014-02-11 18:44:42 -0800414 mSensorQueue->sendAck(buffer, n);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800415 }
416 if (n<0 && n != -EAGAIN) {
417 // FIXME: error receiving events, what to do in this case?
418 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800419 return 1;
420 }
421};
422
Svet Ganovb9d71a62015-04-30 10:38:13 -0700423static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
Peng Xua2958352016-01-26 18:42:17 -0800424 jobject eventQWeak, jobject msgQ, jstring packageName, jint mode) {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700425 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
Aravind Akella88445992015-02-26 17:05:28 -0800426 ScopedUtfChars packageUtf(env, packageName);
427 String8 clientName(packageUtf.c_str());
Svet Ganovb9d71a62015-04-30 10:38:13 -0700428 sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429
Peng Xud9d4e1b2017-04-23 15:23:07 -0700430 if (queue == NULL) {
431 jniThrowRuntimeException(env, "Cannot construct native SensorEventQueue.");
432 return 0;
433 }
434
Mathias Agopiandb772d82013-01-31 19:31:12 -0800435 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
436 if (messageQueue == NULL) {
437 jniThrowRuntimeException(env, "MessageQueue is not initialized.");
438 return 0;
Mathias Agopian0b6d77b2012-05-07 18:27:06 -0700439 }
Mathias Agopian1bf79782010-07-14 23:41:37 -0700440
Peng Xua2958352016-01-26 18:42:17 -0800441 sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak);
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800442 receiver->incStrong((void*)nativeInitSensorEventQueue);
Ashok Bhat4838e332014-01-03 14:37:19 +0000443 return jlong(receiver.get());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444}
445
Ashok Bhat4838e332014-01-03 14:37:19 +0000446static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us,
Aravind Akella88445992015-02-26 17:05:28 -0800447 jint maxBatchReportLatency) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800448 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
Aravind Akellab4c76b12013-06-27 12:04:16 -0700449 return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency,
Aravind Akella88445992015-02-26 17:05:28 -0800450 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451}
452
Ashok Bhat4838e332014-01-03 14:37:19 +0000453static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800454 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
455 return receiver->getSensorEventQueue()->disableSensor(handle);
456}
Mathias Agopian1bf79782010-07-14 23:41:37 -0700457
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700458static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jlong eventQ) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800459 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
460 receiver->destroy();
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800461 receiver->decStrong((void*)nativeInitSensorEventQueue);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800462}
Mathias Agopian1bf79782010-07-14 23:41:37 -0700463
Ashok Bhat4838e332014-01-03 14:37:19 +0000464static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jlong eventQ) {
Aravind Akellab4c76b12013-06-27 12:04:16 -0700465 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700466 return receiver->getSensorEventQueue()->flush();
Aravind Akellab4c76b12013-06-27 12:04:16 -0700467}
Mathias Agopiandb772d82013-01-31 19:31:12 -0800468
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700469static 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}
Mathias Agopiandb772d82013-01-31 19:31:12 -0800480//----------------------------------------------------------------------------
481
Daniel Micay76f6a862015-09-19 17:31:01 -0400482static const JNINativeMethod gSystemSensorManagerMethods[] = {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800483 {"nativeClassInit",
484 "()V",
485 (void*)nativeClassInit },
Svet Ganovb9d71a62015-04-30 10:38:13 -0700486 {"nativeCreate",
487 "(Ljava/lang/String;)J",
488 (void*)nativeCreate },
Mathias Agopiandb772d82013-01-31 19:31:12 -0800489
Aravind Akella516e40e2015-07-01 16:54:24 -0700490 {"nativeGetSensorAtIndex",
491 "(JLandroid/hardware/Sensor;I)Z",
492 (void*)nativeGetSensorAtIndex },
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700493
Peng Xua35b5532016-01-20 00:05:45 -0800494 {"nativeGetDynamicSensors",
495 "(JLjava/util/List;)V",
496 (void*)nativeGetDynamicSensors },
497
Aravind Akellad123b512015-06-29 12:35:51 -0700498 {"nativeIsDataInjectionEnabled",
499 "(J)Z",
Peng Xufa2672b2016-12-07 03:54:44 -0800500 (void*)nativeIsDataInjectionEnabled },
501
502 {"nativeCreateDirectChannel",
Peng Xu7d96fa02017-03-04 16:15:45 -0800503 "(JJIILandroid/hardware/HardwareBuffer;)I",
Peng Xufa2672b2016-12-07 03:54:44 -0800504 (void*)nativeCreateDirectChannel },
505
506 {"nativeDestroyDirectChannel",
507 "(JI)V",
508 (void*)nativeDestroyDirectChannel },
509
510 {"nativeConfigDirectChannel",
511 "(JIII)I",
512 (void*)nativeConfigDirectChannel },
Peng Xu1cfde252017-01-19 17:10:09 -0800513
514 {"nativeSetOperationParameter",
Alexey Polyudov5b5e11c2017-05-23 19:54:26 -0700515 "(JII[F[I)I",
Peng Xu1cfde252017-01-19 17:10:09 -0800516 (void*)nativeSetOperationParameter },
Mathias Agopiandb772d82013-01-31 19:31:12 -0800517};
518
Daniel Micay76f6a862015-09-19 17:31:01 -0400519static const JNINativeMethod gBaseEventQueueMethods[] = {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800520 {"nativeInitBaseEventQueue",
Peng Xua2958352016-01-26 18:42:17 -0800521 "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;Ljava/lang/String;ILjava/lang/String;)J",
Svet Ganovb9d71a62015-04-30 10:38:13 -0700522 (void*)nativeInitSensorEventQueue },
Mathias Agopiandb772d82013-01-31 19:31:12 -0800523
524 {"nativeEnableSensor",
Aravind Akella88445992015-02-26 17:05:28 -0800525 "(JIII)I",
Mathias Agopiandb772d82013-01-31 19:31:12 -0800526 (void*)nativeEnableSensor },
527
528 {"nativeDisableSensor",
Ashok Bhat4838e332014-01-03 14:37:19 +0000529 "(JI)I",
Mathias Agopiandb772d82013-01-31 19:31:12 -0800530 (void*)nativeDisableSensor },
531
532 {"nativeDestroySensorEventQueue",
Ashok Bhat4838e332014-01-03 14:37:19 +0000533 "(J)V",
Mathias Agopiandb772d82013-01-31 19:31:12 -0800534 (void*)nativeDestroySensorEventQueue },
Aravind Akellab4c76b12013-06-27 12:04:16 -0700535
536 {"nativeFlushSensor",
Ashok Bhat4838e332014-01-03 14:37:19 +0000537 "(J)I",
Aravind Akellab4c76b12013-06-27 12:04:16 -0700538 (void*)nativeFlushSensor },
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700539
540 {"nativeInjectSensorData",
541 "(JI[FIJ)I",
542 (void*)nativeInjectSensorData },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543};
544
Peng Xu4a4baef2016-03-16 16:56:39 -0700545} //unnamed namespace
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546
547int register_android_hardware_SensorManager(JNIEnv *env)
548{
Andreas Gampe987f79f2014-11-18 17:29:46 -0800549 RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager",
Mathias Agopiandb772d82013-01-31 19:31:12 -0800550 gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
551
Andreas Gampe987f79f2014-11-18 17:29:46 -0800552 RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager$BaseEventQueue",
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800553 gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));
Mathias Agopiandb772d82013-01-31 19:31:12 -0800554
Andreas Gampe987f79f2014-11-18 17:29:46 -0800555 gBaseEventQueueClassInfo.clazz = FindClassOrDie(env,
556 "android/hardware/SystemSensorManager$BaseEventQueue");
Mathias Agopiandb772d82013-01-31 19:31:12 -0800557
Andreas Gampe987f79f2014-11-18 17:29:46 -0800558 gBaseEventQueueClassInfo.dispatchSensorEvent = GetMethodIDOrDie(env,
559 gBaseEventQueueClassInfo.clazz, "dispatchSensorEvent", "(I[FIJ)V");
Mathias Agopiandb772d82013-01-31 19:31:12 -0800560
Andreas Gampe987f79f2014-11-18 17:29:46 -0800561 gBaseEventQueueClassInfo.dispatchFlushCompleteEvent = GetMethodIDOrDie(env,
562 gBaseEventQueueClassInfo.clazz, "dispatchFlushCompleteEvent", "(I)V");
Aravind Akellab4c76b12013-06-27 12:04:16 -0700563
Peng Xua2958352016-01-26 18:42:17 -0800564 gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent = GetMethodIDOrDie(env,
565 gBaseEventQueueClassInfo.clazz, "dispatchAdditionalInfoEvent", "(III[F[I)V");
566
Mathias Agopiandb772d82013-01-31 19:31:12 -0800567 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800568}