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_runtime/AndroidRuntime.h>
21 #include <core_jni_helpers.h>
22 #include <cutils/properties.h>
23 #include <jni.h>
24 #include <sensorservice/SensorService.h>
25 #include <utils/Log.h>
26 #include <utils/misc.h>
27 
28 #include <mutex>
29 
30 #define PROXIMITY_ACTIVE_CLASS \
31     "com/android/server/sensors/SensorManagerInternal$ProximityActiveListener"
32 
33 namespace android {
34 
35 static JavaVM* sJvm = nullptr;
36 static jmethodID sMethodIdOnProximityActive;
37 
38 class NativeSensorService {
39 public:
40     NativeSensorService(JNIEnv* env, jobject listener);
41 
42     void registerProximityActiveListener();
43     void unregisterProximityActiveListener();
44 
45 private:
46     sp<SensorService> mService;
47 
48     class ProximityActiveListenerDelegate : public SensorService::ProximityActiveListener {
49     public:
50         ProximityActiveListenerDelegate(JNIEnv* env, jobject listener);
51         ~ProximityActiveListenerDelegate();
52 
53         void onProximityActive(bool isActive) override;
54 
55     private:
56         jobject mListener;
57     };
58     sp<ProximityActiveListenerDelegate> mProximityActiveListenerDelegate;
59 };
60 
NativeSensorService(JNIEnv * env,jobject listener)61 NativeSensorService::NativeSensorService(JNIEnv* env, jobject listener)
62       : mProximityActiveListenerDelegate(new ProximityActiveListenerDelegate(env, listener)) {
63     if (base::GetBoolProperty("system_init.startsensorservice", true)) {
64         sp<IServiceManager> sm(defaultServiceManager());
65         mService = new SensorService();
66         sm->addService(String16(SensorService::getServiceName()), mService,
67                        false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
68     }
69 }
70 
registerProximityActiveListener()71 void NativeSensorService::registerProximityActiveListener() {
72     if (mService == nullptr) {
73         ALOGD("Dropping registerProximityActiveListener, sensor service not available.");
74         return;
75     }
76     mService->addProximityActiveListener(mProximityActiveListenerDelegate);
77 }
78 
unregisterProximityActiveListener()79 void NativeSensorService::unregisterProximityActiveListener() {
80     if (mService == nullptr) {
81         ALOGD("Dropping unregisterProximityActiveListener, sensor service not available.");
82         return;
83     }
84 
85     mService->removeProximityActiveListener(mProximityActiveListenerDelegate);
86 }
87 
ProximityActiveListenerDelegate(JNIEnv * env,jobject listener)88 NativeSensorService::ProximityActiveListenerDelegate::ProximityActiveListenerDelegate(
89         JNIEnv* env, jobject listener)
90       : mListener(env->NewGlobalRef(listener)) {}
91 
~ProximityActiveListenerDelegate()92 NativeSensorService::ProximityActiveListenerDelegate::~ProximityActiveListenerDelegate() {
93     AndroidRuntime::getJNIEnv()->DeleteGlobalRef(mListener);
94 }
95 
onProximityActive(bool isActive)96 void NativeSensorService::ProximityActiveListenerDelegate::onProximityActive(bool isActive) {
97     auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
98     jniEnv->CallVoidMethod(mListener, sMethodIdOnProximityActive, static_cast<jboolean>(isActive));
99 }
100 
startSensorServiceNative(JNIEnv * env,jclass,jobject listener)101 static jlong startSensorServiceNative(JNIEnv* env, jclass, jobject listener) {
102     NativeSensorService* service = new NativeSensorService(env, listener);
103     return reinterpret_cast<jlong>(service);
104 }
105 
registerProximityActiveListenerNative(JNIEnv * env,jclass,jlong ptr)106 static void registerProximityActiveListenerNative(JNIEnv* env, jclass, jlong ptr) {
107     auto* service = reinterpret_cast<NativeSensorService*>(ptr);
108     service->registerProximityActiveListener();
109 }
110 
unregisterProximityActiveListenerNative(JNIEnv * env,jclass,jlong ptr)111 static void unregisterProximityActiveListenerNative(JNIEnv* env, jclass, jlong ptr) {
112     auto* service = reinterpret_cast<NativeSensorService*>(ptr);
113     service->unregisterProximityActiveListener();
114 }
115 
116 static const JNINativeMethod methods[] = {
117         {
118                 "startSensorServiceNative", "(L" PROXIMITY_ACTIVE_CLASS ";)J",
119                 reinterpret_cast<void*>(startSensorServiceNative)
120         },
121         {
122                 "registerProximityActiveListenerNative", "(J)V",
123                 reinterpret_cast<void*>(registerProximityActiveListenerNative)
124         },
125         {
126                 "unregisterProximityActiveListenerNative", "(J)V",
127                 reinterpret_cast<void*>(unregisterProximityActiveListenerNative)
128          },
129 
130 };
131 
register_android_server_sensor_SensorService(JavaVM * vm,JNIEnv * env)132 int register_android_server_sensor_SensorService(JavaVM* vm, JNIEnv* env) {
133     sJvm = vm;
134     jclass listenerClass = FindClassOrDie(env, PROXIMITY_ACTIVE_CLASS);
135     sMethodIdOnProximityActive = GetMethodIDOrDie(env, listenerClass, "onProximityActive", "(Z)V");
136     return jniRegisterNativeMethods(env, "com/android/server/sensors/SensorService", methods,
137                                     NELEM(methods));
138 }
139 
140 }; // namespace android
141