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 
17 #define LOG_TAG "SensorManager"
18 
19 #include <map>
20 
21 #include <ScopedUtfChars.h>
22 #include <ScopedLocalRef.h>
23 
24 #include <utils/Log.h>
25 #include <utils/Looper.h>
26 
27 #include <gui/Sensor.h>
28 #include <gui/SensorManager.h>
29 #include <gui/SensorEventQueue.h>
30 
31 #include "jni.h"
32 #include "JNIHelp.h"
33 #include "android_os_MessageQueue.h"
34 #include <android_runtime/AndroidRuntime.h>
35 
36 #include "core_jni_helpers.h"
37 
38 static struct {
39     jclass clazz;
40     jmethodID dispatchSensorEvent;
41     jmethodID dispatchFlushCompleteEvent;
42 } gBaseEventQueueClassInfo;
43 
44 namespace android {
45 
46 struct SensorOffsets
47 {
48     jfieldID    name;
49     jfieldID    vendor;
50     jfieldID    version;
51     jfieldID    handle;
52     jfieldID    range;
53     jfieldID    resolution;
54     jfieldID    power;
55     jfieldID    minDelay;
56     jfieldID    fifoReservedEventCount;
57     jfieldID    fifoMaxEventCount;
58     jfieldID    stringType;
59     jfieldID    requiredPermission;
60     jfieldID    maxDelay;
61     jfieldID    flags;
62     jmethodID   setType;
63 } gSensorOffsets;
64 
65 
66 /*
67  * The method below are not thread-safe and not intended to be
68  */
69 
70 static void
nativeClassInit(JNIEnv * _env,jclass _this)71 nativeClassInit (JNIEnv *_env, jclass _this)
72 {
73     jclass sensorClass = _env->FindClass("android/hardware/Sensor");
74     SensorOffsets& sensorOffsets = gSensorOffsets;
75     sensorOffsets.name        = _env->GetFieldID(sensorClass, "mName",      "Ljava/lang/String;");
76     sensorOffsets.vendor      = _env->GetFieldID(sensorClass, "mVendor",    "Ljava/lang/String;");
77     sensorOffsets.version     = _env->GetFieldID(sensorClass, "mVersion",   "I");
78     sensorOffsets.handle      = _env->GetFieldID(sensorClass, "mHandle",    "I");
79     sensorOffsets.range       = _env->GetFieldID(sensorClass, "mMaxRange",  "F");
80     sensorOffsets.resolution  = _env->GetFieldID(sensorClass, "mResolution","F");
81     sensorOffsets.power       = _env->GetFieldID(sensorClass, "mPower",     "F");
82     sensorOffsets.minDelay    = _env->GetFieldID(sensorClass, "mMinDelay",  "I");
83     sensorOffsets.fifoReservedEventCount =
84             _env->GetFieldID(sensorClass, "mFifoReservedEventCount",  "I");
85     sensorOffsets.fifoMaxEventCount = _env->GetFieldID(sensorClass, "mFifoMaxEventCount",  "I");
86     sensorOffsets.stringType = _env->GetFieldID(sensorClass, "mStringType", "Ljava/lang/String;");
87     sensorOffsets.requiredPermission = _env->GetFieldID(sensorClass, "mRequiredPermission",
88                                                         "Ljava/lang/String;");
89     sensorOffsets.maxDelay    = _env->GetFieldID(sensorClass, "mMaxDelay",  "I");
90     sensorOffsets.flags = _env->GetFieldID(sensorClass, "mFlags",  "I");
91     sensorOffsets.setType = _env->GetMethodID(sensorClass, "setType", "(I)Z");
92 }
93 
94 /**
95  * A key comparator predicate.
96  * It is used to intern strings associated with Sensor data.
97  * It defines a 'Strict weak ordering' for the interned strings.
98  */
99 class InternedStringCompare {
100 public:
operator ()(const String8 * string1,const String8 * string2) const101     bool operator()(const String8* string1, const String8* string2) const {
102         if (string1 == NULL) {
103             return string2 != NULL;
104         }
105         if (string2 == NULL) {
106             return false;
107         }
108         return string1->compare(*string2) < 0;
109     }
110 };
111 
112 /**
113  * A localized interning mechanism for Sensor strings.
114  * We implement our own interning to avoid the overhead of using java.lang.String#intern().
115  * It is common that Vendor, StringType, and RequirePermission data is common between many of the
116  * Sensors, by interning the memory usage to represent Sensors is optimized.
117  */
118 static jstring
getInternedString(JNIEnv * env,const String8 * string)119 getInternedString(JNIEnv *env, const String8* string) {
120     static std::map<const String8*, jstring, InternedStringCompare> internedStrings;
121 
122     jstring internedString;
123     std::map<const String8*, jstring>::iterator iterator = internedStrings.find(string);
124     if (iterator != internedStrings.end()) {
125         internedString = iterator->second;
126     } else {
127         jstring localString = env->NewStringUTF(string->string());
128         // we are implementing our own interning so expect these strings to be backed by global refs
129         internedString = (jstring) env->NewGlobalRef(localString);
130         internedStrings.insert(std::make_pair(string, internedString));
131         env->DeleteLocalRef(localString);
132     }
133     return internedString;
134 }
135 
136 static jlong
nativeCreate(JNIEnv * env,jclass clazz,jstring opPackageName)137 nativeCreate
138 (JNIEnv *env, jclass clazz, jstring opPackageName)
139 {
140     ScopedUtfChars opPackageNameUtf(env, opPackageName);
141     return (jlong) new SensorManager(String16(opPackageNameUtf.c_str()));
142 }
143 
144 static jboolean
nativeGetSensorAtIndex(JNIEnv * env,jclass clazz,jlong sensorManager,jobject sensor,jint index)145 nativeGetSensorAtIndex(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensor, jint index)
146 {
147     SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
148 
149     Sensor const* const* sensorList;
150     size_t count = mgr->getSensorList(&sensorList);
151     if (size_t(index) >= count) {
152         return false;
153     }
154 
155     Sensor const* const list = sensorList[index];
156     const SensorOffsets& sensorOffsets(gSensorOffsets);
157     jstring name = getInternedString(env, &list->getName());
158     jstring vendor = getInternedString(env, &list->getVendor());
159     jstring requiredPermission = getInternedString(env, &list->getRequiredPermission());
160     env->SetObjectField(sensor, sensorOffsets.name,      name);
161     env->SetObjectField(sensor, sensorOffsets.vendor,    vendor);
162     env->SetIntField(sensor, sensorOffsets.version,      list->getVersion());
163     env->SetIntField(sensor, sensorOffsets.handle,       list->getHandle());
164     env->SetFloatField(sensor, sensorOffsets.range,      list->getMaxValue());
165     env->SetFloatField(sensor, sensorOffsets.resolution, list->getResolution());
166     env->SetFloatField(sensor, sensorOffsets.power,      list->getPowerUsage());
167     env->SetIntField(sensor, sensorOffsets.minDelay,     list->getMinDelay());
168     env->SetIntField(sensor, sensorOffsets.fifoReservedEventCount,
169                      list->getFifoReservedEventCount());
170     env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount,
171                      list->getFifoMaxEventCount());
172     env->SetObjectField(sensor, sensorOffsets.requiredPermission,
173                         requiredPermission);
174     env->SetIntField(sensor, sensorOffsets.maxDelay, list->getMaxDelay());
175     env->SetIntField(sensor, sensorOffsets.flags, list->getFlags());
176     if (env->CallBooleanMethod(sensor, sensorOffsets.setType, list->getType()) == JNI_FALSE) {
177         jstring stringType = getInternedString(env, &list->getStringType());
178         env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
179     }
180     return true;
181 }
182 
nativeIsDataInjectionEnabled(JNIEnv * _env,jclass _this,jlong sensorManager)183 static jboolean nativeIsDataInjectionEnabled(JNIEnv *_env, jclass _this, jlong sensorManager) {
184     SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
185     return mgr->isDataInjectionEnabled();
186 }
187 
188 //----------------------------------------------------------------------------
189 
190 class Receiver : public LooperCallback {
191     sp<SensorEventQueue> mSensorQueue;
192     sp<MessageQueue> mMessageQueue;
193     jobject mReceiverWeakGlobal;
194     jfloatArray mScratch;
195 public:
Receiver(const sp<SensorEventQueue> & sensorQueue,const sp<MessageQueue> & messageQueue,jobject receiverWeak,jfloatArray scratch)196     Receiver(const sp<SensorEventQueue>& sensorQueue,
197             const sp<MessageQueue>& messageQueue,
198             jobject receiverWeak, jfloatArray scratch) {
199         JNIEnv* env = AndroidRuntime::getJNIEnv();
200         mSensorQueue = sensorQueue;
201         mMessageQueue = messageQueue;
202         mReceiverWeakGlobal = env->NewGlobalRef(receiverWeak);
203         mScratch = (jfloatArray)env->NewGlobalRef(scratch);
204     }
~Receiver()205     ~Receiver() {
206         JNIEnv* env = AndroidRuntime::getJNIEnv();
207         env->DeleteGlobalRef(mReceiverWeakGlobal);
208         env->DeleteGlobalRef(mScratch);
209     }
getSensorEventQueue() const210     sp<SensorEventQueue> getSensorEventQueue() const {
211         return mSensorQueue;
212     }
213 
destroy()214     void destroy() {
215         mMessageQueue->getLooper()->removeFd( mSensorQueue->getFd() );
216     }
217 
218 private:
onFirstRef()219     virtual void onFirstRef() {
220         LooperCallback::onFirstRef();
221         mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
222                 ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
223     }
224 
handleEvent(int fd,int events,void * data)225     virtual int handleEvent(int fd, int events, void* data) {
226         JNIEnv* env = AndroidRuntime::getJNIEnv();
227         sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);
228         ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
229 
230         ssize_t n;
231         ASensorEvent buffer[16];
232         while ((n = q->read(buffer, 16)) > 0) {
233             for (int i=0 ; i<n ; i++) {
234                 if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {
235                     // step-counter returns a uint64, but the java API only deals with floats
236                     float value = float(buffer[i].u64.step_counter);
237                     env->SetFloatArrayRegion(mScratch, 0, 1, &value);
238                 } else {
239                     env->SetFloatArrayRegion(mScratch, 0, 16, buffer[i].data);
240                 }
241 
242                 if (buffer[i].type == SENSOR_TYPE_META_DATA) {
243                     // This is a flush complete sensor event. Call dispatchFlushCompleteEvent
244                     // method.
245                     if (receiverObj.get()) {
246                         env->CallVoidMethod(receiverObj.get(),
247                                             gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
248                                             buffer[i].meta_data.sensor);
249                     }
250                 } else {
251                     int8_t status;
252                     switch (buffer[i].type) {
253                     case SENSOR_TYPE_ORIENTATION:
254                     case SENSOR_TYPE_MAGNETIC_FIELD:
255                     case SENSOR_TYPE_ACCELEROMETER:
256                     case SENSOR_TYPE_GYROSCOPE:
257                     case SENSOR_TYPE_GRAVITY:
258                     case SENSOR_TYPE_LINEAR_ACCELERATION:
259                         status = buffer[i].vector.status;
260                         break;
261                     case SENSOR_TYPE_HEART_RATE:
262                         status = buffer[i].heart_rate.status;
263                         break;
264                     default:
265                         status = SENSOR_STATUS_ACCURACY_HIGH;
266                         break;
267                     }
268                     if (receiverObj.get()) {
269                         env->CallVoidMethod(receiverObj.get(),
270                                             gBaseEventQueueClassInfo.dispatchSensorEvent,
271                                             buffer[i].sensor,
272                                             mScratch,
273                                             status,
274                                             buffer[i].timestamp);
275                     }
276                 }
277                 if (env->ExceptionCheck()) {
278                     mSensorQueue->sendAck(buffer, n);
279                     ALOGE("Exception dispatching input event.");
280                     return 1;
281                 }
282             }
283             mSensorQueue->sendAck(buffer, n);
284         }
285         if (n<0 && n != -EAGAIN) {
286             // FIXME: error receiving events, what to do in this case?
287         }
288         return 1;
289     }
290 };
291 
nativeInitSensorEventQueue(JNIEnv * env,jclass clazz,jlong sensorManager,jobject eventQWeak,jobject msgQ,jfloatArray scratch,jstring packageName,jint mode)292 static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
293         jobject eventQWeak, jobject msgQ, jfloatArray scratch, jstring packageName, jint mode) {
294     SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
295     ScopedUtfChars packageUtf(env, packageName);
296     String8 clientName(packageUtf.c_str());
297     sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode));
298 
299     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
300     if (messageQueue == NULL) {
301         jniThrowRuntimeException(env, "MessageQueue is not initialized.");
302         return 0;
303     }
304 
305     sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak, scratch);
306     receiver->incStrong((void*)nativeInitSensorEventQueue);
307     return jlong(receiver.get());
308 }
309 
nativeEnableSensor(JNIEnv * env,jclass clazz,jlong eventQ,jint handle,jint rate_us,jint maxBatchReportLatency)310 static jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us,
311                                jint maxBatchReportLatency) {
312     sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
313     return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency,
314                                                          0);
315 }
316 
nativeDisableSensor(JNIEnv * env,jclass clazz,jlong eventQ,jint handle)317 static jint nativeDisableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle) {
318     sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
319     return receiver->getSensorEventQueue()->disableSensor(handle);
320 }
321 
nativeDestroySensorEventQueue(JNIEnv * env,jclass clazz,jlong eventQ)322 static void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jlong eventQ) {
323     sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
324     receiver->destroy();
325     receiver->decStrong((void*)nativeInitSensorEventQueue);
326 }
327 
nativeFlushSensor(JNIEnv * env,jclass clazz,jlong eventQ)328 static jint nativeFlushSensor(JNIEnv *env, jclass clazz, jlong eventQ) {
329     sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
330     return receiver->getSensorEventQueue()->flush();
331 }
332 
nativeInjectSensorData(JNIEnv * env,jclass clazz,jlong eventQ,jint handle,jfloatArray values,jint accuracy,jlong timestamp)333 static jint nativeInjectSensorData(JNIEnv *env, jclass clazz, jlong eventQ, jint handle,
334         jfloatArray values, jint accuracy, jlong timestamp) {
335     sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
336     // Create a sensor_event from the above data which can be injected into the HAL.
337     ASensorEvent sensor_event;
338     memset(&sensor_event, 0, sizeof(sensor_event));
339     sensor_event.sensor = handle;
340     sensor_event.timestamp = timestamp;
341     env->GetFloatArrayRegion(values, 0, env->GetArrayLength(values), sensor_event.data);
342     return receiver->getSensorEventQueue()->injectSensorEvent(sensor_event);
343 }
344 //----------------------------------------------------------------------------
345 
346 static JNINativeMethod gSystemSensorManagerMethods[] = {
347     {"nativeClassInit",
348             "()V",
349             (void*)nativeClassInit },
350     {"nativeCreate",
351              "(Ljava/lang/String;)J",
352              (void*)nativeCreate },
353 
354     {"nativeGetSensorAtIndex",
355             "(JLandroid/hardware/Sensor;I)Z",
356             (void*)nativeGetSensorAtIndex },
357 
358     {"nativeIsDataInjectionEnabled",
359             "(J)Z",
360             (void*)nativeIsDataInjectionEnabled},
361 };
362 
363 static JNINativeMethod gBaseEventQueueMethods[] = {
364     {"nativeInitBaseEventQueue",
365              "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;[FLjava/lang/String;ILjava/lang/String;)J",
366              (void*)nativeInitSensorEventQueue },
367 
368     {"nativeEnableSensor",
369             "(JIII)I",
370             (void*)nativeEnableSensor },
371 
372     {"nativeDisableSensor",
373             "(JI)I",
374             (void*)nativeDisableSensor },
375 
376     {"nativeDestroySensorEventQueue",
377             "(J)V",
378             (void*)nativeDestroySensorEventQueue },
379 
380     {"nativeFlushSensor",
381             "(J)I",
382             (void*)nativeFlushSensor },
383 
384     {"nativeInjectSensorData",
385             "(JI[FIJ)I",
386             (void*)nativeInjectSensorData },
387 };
388 
389 }; // namespace android
390 
391 using namespace android;
392 
register_android_hardware_SensorManager(JNIEnv * env)393 int register_android_hardware_SensorManager(JNIEnv *env)
394 {
395     RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager",
396             gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
397 
398     RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager$BaseEventQueue",
399             gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));
400 
401     gBaseEventQueueClassInfo.clazz = FindClassOrDie(env,
402             "android/hardware/SystemSensorManager$BaseEventQueue");
403 
404     gBaseEventQueueClassInfo.dispatchSensorEvent = GetMethodIDOrDie(env,
405             gBaseEventQueueClassInfo.clazz, "dispatchSensorEvent", "(I[FIJ)V");
406 
407     gBaseEventQueueClassInfo.dispatchFlushCompleteEvent = GetMethodIDOrDie(env,
408             gBaseEventQueueClassInfo.clazz, "dispatchFlushCompleteEvent", "(I)V");
409 
410     return 0;
411 }
412