blob: 2c7174d71c6b424a58461d630e6cedb7c7ef6e58 [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
Peng Xud5ec5f92016-04-27 14:49:25 -070018#include "JNIHelp.h"
19#include "android_os_MessageQueue.h"
20#include "core_jni_helpers.h"
21#include "jni.h"
destradaa9ba7c1c2015-02-10 15:04:43 -080022
Aravind Akella88445992015-02-26 17:05:28 -080023#include <ScopedUtfChars.h>
Jeff Brown3b4049e2015-04-17 15:22:27 -070024#include <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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078/*
Peng Xu4a4baef2016-03-16 16:56:39 -070079 * nativeClassInit is not inteneded to be thread-safe. It should be called before other native...
80 * functions (except nativeCreate).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 */
Mathias Agopiandb772d82013-01-31 19:31:12 -080082static void
83nativeClassInit (JNIEnv *_env, jclass _this)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084{
Peng Xua35b5532016-01-20 00:05:45 -080085 //android.hardware.Sensor
Mathias Agopiandb772d82013-01-31 19:31:12 -080086 SensorOffsets& sensorOffsets = gSensorOffsets;
Peng Xua35b5532016-01-20 00:05:45 -080087 jclass sensorClass = (jclass) _env->NewGlobalRef(_env->FindClass("android/hardware/Sensor"));
88 sensorOffsets.clazz = sensorClass;
Mathias Agopiandb772d82013-01-31 19:31:12 -080089 sensorOffsets.name = _env->GetFieldID(sensorClass, "mName", "Ljava/lang/String;");
90 sensorOffsets.vendor = _env->GetFieldID(sensorClass, "mVendor", "Ljava/lang/String;");
91 sensorOffsets.version = _env->GetFieldID(sensorClass, "mVersion", "I");
92 sensorOffsets.handle = _env->GetFieldID(sensorClass, "mHandle", "I");
Mathias Agopiandb772d82013-01-31 19:31:12 -080093 sensorOffsets.range = _env->GetFieldID(sensorClass, "mMaxRange", "F");
94 sensorOffsets.resolution = _env->GetFieldID(sensorClass, "mResolution","F");
95 sensorOffsets.power = _env->GetFieldID(sensorClass, "mPower", "F");
96 sensorOffsets.minDelay = _env->GetFieldID(sensorClass, "mMinDelay", "I");
Aravind Akellab4c76b12013-06-27 12:04:16 -070097 sensorOffsets.fifoReservedEventCount =
98 _env->GetFieldID(sensorClass, "mFifoReservedEventCount", "I");
99 sensorOffsets.fifoMaxEventCount = _env->GetFieldID(sensorClass, "mFifoMaxEventCount", "I");
Aravind Akellacd9a7bb2014-04-07 22:55:21 +0000100 sensorOffsets.stringType = _env->GetFieldID(sensorClass, "mStringType", "Ljava/lang/String;");
101 sensorOffsets.requiredPermission = _env->GetFieldID(sensorClass, "mRequiredPermission",
102 "Ljava/lang/String;");
Aravind Akella2f8b9142014-05-12 14:39:29 -0700103 sensorOffsets.maxDelay = _env->GetFieldID(sensorClass, "mMaxDelay", "I");
Aravind Akella27900352014-06-03 19:20:42 -0700104 sensorOffsets.flags = _env->GetFieldID(sensorClass, "mFlags", "I");
Peng Xua35b5532016-01-20 00:05:45 -0800105
destradaa9ba7c1c2015-02-10 15:04:43 -0800106 sensorOffsets.setType = _env->GetMethodID(sensorClass, "setType", "(I)Z");
Peng Xub85b1fe2016-04-20 21:28:33 -0700107 sensorOffsets.setUuid = _env->GetMethodID(sensorClass, "setUuid", "(JJ)V");
Peng Xua35b5532016-01-20 00:05:45 -0800108 sensorOffsets.init = _env->GetMethodID(sensorClass, "<init>", "()V");
109
110 // java.util.List;
111 ListOffsets& listOffsets = gListOffsets;
112 jclass listClass = (jclass) _env->NewGlobalRef(_env->FindClass("java/util/List"));
113 listOffsets.clazz = listClass;
114 listOffsets.add = _env->GetMethodID(listClass, "add", "(Ljava/lang/Object;)Z");
destradaa9ba7c1c2015-02-10 15:04:43 -0800115}
116
117/**
118 * A key comparator predicate.
119 * It is used to intern strings associated with Sensor data.
120 * It defines a 'Strict weak ordering' for the interned strings.
121 */
122class InternedStringCompare {
123public:
124 bool operator()(const String8* string1, const String8* string2) const {
125 if (string1 == NULL) {
126 return string2 != NULL;
127 }
Aravind Akella88445992015-02-26 17:05:28 -0800128 if (string2 == NULL) {
129 return false;
130 }
destradaa9ba7c1c2015-02-10 15:04:43 -0800131 return string1->compare(*string2) < 0;
132 }
133};
134
135/**
136 * A localized interning mechanism for Sensor strings.
137 * We implement our own interning to avoid the overhead of using java.lang.String#intern().
138 * It is common that Vendor, StringType, and RequirePermission data is common between many of the
139 * Sensors, by interning the memory usage to represent Sensors is optimized.
140 */
141static jstring
142getInternedString(JNIEnv *env, const String8* string) {
143 static std::map<const String8*, jstring, InternedStringCompare> internedStrings;
144
145 jstring internedString;
146 std::map<const String8*, jstring>::iterator iterator = internedStrings.find(string);
147 if (iterator != internedStrings.end()) {
148 internedString = iterator->second;
149 } else {
150 jstring localString = env->NewStringUTF(string->string());
151 // we are implementing our own interning so expect these strings to be backed by global refs
152 internedString = (jstring) env->NewGlobalRef(localString);
153 internedStrings.insert(std::make_pair(string, internedString));
154 env->DeleteLocalRef(localString);
155 }
destradaa9ba7c1c2015-02-10 15:04:43 -0800156 return internedString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157}
158
Svet Ganovb9d71a62015-04-30 10:38:13 -0700159static jlong
160nativeCreate
161(JNIEnv *env, jclass clazz, jstring opPackageName)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162{
Svet Ganovb9d71a62015-04-30 10:38:13 -0700163 ScopedUtfChars opPackageNameUtf(env, opPackageName);
Aravind Akella2af91d02015-07-29 18:39:52 -0700164 return (jlong) &SensorManager::getInstanceForPackage(String16(opPackageNameUtf.c_str()));
Svet Ganovb9d71a62015-04-30 10:38:13 -0700165}
166
Peng Xua35b5532016-01-20 00:05:45 -0800167static jobject
168translateNativeSensorToJavaSensor(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 = env->NewStringUTF(nativeSensor.getName().string());
178 jstring vendor = env->NewStringUTF(nativeSensor.getVendor().string());
179 jstring requiredPermission =
180 env->NewStringUTF(nativeSensor.getRequiredPermission().string());
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());
Peng Xub85b1fe2016-04-20 21:28:33 -0700198
Peng Xua35b5532016-01-20 00:05:45 -0800199 if (env->CallBooleanMethod(sensor, sensorOffsets.setType, nativeSensor.getType())
200 == JNI_FALSE) {
201 jstring stringType = getInternedString(env, &nativeSensor.getStringType());
202 env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
203 }
Peng Xub85b1fe2016-04-20 21:28:33 -0700204
Peng Xu716866d2016-05-25 21:10:00 -0700205 // TODO(b/29547335): Rename "setUuid" method to "setId".
206 int64_t id = nativeSensor.getId();
207 env->CallVoidMethod(sensor, sensorOffsets.setUuid, id, 0);
Peng Xua35b5532016-01-20 00:05:45 -0800208 }
209 return sensor;
210}
211
Aravind Akella516e40e2015-07-01 16:54:24 -0700212static jboolean
213nativeGetSensorAtIndex(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensor, jint index)
Svet Ganovb9d71a62015-04-30 10:38:13 -0700214{
215 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216
Mathias Agopian1bf79782010-07-14 23:41:37 -0700217 Sensor const* const* sensorList;
Peng Xua08c9f52016-02-04 22:27:20 -0800218 ssize_t count = mgr->getSensorList(&sensorList);
219 if (ssize_t(index) >= count) {
Aravind Akella516e40e2015-07-01 16:54:24 -0700220 return false;
destradaa9ba7c1c2015-02-10 15:04:43 -0800221 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700222
Peng Xub85b1fe2016-04-20 21:28:33 -0700223 return translateNativeSensorToJavaSensor(env, sensor, *sensorList[index]) != NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224}
225
Peng Xua35b5532016-01-20 00:05:45 -0800226static void
227nativeGetDynamicSensors(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensorList) {
228
229 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
230 const ListOffsets& listOffsets(gListOffsets);
231
232 Vector<Sensor> nativeList;
233
234 mgr->getDynamicSensorList(nativeList);
235
Ben Wagner85ea32b2016-03-16 17:10:42 -0400236 ALOGI("DYNS native SensorManager.getDynamicSensorList return %zu sensors", nativeList.size());
Peng Xua35b5532016-01-20 00:05:45 -0800237 for (size_t i = 0; i < nativeList.size(); ++i) {
238 jobject sensor = translateNativeSensorToJavaSensor(env, NULL, nativeList[i]);
239 // add to list
240 env->CallBooleanMethod(sensorList, listOffsets.add, sensor);
241 }
242}
243
Aravind Akellad123b512015-06-29 12:35:51 -0700244static jboolean nativeIsDataInjectionEnabled(JNIEnv *_env, jclass _this, jlong sensorManager) {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700245 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
Aravind Akellad123b512015-06-29 12:35:51 -0700246 return mgr->isDataInjectionEnabled();
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700247}
248
Peng Xufa2672b2016-12-07 03:54:44 -0800249static jint nativeCreateDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
Peng Xu7d96fa02017-03-04 16:15:45 -0800250 jlong size, jint channelType, jint fd, jobject hardwareBufferObj) {
251 const native_handle_t *nativeHandle = nullptr;
252 NATIVE_HANDLE_DECLARE_STORAGE(ashmemHandle, 1, 0);
Peng Xufa2672b2016-12-07 03:54:44 -0800253
Peng Xu7d96fa02017-03-04 16:15:45 -0800254 if (channelType == SENSOR_DIRECT_MEM_TYPE_ASHMEM) {
255 native_handle_t *handle = native_handle_init(ashmemHandle, 1, 0);
256 handle->data[0] = fd;
257 nativeHandle = handle;
258 } else if (channelType == SENSOR_DIRECT_MEM_TYPE_GRALLOC) {
259 AHardwareBuffer *hardwareBuffer =
260 android_hardware_HardwareBuffer_getNativeHardwareBuffer(_env, hardwareBufferObj);
261 if (hardwareBuffer != nullptr) {
262 nativeHandle = AHardwareBuffer_getNativeHandle(hardwareBuffer);
Peng Xufa2672b2016-12-07 03:54:44 -0800263 }
264 }
Peng Xu7d96fa02017-03-04 16:15:45 -0800265
266 if (nativeHandle == nullptr) {
267 return BAD_VALUE;
268 }
269
270 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
271 return mgr->createDirectChannel(size, channelType, nativeHandle);
Peng Xufa2672b2016-12-07 03:54:44 -0800272}
273
274static void nativeDestroyDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
275 jint channelHandle) {
276 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
277 mgr->destroyDirectChannel(channelHandle);
278}
279
280static jint nativeConfigDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
281 jint channelHandle, jint sensorHandle, jint rate) {
282 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
283 return mgr->configureDirectChannel(channelHandle, sensorHandle, rate);
284}
285
Peng Xu1cfde252017-01-19 17:10:09 -0800286static jint nativeSetOperationParameter(JNIEnv *_env, jclass _this, jlong sensorManager,
287 jint type, jfloatArray floats, jintArray ints) {
288 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
289 Vector<float> floatVector;
290 Vector<int32_t> int32Vector;
291
292 if (floats != nullptr) {
293 floatVector.resize(_env->GetArrayLength(floats));
294 _env->GetFloatArrayRegion(floats, 0, _env->GetArrayLength(floats), floatVector.editArray());
295 }
296
297 if (ints != nullptr) {
298 int32Vector.resize(_env->GetArrayLength(ints));
299 _env->GetIntArrayRegion(ints, 0, _env->GetArrayLength(ints), int32Vector.editArray());
300 }
301
302 return mgr->setOperationParameter(type, floatVector, int32Vector);
303}
304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305//----------------------------------------------------------------------------
Mathias Agopiandb772d82013-01-31 19:31:12 -0800306
307class Receiver : public LooperCallback {
308 sp<SensorEventQueue> mSensorQueue;
309 sp<MessageQueue> mMessageQueue;
Jeff Brown3b4049e2015-04-17 15:22:27 -0700310 jobject mReceiverWeakGlobal;
Peng Xua2958352016-01-26 18:42:17 -0800311 jfloatArray mFloatScratch;
312 jintArray mIntScratch;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800313public:
314 Receiver(const sp<SensorEventQueue>& sensorQueue,
315 const sp<MessageQueue>& messageQueue,
Peng Xua2958352016-01-26 18:42:17 -0800316 jobject receiverWeak) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800317 JNIEnv* env = AndroidRuntime::getJNIEnv();
318 mSensorQueue = sensorQueue;
319 mMessageQueue = messageQueue;
Jeff Brown3b4049e2015-04-17 15:22:27 -0700320 mReceiverWeakGlobal = env->NewGlobalRef(receiverWeak);
Peng Xua2958352016-01-26 18:42:17 -0800321
322 mIntScratch = (jintArray) env->NewGlobalRef(env->NewIntArray(16));
323 mFloatScratch = (jfloatArray) env->NewGlobalRef(env->NewFloatArray(16));
Mathias Agopiandb772d82013-01-31 19:31:12 -0800324 }
325 ~Receiver() {
326 JNIEnv* env = AndroidRuntime::getJNIEnv();
Jeff Brown3b4049e2015-04-17 15:22:27 -0700327 env->DeleteGlobalRef(mReceiverWeakGlobal);
Peng Xua2958352016-01-26 18:42:17 -0800328 env->DeleteGlobalRef(mFloatScratch);
329 env->DeleteGlobalRef(mIntScratch);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800330 }
331 sp<SensorEventQueue> getSensorEventQueue() const {
332 return mSensorQueue;
333 }
334
335 void destroy() {
336 mMessageQueue->getLooper()->removeFd( mSensorQueue->getFd() );
337 }
338
339private:
340 virtual void onFirstRef() {
341 LooperCallback::onFirstRef();
342 mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
343 ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
344 }
345
346 virtual int handleEvent(int fd, int events, void* data) {
347 JNIEnv* env = AndroidRuntime::getJNIEnv();
348 sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);
Jeff Brown3b4049e2015-04-17 15:22:27 -0700349 ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
350
Mathias Agopiandb772d82013-01-31 19:31:12 -0800351 ssize_t n;
352 ASensorEvent buffer[16];
353 while ((n = q->read(buffer, 16)) > 0) {
354 for (int i=0 ; i<n ; i++) {
Aravind Akella0288ca62014-07-28 14:53:44 -0700355 if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {
Jean-Baptiste Queru3c9c0912013-08-05 11:03:28 -0700356 // step-counter returns a uint64, but the java API only deals with floats
357 float value = float(buffer[i].u64.step_counter);
Peng Xua2958352016-01-26 18:42:17 -0800358 env->SetFloatArrayRegion(mFloatScratch, 0, 1, &value);
Peng Xua35b5532016-01-20 00:05:45 -0800359 } else if (buffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META) {
360 float value[2];
361 value[0] = buffer[i].dynamic_sensor_meta.connected ? 1.f: 0.f;
362 value[1] = float(buffer[i].dynamic_sensor_meta.handle);
Peng Xua2958352016-01-26 18:42:17 -0800363 env->SetFloatArrayRegion(mFloatScratch, 0, 2, value);
364 } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
365 env->SetIntArrayRegion(mIntScratch, 0, 14,
366 buffer[i].additional_info.data_int32);
367 env->SetFloatArrayRegion(mFloatScratch, 0, 14,
368 buffer[i].additional_info.data_float);
Jean-Baptiste Queru3c9c0912013-08-05 11:03:28 -0700369 } else {
Peng Xua2958352016-01-26 18:42:17 -0800370 env->SetFloatArrayRegion(mFloatScratch, 0, 16, buffer[i].data);
Jean-Baptiste Queru3c9c0912013-08-05 11:03:28 -0700371 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800372
Aravind Akellab4c76b12013-06-27 12:04:16 -0700373 if (buffer[i].type == SENSOR_TYPE_META_DATA) {
374 // This is a flush complete sensor event. Call dispatchFlushCompleteEvent
375 // method.
Jeff Brown3b4049e2015-04-17 15:22:27 -0700376 if (receiverObj.get()) {
377 env->CallVoidMethod(receiverObj.get(),
378 gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
379 buffer[i].meta_data.sensor);
380 }
Peng Xua2958352016-01-26 18:42:17 -0800381 } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
382 // This is a flush complete sensor event. Call dispatchAdditionalInfoEvent
383 // method.
384 if (receiverObj.get()) {
385 int type = buffer[i].additional_info.type;
386 int serial = buffer[i].additional_info.serial;
387 env->CallVoidMethod(receiverObj.get(),
388 gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent,
389 buffer[i].sensor,
390 type, serial,
391 mFloatScratch,
392 mIntScratch,
393 buffer[i].timestamp);
394 }
395 }else {
Etienne Le Grandaf805102014-05-16 12:21:41 -0700396 int8_t status;
397 switch (buffer[i].type) {
398 case SENSOR_TYPE_ORIENTATION:
399 case SENSOR_TYPE_MAGNETIC_FIELD:
400 case SENSOR_TYPE_ACCELEROMETER:
401 case SENSOR_TYPE_GYROSCOPE:
Aravind Akellaf38226a2015-06-23 10:32:16 -0700402 case SENSOR_TYPE_GRAVITY:
403 case SENSOR_TYPE_LINEAR_ACCELERATION:
Etienne Le Grandaf805102014-05-16 12:21:41 -0700404 status = buffer[i].vector.status;
405 break;
406 case SENSOR_TYPE_HEART_RATE:
407 status = buffer[i].heart_rate.status;
408 break;
409 default:
410 status = SENSOR_STATUS_ACCURACY_HIGH;
411 break;
412 }
Jeff Brown3b4049e2015-04-17 15:22:27 -0700413 if (receiverObj.get()) {
414 env->CallVoidMethod(receiverObj.get(),
415 gBaseEventQueueClassInfo.dispatchSensorEvent,
416 buffer[i].sensor,
Peng Xua2958352016-01-26 18:42:17 -0800417 mFloatScratch,
Jeff Brown3b4049e2015-04-17 15:22:27 -0700418 status,
419 buffer[i].timestamp);
420 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700421 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800422 if (env->ExceptionCheck()) {
Aravind Akella35187bd2014-02-11 18:44:42 -0800423 mSensorQueue->sendAck(buffer, n);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800424 ALOGE("Exception dispatching input event.");
425 return 1;
426 }
427 }
Aravind Akella35187bd2014-02-11 18:44:42 -0800428 mSensorQueue->sendAck(buffer, n);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800429 }
430 if (n<0 && n != -EAGAIN) {
431 // FIXME: error receiving events, what to do in this case?
432 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800433 return 1;
434 }
435};
436
Svet Ganovb9d71a62015-04-30 10:38:13 -0700437static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
Peng Xua2958352016-01-26 18:42:17 -0800438 jobject eventQWeak, jobject msgQ, jstring packageName, jint mode) {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700439 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
Aravind Akella88445992015-02-26 17:05:28 -0800440 ScopedUtfChars packageUtf(env, packageName);
441 String8 clientName(packageUtf.c_str());
Svet Ganovb9d71a62015-04-30 10:38:13 -0700442 sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443
Mathias Agopiandb772d82013-01-31 19:31:12 -0800444 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
445 if (messageQueue == NULL) {
446 jniThrowRuntimeException(env, "MessageQueue is not initialized.");
447 return 0;
Mathias Agopian0b6d77b2012-05-07 18:27:06 -0700448 }
Mathias Agopian1bf79782010-07-14 23:41:37 -0700449
Peng Xua2958352016-01-26 18:42:17 -0800450 sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak);
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800451 receiver->incStrong((void*)nativeInitSensorEventQueue);
Ashok Bhat4838e332014-01-03 14:37:19 +0000452 return jlong(receiver.get());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453}
454
Ashok Bhat4838e332014-01-03 14:37:19 +0000455static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us,
Aravind Akella88445992015-02-26 17:05:28 -0800456 jint maxBatchReportLatency) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800457 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
Aravind Akellab4c76b12013-06-27 12:04:16 -0700458 return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency,
Aravind Akella88445992015-02-26 17:05:28 -0800459 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460}
461
Ashok Bhat4838e332014-01-03 14:37:19 +0000462static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800463 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
464 return receiver->getSensorEventQueue()->disableSensor(handle);
465}
Mathias Agopian1bf79782010-07-14 23:41:37 -0700466
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700467static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jlong eventQ) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800468 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
469 receiver->destroy();
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800470 receiver->decStrong((void*)nativeInitSensorEventQueue);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800471}
Mathias Agopian1bf79782010-07-14 23:41:37 -0700472
Ashok Bhat4838e332014-01-03 14:37:19 +0000473static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jlong eventQ) {
Aravind Akellab4c76b12013-06-27 12:04:16 -0700474 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700475 return receiver->getSensorEventQueue()->flush();
Aravind Akellab4c76b12013-06-27 12:04:16 -0700476}
Mathias Agopiandb772d82013-01-31 19:31:12 -0800477
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700478static jint nativeInjectSensorData(JNIEnv *env, jclass clazz, jlong eventQ, jint handle,
479 jfloatArray values, jint accuracy, jlong timestamp) {
480 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
481 // Create a sensor_event from the above data which can be injected into the HAL.
482 ASensorEvent sensor_event;
483 memset(&sensor_event, 0, sizeof(sensor_event));
484 sensor_event.sensor = handle;
485 sensor_event.timestamp = timestamp;
486 env->GetFloatArrayRegion(values, 0, env->GetArrayLength(values), sensor_event.data);
487 return receiver->getSensorEventQueue()->injectSensorEvent(sensor_event);
488}
Mathias Agopiandb772d82013-01-31 19:31:12 -0800489//----------------------------------------------------------------------------
490
Daniel Micay76f6a862015-09-19 17:31:01 -0400491static const JNINativeMethod gSystemSensorManagerMethods[] = {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800492 {"nativeClassInit",
493 "()V",
494 (void*)nativeClassInit },
Svet Ganovb9d71a62015-04-30 10:38:13 -0700495 {"nativeCreate",
496 "(Ljava/lang/String;)J",
497 (void*)nativeCreate },
Mathias Agopiandb772d82013-01-31 19:31:12 -0800498
Aravind Akella516e40e2015-07-01 16:54:24 -0700499 {"nativeGetSensorAtIndex",
500 "(JLandroid/hardware/Sensor;I)Z",
501 (void*)nativeGetSensorAtIndex },
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700502
Peng Xua35b5532016-01-20 00:05:45 -0800503 {"nativeGetDynamicSensors",
504 "(JLjava/util/List;)V",
505 (void*)nativeGetDynamicSensors },
506
Aravind Akellad123b512015-06-29 12:35:51 -0700507 {"nativeIsDataInjectionEnabled",
508 "(J)Z",
Peng Xufa2672b2016-12-07 03:54:44 -0800509 (void*)nativeIsDataInjectionEnabled },
510
511 {"nativeCreateDirectChannel",
Peng Xu7d96fa02017-03-04 16:15:45 -0800512 "(JJIILandroid/hardware/HardwareBuffer;)I",
Peng Xufa2672b2016-12-07 03:54:44 -0800513 (void*)nativeCreateDirectChannel },
514
515 {"nativeDestroyDirectChannel",
516 "(JI)V",
517 (void*)nativeDestroyDirectChannel },
518
519 {"nativeConfigDirectChannel",
520 "(JIII)I",
521 (void*)nativeConfigDirectChannel },
Peng Xu1cfde252017-01-19 17:10:09 -0800522
523 {"nativeSetOperationParameter",
524 "(JI[F[I)I",
525 (void*)nativeSetOperationParameter },
Mathias Agopiandb772d82013-01-31 19:31:12 -0800526};
527
Daniel Micay76f6a862015-09-19 17:31:01 -0400528static const JNINativeMethod gBaseEventQueueMethods[] = {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800529 {"nativeInitBaseEventQueue",
Peng Xua2958352016-01-26 18:42:17 -0800530 "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;Ljava/lang/String;ILjava/lang/String;)J",
Svet Ganovb9d71a62015-04-30 10:38:13 -0700531 (void*)nativeInitSensorEventQueue },
Mathias Agopiandb772d82013-01-31 19:31:12 -0800532
533 {"nativeEnableSensor",
Aravind Akella88445992015-02-26 17:05:28 -0800534 "(JIII)I",
Mathias Agopiandb772d82013-01-31 19:31:12 -0800535 (void*)nativeEnableSensor },
536
537 {"nativeDisableSensor",
Ashok Bhat4838e332014-01-03 14:37:19 +0000538 "(JI)I",
Mathias Agopiandb772d82013-01-31 19:31:12 -0800539 (void*)nativeDisableSensor },
540
541 {"nativeDestroySensorEventQueue",
Ashok Bhat4838e332014-01-03 14:37:19 +0000542 "(J)V",
Mathias Agopiandb772d82013-01-31 19:31:12 -0800543 (void*)nativeDestroySensorEventQueue },
Aravind Akellab4c76b12013-06-27 12:04:16 -0700544
545 {"nativeFlushSensor",
Ashok Bhat4838e332014-01-03 14:37:19 +0000546 "(J)I",
Aravind Akellab4c76b12013-06-27 12:04:16 -0700547 (void*)nativeFlushSensor },
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700548
549 {"nativeInjectSensorData",
550 "(JI[FIJ)I",
551 (void*)nativeInjectSensorData },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800552};
553
Peng Xu4a4baef2016-03-16 16:56:39 -0700554} //unnamed namespace
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555
556int register_android_hardware_SensorManager(JNIEnv *env)
557{
Andreas Gampe987f79f2014-11-18 17:29:46 -0800558 RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager",
Mathias Agopiandb772d82013-01-31 19:31:12 -0800559 gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
560
Andreas Gampe987f79f2014-11-18 17:29:46 -0800561 RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager$BaseEventQueue",
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800562 gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));
Mathias Agopiandb772d82013-01-31 19:31:12 -0800563
Andreas Gampe987f79f2014-11-18 17:29:46 -0800564 gBaseEventQueueClassInfo.clazz = FindClassOrDie(env,
565 "android/hardware/SystemSensorManager$BaseEventQueue");
Mathias Agopiandb772d82013-01-31 19:31:12 -0800566
Andreas Gampe987f79f2014-11-18 17:29:46 -0800567 gBaseEventQueueClassInfo.dispatchSensorEvent = GetMethodIDOrDie(env,
568 gBaseEventQueueClassInfo.clazz, "dispatchSensorEvent", "(I[FIJ)V");
Mathias Agopiandb772d82013-01-31 19:31:12 -0800569
Andreas Gampe987f79f2014-11-18 17:29:46 -0800570 gBaseEventQueueClassInfo.dispatchFlushCompleteEvent = GetMethodIDOrDie(env,
571 gBaseEventQueueClassInfo.clazz, "dispatchFlushCompleteEvent", "(I)V");
Aravind Akellab4c76b12013-06-27 12:04:16 -0700572
Peng Xua2958352016-01-26 18:42:17 -0800573 gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent = GetMethodIDOrDie(env,
574 gBaseEventQueueClassInfo.clazz, "dispatchAdditionalInfoEvent", "(III[F[I)V");
575
Mathias Agopiandb772d82013-01-31 19:31:12 -0800576 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577}