19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright 2008, The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
16270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood#define LOG_TAG "SensorManager"
17270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood
182279b2534272282a5b5152723235da397e49195cSteven Moreland#include <nativehelper/JNIHelp.h>
19d5ec5f919dc835ca302d97c3cdc8f5b11f0584f0Peng Xu#include "android_os_MessageQueue.h"
20d5ec5f919dc835ca302d97c3cdc8f5b11f0584f0Peng Xu#include "core_jni_helpers.h"
21d5ec5f919dc835ca302d97c3cdc8f5b11f0584f0Peng Xu#include "jni.h"
229ba7c1c17567c19f0187d73cdca55ca99590674edestradaa
232279b2534272282a5b5152723235da397e49195cSteven Moreland#include <nativehelper/ScopedUtfChars.h>
242279b2534272282a5b5152723235da397e49195cSteven Moreland#include <nativehelper/ScopedLocalRef.h>
25d5ec5f919dc835ca302d97c3cdc8f5b11f0584f0Peng Xu#include <android_runtime/AndroidRuntime.h>
267d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu#include <android_runtime/android_hardware_HardwareBuffer.h>
275f73ab7e2a591d45b67a7aaf1b26cc9dcfe58502Jesse Hall#include <vndk/hardware_buffer.h>
28caf8930960ae68d5be2a8952cc127bf3f154f433Mathias Agopian#include <sensor/Sensor.h>
29caf8930960ae68d5be2a8952cc127bf3f154f433Mathias Agopian#include <sensor/SensorEventQueue.h>
30caf8930960ae68d5be2a8952cc127bf3f154f433Mathias Agopian#include <sensor/SensorManager.h>
31fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu#include <cutils/native_handle.h>
32db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian#include <utils/Log.h>
33db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian#include <utils/Looper.h>
34a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu#include <utils/Vector.h>
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
36d5ec5f919dc835ca302d97c3cdc8f5b11f0584f0Peng Xu#include <map>
37987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe
384a4baef431195f3f0a7ce3ea8b8bc316ed68228cPeng Xunamespace {
394a4baef431195f3f0a7ce3ea8b8bc316ed68228cPeng Xu
404a4baef431195f3f0a7ce3ea8b8bc316ed68228cPeng Xuusing namespace android;
414a4baef431195f3f0a7ce3ea8b8bc316ed68228cPeng Xu
424a4baef431195f3f0a7ce3ea8b8bc316ed68228cPeng Xustruct {
43db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    jclass clazz;
44db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    jmethodID dispatchSensorEvent;
45b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    jmethodID dispatchFlushCompleteEvent;
46a29583553957a19755bfba26f48b6ebe977879cbPeng Xu    jmethodID dispatchAdditionalInfoEvent;
479a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh} gBaseEventQueueClassInfo;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct SensorOffsets
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
51a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    jclass      clazz;
52b85b1fed45eef4c4a095c7697156054cd2acf4e1Peng Xu    //fields
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID    name;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID    vendor;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID    version;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID    handle;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID    range;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID    resolution;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    jfieldID    power;
60050b56244ff46d43e4886018d7cd20f0b1dc02b9Mathias Agopian    jfieldID    minDelay;
61b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    jfieldID    fifoReservedEventCount;
62b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    jfieldID    fifoMaxEventCount;
63cd9a7bb3ba742606f93dcbd549d6d6eeb1cb5247Aravind Akella    jfieldID    stringType;
64cd9a7bb3ba742606f93dcbd549d6d6eeb1cb5247Aravind Akella    jfieldID    requiredPermission;
652f8b91449efafa5fb0057cd0150233681c65c9e3Aravind Akella    jfieldID    maxDelay;
6627900358f2f5b89e8b01516b28a916d16c99ba9bAravind Akella    jfieldID    flags;
67b85b1fed45eef4c4a095c7697156054cd2acf4e1Peng Xu    //methods
689ba7c1c17567c19f0187d73cdca55ca99590674edestradaa    jmethodID   setType;
69b85b1fed45eef4c4a095c7697156054cd2acf4e1Peng Xu    jmethodID   setUuid;
70a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    jmethodID   init;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} gSensorOffsets;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
73a35b5539a95342799a18e95616c5e5751a198e4cPeng Xustruct ListOffsets {
74a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    jclass      clazz;
75a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    jmethodID   add;
76a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu} gListOffsets;
77db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
783e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xustruct StringOffsets {
793e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    jclass      clazz;
803e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    jmethodID   intern;
813e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    jstring     emptyString;
823e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu} gStringOffsets;
833e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
854a4baef431195f3f0a7ce3ea8b8bc316ed68228cPeng Xu * nativeClassInit is not inteneded to be thread-safe. It should be called before other native...
864a4baef431195f3f0a7ce3ea8b8bc316ed68228cPeng Xu * functions (except nativeCreate).
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
88db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopianstatic void
89db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias AgopiannativeClassInit (JNIEnv *_env, jclass _this)
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
91a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    //android.hardware.Sensor
92db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    SensorOffsets& sensorOffsets = gSensorOffsets;
933e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    jclass sensorClass = (jclass)
943e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu            MakeGlobalRefOrDie(_env, FindClassOrDie(_env, "android/hardware/Sensor"));
953e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.clazz = sensorClass;
963e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.name = GetFieldIDOrDie(_env, sensorClass, "mName", "Ljava/lang/String;");
973e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.vendor = GetFieldIDOrDie(_env, sensorClass, "mVendor", "Ljava/lang/String;");
983e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.version = GetFieldIDOrDie(_env, sensorClass, "mVersion", "I");
993e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.handle = GetFieldIDOrDie(_env, sensorClass, "mHandle", "I");
1003e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.range = GetFieldIDOrDie(_env, sensorClass, "mMaxRange", "F");
1013e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.resolution = GetFieldIDOrDie(_env, sensorClass, "mResolution","F");
1023e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.power = GetFieldIDOrDie(_env, sensorClass, "mPower", "F");
1033e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.minDelay = GetFieldIDOrDie(_env, sensorClass, "mMinDelay", "I");
104b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    sensorOffsets.fifoReservedEventCount =
1053e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu            GetFieldIDOrDie(_env,sensorClass, "mFifoReservedEventCount", "I");
1063e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.fifoMaxEventCount = GetFieldIDOrDie(_env,sensorClass, "mFifoMaxEventCount", "I");
1073e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.stringType =
1083e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu            GetFieldIDOrDie(_env,sensorClass, "mStringType", "Ljava/lang/String;");
1093e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.requiredPermission =
1103e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu            GetFieldIDOrDie(_env,sensorClass, "mRequiredPermission", "Ljava/lang/String;");
1113e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.maxDelay = GetFieldIDOrDie(_env,sensorClass, "mMaxDelay", "I");
1123e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.flags = GetFieldIDOrDie(_env,sensorClass, "mFlags", "I");
1133e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu
1143e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.setType = GetMethodIDOrDie(_env,sensorClass, "setType", "(I)Z");
1153e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.setUuid = GetMethodIDOrDie(_env,sensorClass, "setUuid", "(JJ)V");
1163e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    sensorOffsets.init = GetMethodIDOrDie(_env,sensorClass, "<init>", "()V");
117a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu
118a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    // java.util.List;
119a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    ListOffsets& listOffsets = gListOffsets;
1203e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    jclass listClass = (jclass) MakeGlobalRefOrDie(_env, FindClassOrDie(_env, "java/util/List"));
121a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    listOffsets.clazz = listClass;
1223e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    listOffsets.add = GetMethodIDOrDie(_env,listClass, "add", "(Ljava/lang/Object;)Z");
1233e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu
1243e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    // initialize java.lang.String and empty string intern
1253e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    StringOffsets& stringOffsets = gStringOffsets;
1263e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    stringOffsets.clazz = MakeGlobalRefOrDie(_env, FindClassOrDie(_env, "java/lang/String"));
1273e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    stringOffsets.intern =
1283e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu            GetMethodIDOrDie(_env, stringOffsets.clazz, "intern", "()Ljava/lang/String;");
1293e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    ScopedLocalRef<jstring> empty(_env, _env->NewStringUTF(""));
1303e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    stringOffsets.emptyString = (jstring)
1313e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu            MakeGlobalRefOrDie(_env, _env->CallObjectMethod(empty.get(), stringOffsets.intern));
1329ba7c1c17567c19f0187d73cdca55ca99590674edestradaa}
1339ba7c1c17567c19f0187d73cdca55ca99590674edestradaa
1343e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xustatic jstring getJavaInternedString(JNIEnv *env, const String8 &string) {
1353e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    if (string == "") {
1363e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu        return gStringOffsets.emptyString;
1379ba7c1c17567c19f0187d73cdca55ca99590674edestradaa    }
1389ba7c1c17567c19f0187d73cdca55ca99590674edestradaa
1393e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    ScopedLocalRef<jstring> javaString(env, env->NewStringUTF(string.string()));
1403e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu    jstring internedString = (jstring)
1413e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu            env->CallObjectMethod(javaString.get(), gStringOffsets.intern);
1429ba7c1c17567c19f0187d73cdca55ca99590674edestradaa    return internedString;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
145b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganovstatic jlong
146b9d71a6f89b1183f6389b1774652445a420c6cbfSvet GanovnativeCreate
147b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov(JNIEnv *env, jclass clazz, jstring opPackageName)
148b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov{
149b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov    ScopedUtfChars opPackageNameUtf(env, opPackageName);
1502af91d0e104b3a80f3e832e464e52893a55a715fAravind Akella    return (jlong) &SensorManager::getInstanceForPackage(String16(opPackageNameUtf.c_str()));
151b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov}
152b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov
153a35b5539a95342799a18e95616c5e5751a198e4cPeng Xustatic jobject
154a35b5539a95342799a18e95616c5e5751a198e4cPeng XutranslateNativeSensorToJavaSensor(JNIEnv *env, jobject sensor, const Sensor& nativeSensor) {
155a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    const SensorOffsets& sensorOffsets(gSensorOffsets);
156a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu
157a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    if (sensor == NULL) {
158a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        // Sensor sensor = new Sensor();
159a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        sensor = env->NewObject(sensorOffsets.clazz, sensorOffsets.init, "");
160a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    }
161a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu
162a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    if (sensor != NULL) {
1633e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu        jstring name = getJavaInternedString(env, nativeSensor.getName());
1643e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu        jstring vendor = getJavaInternedString(env, nativeSensor.getVendor());
165a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        jstring requiredPermission =
1663e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu                getJavaInternedString(env, nativeSensor.getRequiredPermission());
167a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu
168a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        env->SetObjectField(sensor, sensorOffsets.name,      name);
169a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        env->SetObjectField(sensor, sensorOffsets.vendor,    vendor);
170a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        env->SetIntField(sensor, sensorOffsets.version,      nativeSensor.getVersion());
171a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        env->SetIntField(sensor, sensorOffsets.handle,       nativeSensor.getHandle());
172a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        env->SetFloatField(sensor, sensorOffsets.range,      nativeSensor.getMaxValue());
173a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        env->SetFloatField(sensor, sensorOffsets.resolution, nativeSensor.getResolution());
174a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        env->SetFloatField(sensor, sensorOffsets.power,      nativeSensor.getPowerUsage());
175a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        env->SetIntField(sensor, sensorOffsets.minDelay,     nativeSensor.getMinDelay());
176a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        env->SetIntField(sensor, sensorOffsets.fifoReservedEventCount,
177a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu                         nativeSensor.getFifoReservedEventCount());
178a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount,
179a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu                         nativeSensor.getFifoMaxEventCount());
180a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        env->SetObjectField(sensor, sensorOffsets.requiredPermission,
181a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu                            requiredPermission);
182a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        env->SetIntField(sensor, sensorOffsets.maxDelay, nativeSensor.getMaxDelay());
183a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        env->SetIntField(sensor, sensorOffsets.flags, nativeSensor.getFlags());
184b85b1fed45eef4c4a095c7697156054cd2acf4e1Peng Xu
185a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        if (env->CallBooleanMethod(sensor, sensorOffsets.setType, nativeSensor.getType())
186a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu                == JNI_FALSE) {
1873e13204989f0ebb1706cf44223b2ed28968ea46bPeng Xu            jstring stringType = getJavaInternedString(env, nativeSensor.getStringType());
188a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu            env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
189a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        }
190b85b1fed45eef4c4a095c7697156054cd2acf4e1Peng Xu
191716866d56542c267ccb686992de590ad04c84215Peng Xu        // TODO(b/29547335): Rename "setUuid" method to "setId".
192716866d56542c267ccb686992de590ad04c84215Peng Xu        int64_t id = nativeSensor.getId();
193716866d56542c267ccb686992de590ad04c84215Peng Xu        env->CallVoidMethod(sensor, sensorOffsets.setUuid, id, 0);
194a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    }
195a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    return sensor;
196a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu}
197a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu
198516e40ea5d73cf577d8dec559c7902b79cf483d0Aravind Akellastatic jboolean
199516e40ea5d73cf577d8dec559c7902b79cf483d0Aravind AkellanativeGetSensorAtIndex(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensor, jint index)
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
201b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2031bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian    Sensor const* const* sensorList;
204a08c9f52db26fa78e33464b57cc0597981352270Peng Xu    ssize_t count = mgr->getSensorList(&sensorList);
205a08c9f52db26fa78e33464b57cc0597981352270Peng Xu    if (ssize_t(index) >= count) {
206516e40ea5d73cf577d8dec559c7902b79cf483d0Aravind Akella        return false;
2079ba7c1c17567c19f0187d73cdca55ca99590674edestradaa    }
208b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella
209b85b1fed45eef4c4a095c7697156054cd2acf4e1Peng Xu    return translateNativeSensorToJavaSensor(env, sensor, *sensorList[index]) != NULL;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
212a35b5539a95342799a18e95616c5e5751a198e4cPeng Xustatic void
213a35b5539a95342799a18e95616c5e5751a198e4cPeng XunativeGetDynamicSensors(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensorList) {
214a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu
215a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
216a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    const ListOffsets& listOffsets(gListOffsets);
217a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu
218a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    Vector<Sensor> nativeList;
219a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu
220a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    mgr->getDynamicSensorList(nativeList);
221a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu
22285ea32b02a2b281ee5092ef8c31c44a0ba3452a4Ben Wagner    ALOGI("DYNS native SensorManager.getDynamicSensorList return %zu sensors", nativeList.size());
223a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    for (size_t i = 0; i < nativeList.size(); ++i) {
224a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        jobject sensor = translateNativeSensorToJavaSensor(env, NULL, nativeList[i]);
225a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        // add to list
226a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu        env->CallBooleanMethod(sensorList, listOffsets.add, sensor);
227a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    }
228a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu}
229a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu
230d123b51f8b14047804612cb1b15288cca81ed4f9Aravind Akellastatic jboolean nativeIsDataInjectionEnabled(JNIEnv *_env, jclass _this, jlong sensorManager) {
231b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
232d123b51f8b14047804612cb1b15288cca81ed4f9Aravind Akella    return mgr->isDataInjectionEnabled();
23318ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella}
23418ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella
235fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xustatic jint nativeCreateDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
2367d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu        jlong size, jint channelType, jint fd, jobject hardwareBufferObj) {
2377d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu    const native_handle_t *nativeHandle = nullptr;
2387d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu    NATIVE_HANDLE_DECLARE_STORAGE(ashmemHandle, 1, 0);
2397d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu
2407d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu    if (channelType == SENSOR_DIRECT_MEM_TYPE_ASHMEM) {
2417d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu        native_handle_t *handle = native_handle_init(ashmemHandle, 1, 0);
2427d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu        handle->data[0] = fd;
2437d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu        nativeHandle = handle;
2447d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu    } else if (channelType == SENSOR_DIRECT_MEM_TYPE_GRALLOC) {
2457d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu        AHardwareBuffer *hardwareBuffer =
2467d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu                android_hardware_HardwareBuffer_getNativeHardwareBuffer(_env, hardwareBufferObj);
2477d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu        if (hardwareBuffer != nullptr) {
2487d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu            nativeHandle = AHardwareBuffer_getNativeHandle(hardwareBuffer);
249fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu        }
250fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu    }
2517d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu
2527d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu    if (nativeHandle == nullptr) {
2537d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu        return BAD_VALUE;
2547d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu    }
2557d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu
2567d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
2577d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu    return mgr->createDirectChannel(size, channelType, nativeHandle);
258fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu}
259fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu
260fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xustatic void nativeDestroyDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
261fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu        jint channelHandle) {
262fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
263fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu    mgr->destroyDirectChannel(channelHandle);
264fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu}
265fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu
266fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xustatic jint nativeConfigDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
267fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu        jint channelHandle, jint sensorHandle, jint rate) {
268fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
269fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu    return mgr->configureDirectChannel(channelHandle, sensorHandle, rate);
270fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu}
271fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu
2721cfde25e4019bc050c7f030896825fd90d69baf5Peng Xustatic jint nativeSetOperationParameter(JNIEnv *_env, jclass _this, jlong sensorManager,
2735b5e11c483c14f930d3516042af8497a7b766a47Alexey Polyudov        jint handle, jint type, jfloatArray floats, jintArray ints) {
2741cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
2751cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu    Vector<float> floatVector;
2761cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu    Vector<int32_t> int32Vector;
2771cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu
2781cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu    if (floats != nullptr) {
2791cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu        floatVector.resize(_env->GetArrayLength(floats));
2801cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu        _env->GetFloatArrayRegion(floats, 0, _env->GetArrayLength(floats), floatVector.editArray());
2811cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu    }
2821cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu
2831cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu    if (ints != nullptr) {
2841cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu        int32Vector.resize(_env->GetArrayLength(ints));
2851cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu        _env->GetIntArrayRegion(ints, 0, _env->GetArrayLength(ints), int32Vector.editArray());
2861cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu    }
2871cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu
2885b5e11c483c14f930d3516042af8497a7b766a47Alexey Polyudov    return mgr->setOperationParameter(handle, type, floatVector, int32Vector);
2891cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu}
2901cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project//----------------------------------------------------------------------------
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
293db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopianclass Receiver : public LooperCallback {
294db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    sp<SensorEventQueue> mSensorQueue;
295db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    sp<MessageQueue> mMessageQueue;
2963b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown    jobject mReceiverWeakGlobal;
297a29583553957a19755bfba26f48b6ebe977879cbPeng Xu    jfloatArray mFloatScratch;
298a29583553957a19755bfba26f48b6ebe977879cbPeng Xu    jintArray   mIntScratch;
299db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopianpublic:
300db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    Receiver(const sp<SensorEventQueue>& sensorQueue,
301db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            const sp<MessageQueue>& messageQueue,
302a29583553957a19755bfba26f48b6ebe977879cbPeng Xu            jobject receiverWeak) {
303db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        JNIEnv* env = AndroidRuntime::getJNIEnv();
304db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        mSensorQueue = sensorQueue;
305db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        mMessageQueue = messageQueue;
3063b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown        mReceiverWeakGlobal = env->NewGlobalRef(receiverWeak);
307a29583553957a19755bfba26f48b6ebe977879cbPeng Xu
308a29583553957a19755bfba26f48b6ebe977879cbPeng Xu        mIntScratch = (jintArray) env->NewGlobalRef(env->NewIntArray(16));
309a29583553957a19755bfba26f48b6ebe977879cbPeng Xu        mFloatScratch = (jfloatArray) env->NewGlobalRef(env->NewFloatArray(16));
310db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    }
311db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    ~Receiver() {
312db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        JNIEnv* env = AndroidRuntime::getJNIEnv();
3133b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown        env->DeleteGlobalRef(mReceiverWeakGlobal);
314a29583553957a19755bfba26f48b6ebe977879cbPeng Xu        env->DeleteGlobalRef(mFloatScratch);
315a29583553957a19755bfba26f48b6ebe977879cbPeng Xu        env->DeleteGlobalRef(mIntScratch);
316db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    }
317db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    sp<SensorEventQueue> getSensorEventQueue() const {
318db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        return mSensorQueue;
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
321db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    void destroy() {
322db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        mMessageQueue->getLooper()->removeFd( mSensorQueue->getFd() );
323270e87f71abc2edf446dbec20c725c823e8c7f37Mike Lockwood    }
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
325db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopianprivate:
326db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    virtual void onFirstRef() {
327db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        LooperCallback::onFirstRef();
328db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        mMessageQueue->getLooper()->addFd(mSensorQueue->getFd(), 0,
329db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                ALOOPER_EVENT_INPUT, this, mSensorQueue.get());
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
331db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
332db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    virtual int handleEvent(int fd, int events, void* data) {
333db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        JNIEnv* env = AndroidRuntime::getJNIEnv();
334db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        sp<SensorEventQueue> q = reinterpret_cast<SensorEventQueue *>(data);
3353b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown        ScopedLocalRef<jobject> receiverObj(env, jniGetReferent(env, mReceiverWeakGlobal));
3363b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown
337db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        ssize_t n;
338db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        ASensorEvent buffer[16];
339db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        while ((n = q->read(buffer, 16)) > 0) {
340db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            for (int i=0 ; i<n ; i++) {
3410288ca63e3f0aee05ad2ede23564e04e53aca950Aravind Akella                if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {
3423c9c0918635143f373817fff1ce5131b995282cfJean-Baptiste Queru                    // step-counter returns a uint64, but the java API only deals with floats
3433c9c0918635143f373817fff1ce5131b995282cfJean-Baptiste Queru                    float value = float(buffer[i].u64.step_counter);
344a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                    env->SetFloatArrayRegion(mFloatScratch, 0, 1, &value);
345a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu                } else if (buffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META) {
346a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu                    float value[2];
347a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu                    value[0] = buffer[i].dynamic_sensor_meta.connected ? 1.f: 0.f;
348a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu                    value[1] = float(buffer[i].dynamic_sensor_meta.handle);
349a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                    env->SetFloatArrayRegion(mFloatScratch, 0, 2, value);
350a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
351a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                    env->SetIntArrayRegion(mIntScratch, 0, 14,
352a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                                           buffer[i].additional_info.data_int32);
353a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                    env->SetFloatArrayRegion(mFloatScratch, 0, 14,
354a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                                             buffer[i].additional_info.data_float);
3553c9c0918635143f373817fff1ce5131b995282cfJean-Baptiste Queru                } else {
356a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                    env->SetFloatArrayRegion(mFloatScratch, 0, 16, buffer[i].data);
3573c9c0918635143f373817fff1ce5131b995282cfJean-Baptiste Queru                }
358db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
359b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                if (buffer[i].type == SENSOR_TYPE_META_DATA) {
360b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                    // This is a flush complete sensor event. Call dispatchFlushCompleteEvent
361b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                    // method.
3623b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown                    if (receiverObj.get()) {
3633b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown                        env->CallVoidMethod(receiverObj.get(),
3643b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown                                            gBaseEventQueueClassInfo.dispatchFlushCompleteEvent,
3653b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown                                            buffer[i].meta_data.sensor);
3663b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown                    }
367a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                } else if (buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
368a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                    // This is a flush complete sensor event. Call dispatchAdditionalInfoEvent
369a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                    // method.
370a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                    if (receiverObj.get()) {
371a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                        int type = buffer[i].additional_info.type;
372a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                        int serial = buffer[i].additional_info.serial;
373a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                        env->CallVoidMethod(receiverObj.get(),
374a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                                            gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent,
375a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                                            buffer[i].sensor,
376a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                                            type, serial,
377a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                                            mFloatScratch,
378a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                                            mIntScratch,
379a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                                            buffer[i].timestamp);
380a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                    }
381a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                }else {
382af80510e85b301c8d8ba1e28e7edc7a0c9156a1aEtienne Le Grand                    int8_t status;
383af80510e85b301c8d8ba1e28e7edc7a0c9156a1aEtienne Le Grand                    switch (buffer[i].type) {
384af80510e85b301c8d8ba1e28e7edc7a0c9156a1aEtienne Le Grand                    case SENSOR_TYPE_ORIENTATION:
385af80510e85b301c8d8ba1e28e7edc7a0c9156a1aEtienne Le Grand                    case SENSOR_TYPE_MAGNETIC_FIELD:
386af80510e85b301c8d8ba1e28e7edc7a0c9156a1aEtienne Le Grand                    case SENSOR_TYPE_ACCELEROMETER:
387af80510e85b301c8d8ba1e28e7edc7a0c9156a1aEtienne Le Grand                    case SENSOR_TYPE_GYROSCOPE:
388f38226ab40feadb63b9b0c48d148db919ecec7f4Aravind Akella                    case SENSOR_TYPE_GRAVITY:
389f38226ab40feadb63b9b0c48d148db919ecec7f4Aravind Akella                    case SENSOR_TYPE_LINEAR_ACCELERATION:
390af80510e85b301c8d8ba1e28e7edc7a0c9156a1aEtienne Le Grand                        status = buffer[i].vector.status;
391af80510e85b301c8d8ba1e28e7edc7a0c9156a1aEtienne Le Grand                        break;
392af80510e85b301c8d8ba1e28e7edc7a0c9156a1aEtienne Le Grand                    case SENSOR_TYPE_HEART_RATE:
393af80510e85b301c8d8ba1e28e7edc7a0c9156a1aEtienne Le Grand                        status = buffer[i].heart_rate.status;
394af80510e85b301c8d8ba1e28e7edc7a0c9156a1aEtienne Le Grand                        break;
395af80510e85b301c8d8ba1e28e7edc7a0c9156a1aEtienne Le Grand                    default:
396af80510e85b301c8d8ba1e28e7edc7a0c9156a1aEtienne Le Grand                        status = SENSOR_STATUS_ACCURACY_HIGH;
397af80510e85b301c8d8ba1e28e7edc7a0c9156a1aEtienne Le Grand                        break;
398af80510e85b301c8d8ba1e28e7edc7a0c9156a1aEtienne Le Grand                    }
3993b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown                    if (receiverObj.get()) {
4003b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown                        env->CallVoidMethod(receiverObj.get(),
4013b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown                                            gBaseEventQueueClassInfo.dispatchSensorEvent,
4023b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown                                            buffer[i].sensor,
403a29583553957a19755bfba26f48b6ebe977879cbPeng Xu                                            mFloatScratch,
4043b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown                                            status,
4053b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown                                            buffer[i].timestamp);
4063b4049e79b1ea2872891cc0e87146e146111d502Jeff Brown                    }
407b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella                }
408db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                if (env->ExceptionCheck()) {
40935187bd5c1e40ea52a672c525411d05cbcdd6482Aravind Akella                    mSensorQueue->sendAck(buffer, n);
410db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                    ALOGE("Exception dispatching input event.");
411db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                    return 1;
412db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian                }
413db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            }
41435187bd5c1e40ea52a672c525411d05cbcdd6482Aravind Akella            mSensorQueue->sendAck(buffer, n);
415db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        }
416db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        if (n<0 && n != -EAGAIN) {
417db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            // FIXME: error receiving events, what to do in this case?
418db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        }
419db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        return 1;
4200b6d77bdeb99ca92709828c7c4867eec2f727f88Mathias Agopian    }
421db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian};
4221bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
423b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganovstatic jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
424a29583553957a19755bfba26f48b6ebe977879cbPeng Xu        jobject eventQWeak, jobject msgQ, jstring packageName, jint mode) {
425b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov    SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
42688445990b426499f25a9f37bc3b75f6e0267b4cbAravind Akella    ScopedUtfChars packageUtf(env, packageName);
42788445990b426499f25a9f37bc3b75f6e0267b4cbAravind Akella    String8 clientName(packageUtf.c_str());
428b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov    sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode));
429db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
430d9d4e1bc3bcecea31cc0aa055758915b3cbc6befPeng Xu    if (queue == NULL) {
431d9d4e1bc3bcecea31cc0aa055758915b3cbc6befPeng Xu        jniThrowRuntimeException(env, "Cannot construct native SensorEventQueue.");
432d9d4e1bc3bcecea31cc0aa055758915b3cbc6befPeng Xu        return 0;
433d9d4e1bc3bcecea31cc0aa055758915b3cbc6befPeng Xu    }
434d9d4e1bc3bcecea31cc0aa055758915b3cbc6befPeng Xu
435db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, msgQ);
436db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    if (messageQueue == NULL) {
437db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
438db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian        return 0;
439db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    }
4401bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
441a29583553957a19755bfba26f48b6ebe977879cbPeng Xu    sp<Receiver> receiver = new Receiver(queue, messageQueue, eventQWeak);
442b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian    receiver->incStrong((void*)nativeInitSensorEventQueue);
4434838e338129e09a37b8c8ad5e44f85ec5cd3aea1Ashok Bhat    return jlong(receiver.get());
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4464838e338129e09a37b8c8ad5e44f85ec5cd3aea1Ashok Bhatstatic jint nativeEnableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle, jint rate_us,
44788445990b426499f25a9f37bc3b75f6e0267b4cbAravind Akella                               jint maxBatchReportLatency) {
448db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
449b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    return receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency,
45088445990b426499f25a9f37bc3b75f6e0267b4cbAravind Akella                                                         0);
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4534838e338129e09a37b8c8ad5e44f85ec5cd3aea1Ashok Bhatstatic jint nativeDisableSensor(JNIEnv *env, jclass clazz, jlong eventQ, jint handle) {
454db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
455db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    return receiver->getSensorEventQueue()->disableSensor(handle);
456db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian}
457db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
45818ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akellastatic void nativeDestroySensorEventQueue(JNIEnv *env, jclass clazz, jlong eventQ) {
459db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
460db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    receiver->destroy();
461b1d90c8f60f71422196c337f1d078b68867f5710Mathias Agopian    receiver->decStrong((void*)nativeInitSensorEventQueue);
462db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian}
463db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
4644838e338129e09a37b8c8ad5e44f85ec5cd3aea1Ashok Bhatstatic jint nativeFlushSensor(JNIEnv *env, jclass clazz, jlong eventQ) {
465b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
4664bdc37d315a6dbdcf2425e70423ec43d7b74e102Aravind Akella    return receiver->getSensorEventQueue()->flush();
467b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella}
468db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
46918ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akellastatic jint nativeInjectSensorData(JNIEnv *env, jclass clazz, jlong eventQ, jint handle,
47018ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella        jfloatArray values, jint accuracy, jlong timestamp) {
47118ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella    sp<Receiver> receiver(reinterpret_cast<Receiver *>(eventQ));
47218ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella    // Create a sensor_event from the above data which can be injected into the HAL.
47318ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella    ASensorEvent sensor_event;
47418ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella    memset(&sensor_event, 0, sizeof(sensor_event));
47518ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella    sensor_event.sensor = handle;
47618ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella    sensor_event.timestamp = timestamp;
47718ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella    env->GetFloatArrayRegion(values, 0, env->GetArrayLength(values), sensor_event.data);
47818ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella    return receiver->getSensorEventQueue()->injectSensorEvent(sensor_event);
47918ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella}
480db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian//----------------------------------------------------------------------------
481db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
48276f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gSystemSensorManagerMethods[] = {
483db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    {"nativeClassInit",
484db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            "()V",
485db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            (void*)nativeClassInit },
486b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov    {"nativeCreate",
487b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov             "(Ljava/lang/String;)J",
488b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov             (void*)nativeCreate },
489db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
490516e40ea5d73cf577d8dec559c7902b79cf483d0Aravind Akella    {"nativeGetSensorAtIndex",
491516e40ea5d73cf577d8dec559c7902b79cf483d0Aravind Akella            "(JLandroid/hardware/Sensor;I)Z",
492516e40ea5d73cf577d8dec559c7902b79cf483d0Aravind Akella            (void*)nativeGetSensorAtIndex },
49318ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella
494a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu    {"nativeGetDynamicSensors",
495a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu            "(JLjava/util/List;)V",
496a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu            (void*)nativeGetDynamicSensors },
497a35b5539a95342799a18e95616c5e5751a198e4cPeng Xu
498d123b51f8b14047804612cb1b15288cca81ed4f9Aravind Akella    {"nativeIsDataInjectionEnabled",
499d123b51f8b14047804612cb1b15288cca81ed4f9Aravind Akella            "(J)Z",
500fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu            (void*)nativeIsDataInjectionEnabled },
501fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu
502fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu    {"nativeCreateDirectChannel",
5037d96fa0b2acb54a0951dbaf6f9ca5ecc1e2b1f0fPeng Xu            "(JJIILandroid/hardware/HardwareBuffer;)I",
504fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu            (void*)nativeCreateDirectChannel },
505fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu
506fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu    {"nativeDestroyDirectChannel",
507fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu            "(JI)V",
508fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu            (void*)nativeDestroyDirectChannel },
509fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu
510fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu    {"nativeConfigDirectChannel",
511fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu            "(JIII)I",
512fa2672b71d9501463d8b9de5162f069b9e48384bPeng Xu            (void*)nativeConfigDirectChannel },
5131cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu
5141cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu    {"nativeSetOperationParameter",
5155b5e11c483c14f930d3516042af8497a7b766a47Alexey Polyudov            "(JII[F[I)I",
5161cfde25e4019bc050c7f030896825fd90d69baf5Peng Xu            (void*)nativeSetOperationParameter },
517db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian};
5181bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
51976f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gBaseEventQueueMethods[] = {
5209a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh    {"nativeInitBaseEventQueue",
521a29583553957a19755bfba26f48b6ebe977879cbPeng Xu             "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;Ljava/lang/String;ILjava/lang/String;)J",
522b9d71a6f89b1183f6389b1774652445a420c6cbfSvet Ganov             (void*)nativeInitSensorEventQueue },
5231bf797857e025e8a71db86fb9e79765a767ec1ebMathias Agopian
524db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    {"nativeEnableSensor",
52588445990b426499f25a9f37bc3b75f6e0267b4cbAravind Akella            "(JIII)I",
526db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            (void*)nativeEnableSensor },
527db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
528db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    {"nativeDisableSensor",
5294838e338129e09a37b8c8ad5e44f85ec5cd3aea1Ashok Bhat            "(JI)I",
530db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            (void*)nativeDisableSensor },
531db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
532db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    {"nativeDestroySensorEventQueue",
5334838e338129e09a37b8c8ad5e44f85ec5cd3aea1Ashok Bhat            "(J)V",
534db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            (void*)nativeDestroySensorEventQueue },
535b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella
536b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella    {"nativeFlushSensor",
5374838e338129e09a37b8c8ad5e44f85ec5cd3aea1Ashok Bhat            "(J)I",
538b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella            (void*)nativeFlushSensor },
53918ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella
54018ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella    {"nativeInjectSensorData",
54118ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella            "(JI[FIJ)I",
54218ebf732b84d0575c871db35b25bf000e0c7c6a6Aravind Akella            (void*)nativeInjectSensorData },
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5454a4baef431195f3f0a7ce3ea8b8bc316ed68228cPeng Xu} //unnamed namespace
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_hardware_SensorManager(JNIEnv *env)
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
549987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager",
550db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian            gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
551db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
552987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    RegisterMethodsOrDie(env, "android/hardware/SystemSensorManager$BaseEventQueue",
5539a8df4dcf9f83c1cf0cd8dedeb51d1ff8a52a2b5Jaikumar Ganesh            gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));
554db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
555987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gBaseEventQueueClassInfo.clazz = FindClassOrDie(env,
556987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe            "android/hardware/SystemSensorManager$BaseEventQueue");
557db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
558987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gBaseEventQueueClassInfo.dispatchSensorEvent = GetMethodIDOrDie(env,
559987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe            gBaseEventQueueClassInfo.clazz, "dispatchSensorEvent", "(I[FIJ)V");
560db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian
561987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe    gBaseEventQueueClassInfo.dispatchFlushCompleteEvent = GetMethodIDOrDie(env,
562987f79f60bb1f0a4bcd3ef22e57301c743f0b94fAndreas Gampe            gBaseEventQueueClassInfo.clazz, "dispatchFlushCompleteEvent", "(I)V");
563b4c76b18a369d940f448bcc55d7245b6b30084ddAravind Akella
564a29583553957a19755bfba26f48b6ebe977879cbPeng Xu    gBaseEventQueueClassInfo.dispatchAdditionalInfoEvent = GetMethodIDOrDie(env,
565a29583553957a19755bfba26f48b6ebe977879cbPeng Xu            gBaseEventQueueClassInfo.clazz, "dispatchAdditionalInfoEvent", "(III[F[I)V");
566a29583553957a19755bfba26f48b6ebe977879cbPeng Xu
567db772d813492517dce2bd7e6e9fbc88e42b30c02Mathias Agopian    return 0;
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
569