blob: f4237d20f47ac96f2342670ce2e4948eacfb1b28 [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>
26#include <gui/Sensor.h>
27#include <gui/SensorEventQueue.h>
28#include <gui/SensorManager.h>
Mathias Agopiandb772d82013-01-31 19:31:12 -080029#include <utils/Log.h>
30#include <utils/Looper.h>
Peng Xua35b5532016-01-20 00:05:45 -080031#include <utils/Vector.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032
Peng Xud5ec5f92016-04-27 14:49:25 -070033#include <endian.h> // htobe64
34#include <map>
Andreas Gampe987f79f2014-11-18 17:29:46 -080035
Peng Xu4a4baef2016-03-16 16:56:39 -070036namespace {
37
38using namespace android;
39
40struct {
Mathias Agopiandb772d82013-01-31 19:31:12 -080041 jclass clazz;
42 jmethodID dispatchSensorEvent;
Aravind Akellab4c76b12013-06-27 12:04:16 -070043 jmethodID dispatchFlushCompleteEvent;
Peng Xua2958352016-01-26 18:42:17 -080044 jmethodID dispatchAdditionalInfoEvent;
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -080045} gBaseEventQueueClassInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047struct SensorOffsets
48{
Peng Xua35b5532016-01-20 00:05:45 -080049 jclass clazz;
Peng Xub85b1fe2016-04-20 21:28:33 -070050 //fields
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051 jfieldID name;
52 jfieldID vendor;
53 jfieldID version;
54 jfieldID handle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055 jfieldID range;
56 jfieldID resolution;
57 jfieldID power;
Mathias Agopian050b5622010-07-29 16:51:38 -070058 jfieldID minDelay;
Aravind Akellab4c76b12013-06-27 12:04:16 -070059 jfieldID fifoReservedEventCount;
60 jfieldID fifoMaxEventCount;
Aravind Akellacd9a7bb2014-04-07 22:55:21 +000061 jfieldID stringType;
62 jfieldID requiredPermission;
Aravind Akella2f8b9142014-05-12 14:39:29 -070063 jfieldID maxDelay;
Aravind Akella27900352014-06-03 19:20:42 -070064 jfieldID flags;
Peng Xub85b1fe2016-04-20 21:28:33 -070065 //methods
destradaa9ba7c1c2015-02-10 15:04:43 -080066 jmethodID setType;
Peng Xub85b1fe2016-04-20 21:28:33 -070067 jmethodID setUuid;
Peng Xua35b5532016-01-20 00:05:45 -080068 jmethodID init;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069} gSensorOffsets;
70
Peng Xua35b5532016-01-20 00:05:45 -080071struct ListOffsets {
72 jclass clazz;
73 jmethodID add;
74} gListOffsets;
Mathias Agopiandb772d82013-01-31 19:31:12 -080075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076/*
Peng Xu4a4baef2016-03-16 16:56:39 -070077 * nativeClassInit is not inteneded to be thread-safe. It should be called before other native...
78 * functions (except nativeCreate).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079 */
Mathias Agopiandb772d82013-01-31 19:31:12 -080080static void
81nativeClassInit (JNIEnv *_env, jclass _this)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082{
Peng Xua35b5532016-01-20 00:05:45 -080083 //android.hardware.Sensor
Mathias Agopiandb772d82013-01-31 19:31:12 -080084 SensorOffsets& sensorOffsets = gSensorOffsets;
Peng Xua35b5532016-01-20 00:05:45 -080085 jclass sensorClass = (jclass) _env->NewGlobalRef(_env->FindClass("android/hardware/Sensor"));
86 sensorOffsets.clazz = sensorClass;
Mathias Agopiandb772d82013-01-31 19:31:12 -080087 sensorOffsets.name = _env->GetFieldID(sensorClass, "mName", "Ljava/lang/String;");
88 sensorOffsets.vendor = _env->GetFieldID(sensorClass, "mVendor", "Ljava/lang/String;");
89 sensorOffsets.version = _env->GetFieldID(sensorClass, "mVersion", "I");
90 sensorOffsets.handle = _env->GetFieldID(sensorClass, "mHandle", "I");
Mathias Agopiandb772d82013-01-31 19:31:12 -080091 sensorOffsets.range = _env->GetFieldID(sensorClass, "mMaxRange", "F");
92 sensorOffsets.resolution = _env->GetFieldID(sensorClass, "mResolution","F");
93 sensorOffsets.power = _env->GetFieldID(sensorClass, "mPower", "F");
94 sensorOffsets.minDelay = _env->GetFieldID(sensorClass, "mMinDelay", "I");
Aravind Akellab4c76b12013-06-27 12:04:16 -070095 sensorOffsets.fifoReservedEventCount =
96 _env->GetFieldID(sensorClass, "mFifoReservedEventCount", "I");
97 sensorOffsets.fifoMaxEventCount = _env->GetFieldID(sensorClass, "mFifoMaxEventCount", "I");
Aravind Akellacd9a7bb2014-04-07 22:55:21 +000098 sensorOffsets.stringType = _env->GetFieldID(sensorClass, "mStringType", "Ljava/lang/String;");
99 sensorOffsets.requiredPermission = _env->GetFieldID(sensorClass, "mRequiredPermission",
100 "Ljava/lang/String;");
Aravind Akella2f8b9142014-05-12 14:39:29 -0700101 sensorOffsets.maxDelay = _env->GetFieldID(sensorClass, "mMaxDelay", "I");
Aravind Akella27900352014-06-03 19:20:42 -0700102 sensorOffsets.flags = _env->GetFieldID(sensorClass, "mFlags", "I");
Peng Xua35b5532016-01-20 00:05:45 -0800103
destradaa9ba7c1c2015-02-10 15:04:43 -0800104 sensorOffsets.setType = _env->GetMethodID(sensorClass, "setType", "(I)Z");
Peng Xub85b1fe2016-04-20 21:28:33 -0700105 sensorOffsets.setUuid = _env->GetMethodID(sensorClass, "setUuid", "(JJ)V");
Peng Xua35b5532016-01-20 00:05:45 -0800106 sensorOffsets.init = _env->GetMethodID(sensorClass, "<init>", "()V");
107
108 // java.util.List;
109 ListOffsets& listOffsets = gListOffsets;
110 jclass listClass = (jclass) _env->NewGlobalRef(_env->FindClass("java/util/List"));
111 listOffsets.clazz = listClass;
112 listOffsets.add = _env->GetMethodID(listClass, "add", "(Ljava/lang/Object;)Z");
destradaa9ba7c1c2015-02-10 15:04:43 -0800113}
114
115/**
116 * A key comparator predicate.
117 * It is used to intern strings associated with Sensor data.
118 * It defines a 'Strict weak ordering' for the interned strings.
119 */
120class InternedStringCompare {
121public:
122 bool operator()(const String8* string1, const String8* string2) const {
123 if (string1 == NULL) {
124 return string2 != NULL;
125 }
Aravind Akella88445992015-02-26 17:05:28 -0800126 if (string2 == NULL) {
127 return false;
128 }
destradaa9ba7c1c2015-02-10 15:04:43 -0800129 return string1->compare(*string2) < 0;
130 }
131};
132
133/**
134 * A localized interning mechanism for Sensor strings.
135 * We implement our own interning to avoid the overhead of using java.lang.String#intern().
136 * It is common that Vendor, StringType, and RequirePermission data is common between many of the
137 * Sensors, by interning the memory usage to represent Sensors is optimized.
138 */
139static jstring
140getInternedString(JNIEnv *env, const String8* string) {
141 static std::map<const String8*, jstring, InternedStringCompare> internedStrings;
142
143 jstring internedString;
144 std::map<const String8*, jstring>::iterator iterator = internedStrings.find(string);
145 if (iterator != internedStrings.end()) {
146 internedString = iterator->second;
147 } else {
148 jstring localString = env->NewStringUTF(string->string());
149 // we are implementing our own interning so expect these strings to be backed by global refs
150 internedString = (jstring) env->NewGlobalRef(localString);
151 internedStrings.insert(std::make_pair(string, internedString));
152 env->DeleteLocalRef(localString);
153 }
destradaa9ba7c1c2015-02-10 15:04:43 -0800154 return internedString;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155}
156
Svet Ganovb9d71a62015-04-30 10:38:13 -0700157static jlong
158nativeCreate
159(JNIEnv *env, jclass clazz, jstring opPackageName)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160{
Svet Ganovb9d71a62015-04-30 10:38:13 -0700161 ScopedUtfChars opPackageNameUtf(env, opPackageName);
Aravind Akella2af91d02015-07-29 18:39:52 -0700162 return (jlong) &SensorManager::getInstanceForPackage(String16(opPackageNameUtf.c_str()));
Svet Ganovb9d71a62015-04-30 10:38:13 -0700163}
164
Peng Xua35b5532016-01-20 00:05:45 -0800165static jobject
166translateNativeSensorToJavaSensor(JNIEnv *env, jobject sensor, const Sensor& nativeSensor) {
167 const SensorOffsets& sensorOffsets(gSensorOffsets);
168
169 if (sensor == NULL) {
170 // Sensor sensor = new Sensor();
171 sensor = env->NewObject(sensorOffsets.clazz, sensorOffsets.init, "");
172 }
173
174 if (sensor != NULL) {
175 jstring name = env->NewStringUTF(nativeSensor.getName().string());
176 jstring vendor = env->NewStringUTF(nativeSensor.getVendor().string());
177 jstring requiredPermission =
178 env->NewStringUTF(nativeSensor.getRequiredPermission().string());
179
180 env->SetObjectField(sensor, sensorOffsets.name, name);
181 env->SetObjectField(sensor, sensorOffsets.vendor, vendor);
182 env->SetIntField(sensor, sensorOffsets.version, nativeSensor.getVersion());
183 env->SetIntField(sensor, sensorOffsets.handle, nativeSensor.getHandle());
184 env->SetFloatField(sensor, sensorOffsets.range, nativeSensor.getMaxValue());
185 env->SetFloatField(sensor, sensorOffsets.resolution, nativeSensor.getResolution());
186 env->SetFloatField(sensor, sensorOffsets.power, nativeSensor.getPowerUsage());
187 env->SetIntField(sensor, sensorOffsets.minDelay, nativeSensor.getMinDelay());
188 env->SetIntField(sensor, sensorOffsets.fifoReservedEventCount,
189 nativeSensor.getFifoReservedEventCount());
190 env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount,
191 nativeSensor.getFifoMaxEventCount());
192 env->SetObjectField(sensor, sensorOffsets.requiredPermission,
193 requiredPermission);
194 env->SetIntField(sensor, sensorOffsets.maxDelay, nativeSensor.getMaxDelay());
195 env->SetIntField(sensor, sensorOffsets.flags, nativeSensor.getFlags());
Peng Xub85b1fe2016-04-20 21:28:33 -0700196
Peng Xua35b5532016-01-20 00:05:45 -0800197 if (env->CallBooleanMethod(sensor, sensorOffsets.setType, nativeSensor.getType())
198 == JNI_FALSE) {
199 jstring stringType = getInternedString(env, &nativeSensor.getStringType());
200 env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
201 }
Peng Xub85b1fe2016-04-20 21:28:33 -0700202
203 // java.util.UUID constructor UUID(long a, long b) assumes the two long inputs a and b
204 // correspond to first half and second half of the 16-byte stream in big-endian,
205 // respectively, if the byte stream is serialized according to RFC 4122 (Sec. 4.1.2).
206 //
207 // For Java UUID 12345678-90AB-CDEF-1122-334455667788, the byte stream will be
208 // (uint8_t) {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, ....} according RFC 4122.
209 //
210 // According to Java UUID constructor document, the long parameter a should be always
211 // 0x12345678980ABCDEF regardless of host machine endianess. Thus, htobe64 is used to
212 // convert int64_t read directly, which will be in host-endian, to the big-endian required
213 // by Java constructor.
214 const int64_t (&uuid)[2] = nativeSensor.getUuid().i64;
215 env->CallVoidMethod(sensor, sensorOffsets.setUuid, htobe64(uuid[0]), htobe64(uuid[1]));
Peng Xua35b5532016-01-20 00:05:45 -0800216 }
217 return sensor;
218}
219
Aravind Akella516e40e2015-07-01 16:54:24 -0700220static jboolean
221nativeGetSensorAtIndex(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensor, jint index)
Svet Ganovb9d71a62015-04-30 10:38:13 -0700222{
223 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224
Mathias Agopian1bf79782010-07-14 23:41:37 -0700225 Sensor const* const* sensorList;
Peng Xua08c9f52016-02-04 22:27:20 -0800226 ssize_t count = mgr->getSensorList(&sensorList);
227 if (ssize_t(index) >= count) {
Aravind Akella516e40e2015-07-01 16:54:24 -0700228 return false;
destradaa9ba7c1c2015-02-10 15:04:43 -0800229 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700230
Peng Xub85b1fe2016-04-20 21:28:33 -0700231 return translateNativeSensorToJavaSensor(env, sensor, *sensorList[index]) != NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232}
233
Peng Xua35b5532016-01-20 00:05:45 -0800234static void
235nativeGetDynamicSensors(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensorList) {
236
237 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
238 const ListOffsets& listOffsets(gListOffsets);
239
240 Vector<Sensor> nativeList;
241
242 mgr->getDynamicSensorList(nativeList);
243
244 ALOGI("DYNS native SensorManager.getDynamicSensorList return %d sensors", nativeList.size());
245 for (size_t i = 0; i < nativeList.size(); ++i) {
246 jobject sensor = translateNativeSensorToJavaSensor(env, NULL, nativeList[i]);
247 // add to list
248 env->CallBooleanMethod(sensorList, listOffsets.add, sensor);
249 }
250}
251
Aravind Akellad123b512015-06-29 12:35:51 -0700252static jboolean nativeIsDataInjectionEnabled(JNIEnv *_env, jclass _this, jlong sensorManager) {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700253 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
Aravind Akellad123b512015-06-29 12:35:51 -0700254 return mgr->isDataInjectionEnabled();
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700255}
256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257//----------------------------------------------------------------------------
Mathias Agopiandb772d82013-01-31 19:31:12 -0800258
259class Receiver : public LooperCallback {
260 sp<SensorEventQueue> mSensorQueue;
261 sp<MessageQueue> mMessageQueue;
Jeff Brown3b4049e2015-04-17 15:22:27 -0700262 jobject mReceiverWeakGlobal;
Peng Xua2958352016-01-26 18:42:17 -0800263 jfloatArray mFloatScratch;
264 jintArray mIntScratch;
Mathias Agopiandb772d82013-01-31 19:31:12 -0800265public:
266 Receiver(const sp<SensorEventQueue>& sensorQueue,
267 const sp<MessageQueue>& messageQueue,
Peng Xua2958352016-01-26 18:42:17 -0800268 jobject receiverWeak) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800269 JNIEnv* env = AndroidRuntime::getJNIEnv();
270 mSensorQueue = sensorQueue;
271 mMessageQueue = messageQueue;
Jeff Brown3b4049e2015-04-17 15:22:27 -0700272 mReceiverWeakGlobal = env->NewGlobalRef(receiverWeak);
Peng Xua2958352016-01-26 18:42:17 -0800273
274 mIntScratch = (jintArray) env->NewGlobalRef(env->NewIntArray(16));
275 mFloatScratch = (jfloatArray) env->NewGlobalRef(env->NewFloatArray(16));
Mathias Agopiandb772d82013-01-31 19:31:12 -0800276 }
277 ~Receiver() {
278 JNIEnv* env = AndroidRuntime::getJNIEnv();
Jeff Brown3b4049e2015-04-17 15:22:27 -0700279 env->DeleteGlobalRef(mReceiverWeakGlobal);
Peng Xua2958352016-01-26 18:42:17 -0800280 env->DeleteGlobalRef(mFloatScratch);
281 env->DeleteGlobalRef(mIntScratch);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800282 }
283 sp<SensorEventQueue> getSensorEventQueue() const {
284 return mSensorQueue;
285 }
286
287 void destroy() {
288 mMessageQueue->getLooper()->removeFd( mSensorQueue->getFd() );
289 }
290
291private:
292 virtual void onFirstRef() {
293 LooperCallback::onFirstRef();
294 mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
295 ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
296 }
297
298 virtual int handleEvent(int fd, int events, void* data) {
299 JNIEnv* env = AndroidRuntime::getJNIEnv();
300 sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);
Jeff Brown3b4049e2015-04-17 15:22:27 -0700301 ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
302
Mathias Agopiandb772d82013-01-31 19:31:12 -0800303 ssize_t n;
304 ASensorEvent buffer[16];
305 while ((n = q->read(buffer, 16)) > 0) {
306 for (int i=0 ; i<n ; i++) {
Aravind Akella0288ca62014-07-28 14:53:44 -0700307 if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {
Jean-Baptiste Queru3c9c0912013-08-05 11:03:28 -0700308 // step-counter returns a uint64, but the java API only deals with floats
309 float value = float(buffer[i].u64.step_counter);
Peng Xua2958352016-01-26 18:42:17 -0800310 env->SetFloatArrayRegion(mFloatScratch, 0, 1, &value);
Peng Xua35b5532016-01-20 00:05:45 -0800311 } else if (buffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META) {
312 float value[2];
313 value[0] = buffer[i].dynamic_sensor_meta.connected ? 1.f: 0.f;
314 value[1] = float(buffer[i].dynamic_sensor_meta.handle);
Peng Xua2958352016-01-26 18:42:17 -0800315 env->SetFloatArrayRegion(mFloatScratch, 0, 2, value);
316 } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
317 env->SetIntArrayRegion(mIntScratch, 0, 14,
318 buffer[i].additional_info.data_int32);
319 env->SetFloatArrayRegion(mFloatScratch, 0, 14,
320 buffer[i].additional_info.data_float);
Jean-Baptiste Queru3c9c0912013-08-05 11:03:28 -0700321 } else {
Peng Xua2958352016-01-26 18:42:17 -0800322 env->SetFloatArrayRegion(mFloatScratch, 0, 16, buffer[i].data);
Jean-Baptiste Queru3c9c0912013-08-05 11:03:28 -0700323 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800324
Aravind Akellab4c76b12013-06-27 12:04:16 -0700325 if (buffer[i].type == SENSOR_TYPE_META_DATA) {
326 // This is a flush complete sensor event. Call dispatchFlushCompleteEvent
327 // method.
Jeff Brown3b4049e2015-04-17 15:22:27 -0700328 if (receiverObj.get()) {
329 env->CallVoidMethod(receiverObj.get(),
330 gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
331 buffer[i].meta_data.sensor);
332 }
Peng Xua2958352016-01-26 18:42:17 -0800333 } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
334 // This is a flush complete sensor event. Call dispatchAdditionalInfoEvent
335 // method.
336 if (receiverObj.get()) {
337 int type = buffer[i].additional_info.type;
338 int serial = buffer[i].additional_info.serial;
339 env->CallVoidMethod(receiverObj.get(),
340 gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent,
341 buffer[i].sensor,
342 type, serial,
343 mFloatScratch,
344 mIntScratch,
345 buffer[i].timestamp);
346 }
347 }else {
Etienne Le Grandaf805102014-05-16 12:21:41 -0700348 int8_t status;
349 switch (buffer[i].type) {
350 case SENSOR_TYPE_ORIENTATION:
351 case SENSOR_TYPE_MAGNETIC_FIELD:
352 case SENSOR_TYPE_ACCELEROMETER:
353 case SENSOR_TYPE_GYROSCOPE:
Aravind Akellaf38226a2015-06-23 10:32:16 -0700354 case SENSOR_TYPE_GRAVITY:
355 case SENSOR_TYPE_LINEAR_ACCELERATION:
Etienne Le Grandaf805102014-05-16 12:21:41 -0700356 status = buffer[i].vector.status;
357 break;
358 case SENSOR_TYPE_HEART_RATE:
359 status = buffer[i].heart_rate.status;
360 break;
361 default:
362 status = SENSOR_STATUS_ACCURACY_HIGH;
363 break;
364 }
Jeff Brown3b4049e2015-04-17 15:22:27 -0700365 if (receiverObj.get()) {
366 env->CallVoidMethod(receiverObj.get(),
367 gBaseEventQueueClassInfo.dispatchSensorEvent,
368 buffer[i].sensor,
Peng Xua2958352016-01-26 18:42:17 -0800369 mFloatScratch,
Jeff Brown3b4049e2015-04-17 15:22:27 -0700370 status,
371 buffer[i].timestamp);
372 }
Aravind Akellab4c76b12013-06-27 12:04:16 -0700373 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800374 if (env->ExceptionCheck()) {
Aravind Akella35187bd2014-02-11 18:44:42 -0800375 mSensorQueue->sendAck(buffer, n);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800376 ALOGE("Exception dispatching input event.");
377 return 1;
378 }
379 }
Aravind Akella35187bd2014-02-11 18:44:42 -0800380 mSensorQueue->sendAck(buffer, n);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800381 }
382 if (n<0 && n != -EAGAIN) {
383 // FIXME: error receiving events, what to do in this case?
384 }
Mathias Agopiandb772d82013-01-31 19:31:12 -0800385 return 1;
386 }
387};
388
Svet Ganovb9d71a62015-04-30 10:38:13 -0700389static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
Peng Xua2958352016-01-26 18:42:17 -0800390 jobject eventQWeak, jobject msgQ, jstring packageName, jint mode) {
Svet Ganovb9d71a62015-04-30 10:38:13 -0700391 SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
Aravind Akella88445992015-02-26 17:05:28 -0800392 ScopedUtfChars packageUtf(env, packageName);
393 String8 clientName(packageUtf.c_str());
Svet Ganovb9d71a62015-04-30 10:38:13 -0700394 sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395
Mathias Agopiandb772d82013-01-31 19:31:12 -0800396 sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
397 if (messageQueue == NULL) {
398 jniThrowRuntimeException(env, "MessageQueue is not initialized.");
399 return 0;
Mathias Agopian0b6d77b2012-05-07 18:27:06 -0700400 }
Mathias Agopian1bf79782010-07-14 23:41:37 -0700401
Peng Xua2958352016-01-26 18:42:17 -0800402 sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak);
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800403 receiver->incStrong((void*)nativeInitSensorEventQueue);
Ashok Bhat4838e332014-01-03 14:37:19 +0000404 return jlong(receiver.get());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405}
406
Ashok Bhat4838e332014-01-03 14:37:19 +0000407static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us,
Aravind Akella88445992015-02-26 17:05:28 -0800408 jint maxBatchReportLatency) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800409 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
Aravind Akellab4c76b12013-06-27 12:04:16 -0700410 return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency,
Aravind Akella88445992015-02-26 17:05:28 -0800411 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412}
413
Ashok Bhat4838e332014-01-03 14:37:19 +0000414static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800415 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
416 return receiver->getSensorEventQueue()->disableSensor(handle);
417}
Mathias Agopian1bf79782010-07-14 23:41:37 -0700418
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700419static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jlong eventQ) {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800420 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
421 receiver->destroy();
Mathias Agopianb1d90c82013-03-06 17:45:42 -0800422 receiver->decStrong((void*)nativeInitSensorEventQueue);
Mathias Agopiandb772d82013-01-31 19:31:12 -0800423}
Mathias Agopian1bf79782010-07-14 23:41:37 -0700424
Ashok Bhat4838e332014-01-03 14:37:19 +0000425static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jlong eventQ) {
Aravind Akellab4c76b12013-06-27 12:04:16 -0700426 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
Aravind Akella4bdc37d2013-10-01 17:58:35 -0700427 return receiver->getSensorEventQueue()->flush();
Aravind Akellab4c76b12013-06-27 12:04:16 -0700428}
Mathias Agopiandb772d82013-01-31 19:31:12 -0800429
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700430static jint nativeInjectSensorData(JNIEnv *env, jclass clazz, jlong eventQ, jint handle,
431 jfloatArray values, jint accuracy, jlong timestamp) {
432 sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
433 // Create a sensor_event from the above data which can be injected into the HAL.
434 ASensorEvent sensor_event;
435 memset(&sensor_event, 0, sizeof(sensor_event));
436 sensor_event.sensor = handle;
437 sensor_event.timestamp = timestamp;
438 env->GetFloatArrayRegion(values, 0, env->GetArrayLength(values), sensor_event.data);
439 return receiver->getSensorEventQueue()->injectSensorEvent(sensor_event);
440}
Mathias Agopiandb772d82013-01-31 19:31:12 -0800441//----------------------------------------------------------------------------
442
Daniel Micay76f6a862015-09-19 17:31:01 -0400443static const JNINativeMethod gSystemSensorManagerMethods[] = {
Mathias Agopiandb772d82013-01-31 19:31:12 -0800444 {"nativeClassInit",
445 "()V",
446 (void*)nativeClassInit },
Svet Ganovb9d71a62015-04-30 10:38:13 -0700447 {"nativeCreate",
448 "(Ljava/lang/String;)J",
449 (void*)nativeCreate },
Mathias Agopiandb772d82013-01-31 19:31:12 -0800450
Aravind Akella516e40e2015-07-01 16:54:24 -0700451 {"nativeGetSensorAtIndex",
452 "(JLandroid/hardware/Sensor;I)Z",
453 (void*)nativeGetSensorAtIndex },
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700454
Peng Xua35b5532016-01-20 00:05:45 -0800455 {"nativeGetDynamicSensors",
456 "(JLjava/util/List;)V",
457 (void*)nativeGetDynamicSensors },
458
Aravind Akellad123b512015-06-29 12:35:51 -0700459 {"nativeIsDataInjectionEnabled",
460 "(J)Z",
461 (void*)nativeIsDataInjectionEnabled},
Mathias Agopiandb772d82013-01-31 19:31:12 -0800462};
463
Daniel Micay76f6a862015-09-19 17:31:01 -0400464static const JNINativeMethod gBaseEventQueueMethods[] = {
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800465 {"nativeInitBaseEventQueue",
Peng Xua2958352016-01-26 18:42:17 -0800466 "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;Ljava/lang/String;ILjava/lang/String;)J",
Svet Ganovb9d71a62015-04-30 10:38:13 -0700467 (void*)nativeInitSensorEventQueue },
Mathias Agopiandb772d82013-01-31 19:31:12 -0800468
469 {"nativeEnableSensor",
Aravind Akella88445992015-02-26 17:05:28 -0800470 "(JIII)I",
Mathias Agopiandb772d82013-01-31 19:31:12 -0800471 (void*)nativeEnableSensor },
472
473 {"nativeDisableSensor",
Ashok Bhat4838e332014-01-03 14:37:19 +0000474 "(JI)I",
Mathias Agopiandb772d82013-01-31 19:31:12 -0800475 (void*)nativeDisableSensor },
476
477 {"nativeDestroySensorEventQueue",
Ashok Bhat4838e332014-01-03 14:37:19 +0000478 "(J)V",
Mathias Agopiandb772d82013-01-31 19:31:12 -0800479 (void*)nativeDestroySensorEventQueue },
Aravind Akellab4c76b12013-06-27 12:04:16 -0700480
481 {"nativeFlushSensor",
Ashok Bhat4838e332014-01-03 14:37:19 +0000482 "(J)I",
Aravind Akellab4c76b12013-06-27 12:04:16 -0700483 (void*)nativeFlushSensor },
Aravind Akella18ebf732b2015-04-20 17:39:51 -0700484
485 {"nativeInjectSensorData",
486 "(JI[FIJ)I",
487 (void*)nativeInjectSensorData },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800488};
489
Peng Xu4a4baef2016-03-16 16:56:39 -0700490} //unnamed namespace
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800491
492int register_android_hardware_SensorManager(JNIEnv *env)
493{
Andreas Gampe987f79f2014-11-18 17:29:46 -0800494 RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager",
Mathias Agopiandb772d82013-01-31 19:31:12 -0800495 gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
496
Andreas Gampe987f79f2014-11-18 17:29:46 -0800497 RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager$BaseEventQueue",
Jaikumar Ganesh9a8df4d2013-02-12 16:31:32 -0800498 gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));
Mathias Agopiandb772d82013-01-31 19:31:12 -0800499
Andreas Gampe987f79f2014-11-18 17:29:46 -0800500 gBaseEventQueueClassInfo.clazz = FindClassOrDie(env,
501 "android/hardware/SystemSensorManager$BaseEventQueue");
Mathias Agopiandb772d82013-01-31 19:31:12 -0800502
Andreas Gampe987f79f2014-11-18 17:29:46 -0800503 gBaseEventQueueClassInfo.dispatchSensorEvent = GetMethodIDOrDie(env,
504 gBaseEventQueueClassInfo.clazz, "dispatchSensorEvent", "(I[FIJ)V");
Mathias Agopiandb772d82013-01-31 19:31:12 -0800505
Andreas Gampe987f79f2014-11-18 17:29:46 -0800506 gBaseEventQueueClassInfo.dispatchFlushCompleteEvent = GetMethodIDOrDie(env,
507 gBaseEventQueueClassInfo.clazz, "dispatchFlushCompleteEvent", "(I)V");
Aravind Akellab4c76b12013-06-27 12:04:16 -0700508
Peng Xua2958352016-01-26 18:42:17 -0800509 gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent = GetMethodIDOrDie(env,
510 gBaseEventQueueClassInfo.clazz, "dispatchAdditionalInfoEvent", "(III[F[I)V");
511
Mathias Agopiandb772d82013-01-31 19:31:12 -0800512 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800513}