1 /*
2  * Copyright (C) 2021 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 "NativeSensorService"
18 
19 #include <android-base/properties.h>
20 #include <android_os_NativeHandle.h>
21 #include <android_runtime/AndroidRuntime.h>
22 #include <core_jni_helpers.h>
23 #include <cutils/native_handle.h>
24 #include <cutils/properties.h>
25 #include <jni.h>
26 #include <nativehelper/JNIPlatformHelp.h>
27 #include <sensorservice/SensorService.h>
28 #include <string.h>
29 #include <utils/Log.h>
30 #include <utils/misc.h>
31 
32 #include <mutex>
33 
34 #include "android_util_Binder.h"
35 
36 #define PROXIMITY_ACTIVE_CLASS \
37     "com/android/server/sensors/SensorManagerInternal$ProximityActiveListener"
38 
39 #define RUNTIME_SENSOR_CALLBACK_CLASS \
40     "com/android/server/sensors/SensorManagerInternal$RuntimeSensorCallback"
41 
42 namespace android {
43 
44 static JavaVM* sJvm = nullptr;
45 static jmethodID sMethodIdOnProximityActive;
46 static jmethodID sMethodIdRuntimeSensorOnConfigurationChanged;
47 static jmethodID sMethodIdRuntimeSensorOnDirectChannelCreated;
48 static jmethodID sMethodIdRuntimeSensorOnDirectChannelDestroyed;
49 static jmethodID sMethodIdRuntimeSensorOnDirectChannelConfigured;
50 
51 class NativeSensorService {
52 public:
53     NativeSensorService(JNIEnv* env, jobject listener);
54 
55     void registerProximityActiveListener();
56     void unregisterProximityActiveListener();
57     jint registerRuntimeSensor(JNIEnv* env, jint deviceId, jint type, jstring name, jstring vendor,
58                                jfloat maximumRange, jfloat resolution, jfloat power, jint minDelay,
59                                jint maxDelay, jint flags, jobject callback);
60     void unregisterRuntimeSensor(jint handle);
61     jboolean sendRuntimeSensorEvent(JNIEnv* env, jint handle, jint type, jlong timestamp,
62                                     jfloatArray values);
63 
64 private:
65     sp<SensorService> mService;
66 
67     class ProximityActiveListenerDelegate : public SensorService::ProximityActiveListener {
68     public:
69         ProximityActiveListenerDelegate(JNIEnv* env, jobject listener);
70         ~ProximityActiveListenerDelegate();
71 
72         void onProximityActive(bool isActive) override;
73 
74     private:
75         jobject mListener;
76     };
77     sp<ProximityActiveListenerDelegate> mProximityActiveListenerDelegate;
78 
79     class RuntimeSensorCallbackDelegate : public SensorService::RuntimeSensorCallback {
80     public:
81         RuntimeSensorCallbackDelegate(JNIEnv* env, jobject callback);
82         ~RuntimeSensorCallbackDelegate();
83 
84         status_t onConfigurationChanged(int32_t handle, bool enabled, int64_t samplingPeriodNs,
85                                         int64_t batchReportLatencyNs) override;
86         int onDirectChannelCreated(int fd) override;
87         void onDirectChannelDestroyed(int channelHandle) override;
88         int onDirectChannelConfigured(int channelHandle, int sensorHandle, int rateLevel) override;
89 
90     private:
91         jobject mCallback;
92     };
93 };
94 
NativeSensorService(JNIEnv * env,jobject listener)95 NativeSensorService::NativeSensorService(JNIEnv* env, jobject listener)
96       : mProximityActiveListenerDelegate(new ProximityActiveListenerDelegate(env, listener)) {
97     if (base::GetBoolProperty("system_init.startsensorservice", true)) {
98         sp<IServiceManager> sm(defaultServiceManager());
99         mService = new SensorService();
100         sm->addService(String16(SensorService::getServiceName()), mService,
101                        false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
102     }
103 }
104 
registerProximityActiveListener()105 void NativeSensorService::registerProximityActiveListener() {
106     if (mService == nullptr) {
107         ALOGD("Dropping registerProximityActiveListener, sensor service not available.");
108         return;
109     }
110     mService->addProximityActiveListener(mProximityActiveListenerDelegate);
111 }
112 
unregisterProximityActiveListener()113 void NativeSensorService::unregisterProximityActiveListener() {
114     if (mService == nullptr) {
115         ALOGD("Dropping unregisterProximityActiveListener, sensor service not available.");
116         return;
117     }
118 
119     mService->removeProximityActiveListener(mProximityActiveListenerDelegate);
120 }
121 
registerRuntimeSensor(JNIEnv * env,jint deviceId,jint type,jstring name,jstring vendor,jfloat maximumRange,jfloat resolution,jfloat power,jint minDelay,jint maxDelay,jint flags,jobject callback)122 jint NativeSensorService::registerRuntimeSensor(JNIEnv* env, jint deviceId, jint type, jstring name,
123                                                 jstring vendor, jfloat maximumRange,
124                                                 jfloat resolution, jfloat power, jint minDelay,
125                                                 jint maxDelay, jint flags, jobject callback) {
126     if (mService == nullptr) {
127         ALOGD("Dropping registerRuntimeSensor, sensor service not available.");
128         return -1;
129     }
130 
131     sensor_t sensor{
132             .name = env->GetStringUTFChars(name, 0),
133             .vendor = env->GetStringUTFChars(vendor, 0),
134             .version = sizeof(sensor_t),
135             .type = type,
136             .maxRange = maximumRange,
137             .resolution = resolution,
138             .power = power,
139             .minDelay = minDelay,
140             .maxDelay = maxDelay,
141 #ifdef __LP64__
142             .flags = static_cast<uint64_t>(flags),
143 #else
144             .flags = static_cast<uint32_t>(flags),
145 #endif
146     };
147 
148     sp<RuntimeSensorCallbackDelegate> callbackDelegate(
149             new RuntimeSensorCallbackDelegate(env, callback));
150     return mService->registerRuntimeSensor(sensor, deviceId, callbackDelegate);
151 }
152 
unregisterRuntimeSensor(jint handle)153 void NativeSensorService::unregisterRuntimeSensor(jint handle) {
154     if (mService == nullptr) {
155         ALOGD("Dropping unregisterProximityActiveListener, sensor service not available.");
156         return;
157     }
158 
159     mService->unregisterRuntimeSensor(handle);
160 }
161 
sendRuntimeSensorEvent(JNIEnv * env,jint handle,jint type,jlong timestamp,jfloatArray values)162 jboolean NativeSensorService::sendRuntimeSensorEvent(JNIEnv* env, jint handle, jint type,
163                                                      jlong timestamp, jfloatArray values) {
164     if (mService == nullptr) {
165         ALOGD("Dropping sendRuntimeSensorEvent, sensor service not available.");
166         return false;
167     }
168     if (values == nullptr) {
169         ALOGD("Dropping sendRuntimeSensorEvent, no values.");
170         return false;
171     }
172 
173     sensors_event_t event{
174             .version = sizeof(sensors_event_t),
175             .timestamp = timestamp,
176             .sensor = handle,
177             .type = type,
178     };
179 
180     int valuesLength = env->GetArrayLength(values);
181     jfloat* sensorValues = env->GetFloatArrayElements(values, nullptr);
182 
183     switch (type) {
184         case SENSOR_TYPE_ACCELEROMETER:
185         case SENSOR_TYPE_MAGNETIC_FIELD:
186         case SENSOR_TYPE_ORIENTATION:
187         case SENSOR_TYPE_GYROSCOPE:
188         case SENSOR_TYPE_GRAVITY:
189         case SENSOR_TYPE_LINEAR_ACCELERATION: {
190             if (valuesLength != 3) {
191                 ALOGD("Dropping sendRuntimeSensorEvent, wrong number of values.");
192                 return false;
193             }
194             event.acceleration.x = sensorValues[0];
195             event.acceleration.y = sensorValues[1];
196             event.acceleration.z = sensorValues[2];
197             break;
198         }
199         case SENSOR_TYPE_DEVICE_ORIENTATION:
200         case SENSOR_TYPE_LIGHT:
201         case SENSOR_TYPE_PRESSURE:
202         case SENSOR_TYPE_TEMPERATURE:
203         case SENSOR_TYPE_PROXIMITY:
204         case SENSOR_TYPE_RELATIVE_HUMIDITY:
205         case SENSOR_TYPE_AMBIENT_TEMPERATURE:
206         case SENSOR_TYPE_SIGNIFICANT_MOTION:
207         case SENSOR_TYPE_STEP_DETECTOR:
208         case SENSOR_TYPE_TILT_DETECTOR:
209         case SENSOR_TYPE_WAKE_GESTURE:
210         case SENSOR_TYPE_GLANCE_GESTURE:
211         case SENSOR_TYPE_PICK_UP_GESTURE:
212         case SENSOR_TYPE_WRIST_TILT_GESTURE:
213         case SENSOR_TYPE_STATIONARY_DETECT:
214         case SENSOR_TYPE_MOTION_DETECT:
215         case SENSOR_TYPE_HEART_BEAT:
216         case SENSOR_TYPE_LOW_LATENCY_OFFBODY_DETECT: {
217             if (valuesLength != 1) {
218                 ALOGD("Dropping sendRuntimeSensorEvent, wrong number of values.");
219                 return false;
220             }
221             event.data[0] = sensorValues[0];
222             break;
223         }
224         default: {
225             if (valuesLength > 16) {
226                 ALOGD("Dropping sendRuntimeSensorEvent, number of values exceeds the maximum.");
227                 return false;
228             }
229             memcpy(event.data, sensorValues, valuesLength * sizeof(float));
230         }
231     }
232 
233     status_t err = mService->sendRuntimeSensorEvent(event);
234     return err == OK;
235 }
236 
ProximityActiveListenerDelegate(JNIEnv * env,jobject listener)237 NativeSensorService::ProximityActiveListenerDelegate::ProximityActiveListenerDelegate(
238         JNIEnv* env, jobject listener)
239       : mListener(env->NewGlobalRef(listener)) {}
240 
~ProximityActiveListenerDelegate()241 NativeSensorService::ProximityActiveListenerDelegate::~ProximityActiveListenerDelegate() {
242     AndroidRuntime::getJNIEnv()->DeleteGlobalRef(mListener);
243 }
244 
onProximityActive(bool isActive)245 void NativeSensorService::ProximityActiveListenerDelegate::onProximityActive(bool isActive) {
246     auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
247     jniEnv->CallVoidMethod(mListener, sMethodIdOnProximityActive, static_cast<jboolean>(isActive));
248 }
249 
RuntimeSensorCallbackDelegate(JNIEnv * env,jobject callback)250 NativeSensorService::RuntimeSensorCallbackDelegate::RuntimeSensorCallbackDelegate(JNIEnv* env,
251                                                                                   jobject callback)
252       : mCallback(env->NewGlobalRef(callback)) {}
253 
~RuntimeSensorCallbackDelegate()254 NativeSensorService::RuntimeSensorCallbackDelegate::~RuntimeSensorCallbackDelegate() {
255     AndroidRuntime::getJNIEnv()->DeleteGlobalRef(mCallback);
256 }
257 
onConfigurationChanged(int32_t handle,bool enabled,int64_t samplingPeriodNs,int64_t batchReportLatencyNs)258 status_t NativeSensorService::RuntimeSensorCallbackDelegate::onConfigurationChanged(
259         int32_t handle, bool enabled, int64_t samplingPeriodNs, int64_t batchReportLatencyNs) {
260     auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
261     return jniEnv->CallIntMethod(mCallback, sMethodIdRuntimeSensorOnConfigurationChanged,
262                                  static_cast<jint>(handle), static_cast<jboolean>(enabled),
263                                  static_cast<jint>(ns2us(samplingPeriodNs)),
264                                  static_cast<jint>(ns2us(batchReportLatencyNs)));
265 }
266 
onDirectChannelCreated(int fd)267 int NativeSensorService::RuntimeSensorCallbackDelegate::onDirectChannelCreated(int fd) {
268     if (fd <= 0) {
269         return 0;
270     }
271     auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
272     jobject jfd = jniCreateFileDescriptor(jniEnv, fd);
273     jobject parcelFileDescriptor = newParcelFileDescriptor(jniEnv, jfd);
274     return jniEnv->CallIntMethod(mCallback, sMethodIdRuntimeSensorOnDirectChannelCreated,
275                                  parcelFileDescriptor);
276 }
277 
onDirectChannelDestroyed(int channelHandle)278 void NativeSensorService::RuntimeSensorCallbackDelegate::onDirectChannelDestroyed(
279         int channelHandle) {
280     auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
281     return jniEnv->CallVoidMethod(mCallback, sMethodIdRuntimeSensorOnDirectChannelDestroyed,
282                                   static_cast<jint>(channelHandle));
283 }
284 
onDirectChannelConfigured(int channelHandle,int sensorHandle,int rateLevel)285 int NativeSensorService::RuntimeSensorCallbackDelegate::onDirectChannelConfigured(int channelHandle,
286                                                                                   int sensorHandle,
287                                                                                   int rateLevel) {
288     auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
289     return jniEnv->CallIntMethod(mCallback, sMethodIdRuntimeSensorOnDirectChannelConfigured,
290                                  static_cast<jint>(channelHandle), static_cast<jint>(sensorHandle),
291                                  static_cast<jint>(rateLevel));
292 }
293 
startSensorServiceNative(JNIEnv * env,jclass,jobject listener)294 static jlong startSensorServiceNative(JNIEnv* env, jclass, jobject listener) {
295     NativeSensorService* service = new NativeSensorService(env, listener);
296     return reinterpret_cast<jlong>(service);
297 }
298 
registerProximityActiveListenerNative(JNIEnv * env,jclass,jlong ptr)299 static void registerProximityActiveListenerNative(JNIEnv* env, jclass, jlong ptr) {
300     auto* service = reinterpret_cast<NativeSensorService*>(ptr);
301     service->registerProximityActiveListener();
302 }
303 
unregisterProximityActiveListenerNative(JNIEnv * env,jclass,jlong ptr)304 static void unregisterProximityActiveListenerNative(JNIEnv* env, jclass, jlong ptr) {
305     auto* service = reinterpret_cast<NativeSensorService*>(ptr);
306     service->unregisterProximityActiveListener();
307 }
308 
registerRuntimeSensorNative(JNIEnv * env,jclass,jlong ptr,jint deviceId,jint type,jstring name,jstring vendor,jfloat maximumRange,jfloat resolution,jfloat power,jint minDelay,jint maxDelay,jint flags,jobject callback)309 static jint registerRuntimeSensorNative(JNIEnv* env, jclass, jlong ptr, jint deviceId, jint type,
310                                         jstring name, jstring vendor, jfloat maximumRange,
311                                         jfloat resolution, jfloat power, jint minDelay,
312                                         jint maxDelay, jint flags, jobject callback) {
313     auto* service = reinterpret_cast<NativeSensorService*>(ptr);
314     return service->registerRuntimeSensor(env, deviceId, type, name, vendor, maximumRange,
315                                           resolution, power, minDelay, maxDelay, flags, callback);
316 }
317 
unregisterRuntimeSensorNative(JNIEnv * env,jclass,jlong ptr,jint handle)318 static void unregisterRuntimeSensorNative(JNIEnv* env, jclass, jlong ptr, jint handle) {
319     auto* service = reinterpret_cast<NativeSensorService*>(ptr);
320     service->unregisterRuntimeSensor(handle);
321 }
322 
sendRuntimeSensorEventNative(JNIEnv * env,jclass,jlong ptr,jint handle,jint type,jlong timestamp,jfloatArray values)323 static jboolean sendRuntimeSensorEventNative(JNIEnv* env, jclass, jlong ptr, jint handle, jint type,
324                                              jlong timestamp, jfloatArray values) {
325     auto* service = reinterpret_cast<NativeSensorService*>(ptr);
326     return service->sendRuntimeSensorEvent(env, handle, type, timestamp, values);
327 }
328 
329 static const JNINativeMethod methods[] = {
330         {"startSensorServiceNative", "(L" PROXIMITY_ACTIVE_CLASS ";)J",
331          reinterpret_cast<void*>(startSensorServiceNative)},
332         {"registerProximityActiveListenerNative", "(J)V",
333          reinterpret_cast<void*>(registerProximityActiveListenerNative)},
334         {"unregisterProximityActiveListenerNative", "(J)V",
335          reinterpret_cast<void*>(unregisterProximityActiveListenerNative)},
336         {"registerRuntimeSensorNative",
337          "(JIILjava/lang/String;Ljava/lang/String;FFFIIIL" RUNTIME_SENSOR_CALLBACK_CLASS ";)I",
338          reinterpret_cast<void*>(registerRuntimeSensorNative)},
339         {"unregisterRuntimeSensorNative", "(JI)V",
340          reinterpret_cast<void*>(unregisterRuntimeSensorNative)},
341         {"sendRuntimeSensorEventNative", "(JIIJ[F)Z",
342          reinterpret_cast<void*>(sendRuntimeSensorEventNative)},
343 };
344 
register_android_server_sensor_SensorService(JavaVM * vm,JNIEnv * env)345 int register_android_server_sensor_SensorService(JavaVM* vm, JNIEnv* env) {
346     sJvm = vm;
347     jclass listenerClass = FindClassOrDie(env, PROXIMITY_ACTIVE_CLASS);
348     sMethodIdOnProximityActive = GetMethodIDOrDie(env, listenerClass, "onProximityActive", "(Z)V");
349     jclass runtimeSensorCallbackClass = FindClassOrDie(env, RUNTIME_SENSOR_CALLBACK_CLASS);
350     sMethodIdRuntimeSensorOnConfigurationChanged =
351             GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onConfigurationChanged", "(IZII)I");
352     sMethodIdRuntimeSensorOnDirectChannelCreated =
353             GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onDirectChannelCreated",
354                              "(Landroid/os/ParcelFileDescriptor;)I");
355     sMethodIdRuntimeSensorOnDirectChannelDestroyed =
356             GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onDirectChannelDestroyed", "(I)V");
357     sMethodIdRuntimeSensorOnDirectChannelConfigured =
358             GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onDirectChannelConfigured",
359                              "(III)I");
360 
361     return jniRegisterNativeMethods(env, "com/android/server/sensors/SensorService", methods,
362                                     NELEM(methods));
363 }
364 
365 }; // namespace android
366