• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 "VibratorManagerService"
18 
19 #include "com_android_server_vibrator_VibratorManagerService.h"
20 
21 #include <nativehelper/JNIHelp.h>
22 #include <utils/Log.h>
23 #include <utils/misc.h>
24 #include <vibratorservice/VibratorManagerHalController.h>
25 
26 #include <unordered_map>
27 
28 #include "android_runtime/AndroidRuntime.h"
29 #include "core_jni_helpers.h"
30 #include "jni.h"
31 
32 namespace android {
33 
34 static JavaVM* sJvm = nullptr;
35 static jmethodID sMethodIdOnSyncedVibrationComplete;
36 static jmethodID sMethodIdOnVibrationSessionComplete;
37 static std::mutex gManagerMutex;
38 static vibrator::ManagerHalController* gManager GUARDED_BY(gManagerMutex) = nullptr;
39 
40 class NativeVibratorManagerService {
41 public:
42     using IVibrationSession = aidl::android::hardware::vibrator::IVibrationSession;
43     using VibrationSessionConfig = aidl::android::hardware::vibrator::VibrationSessionConfig;
44 
NativeVibratorManagerService(JNIEnv * env,jobject callbackListener)45     NativeVibratorManagerService(JNIEnv* env, jobject callbackListener)
46           : mHal(std::make_unique<vibrator::ManagerHalController>()),
47             mCallbackListener(env->NewGlobalRef(callbackListener)) {
48         LOG_ALWAYS_FATAL_IF(mHal == nullptr, "Unable to find reference to vibrator manager hal");
49         LOG_ALWAYS_FATAL_IF(mCallbackListener == nullptr,
50                             "Unable to create global reference to vibration callback handler");
51     }
52 
~NativeVibratorManagerService()53     ~NativeVibratorManagerService() {
54         auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
55         jniEnv->DeleteGlobalRef(mCallbackListener);
56     }
57 
hal() const58     vibrator::ManagerHalController* hal() const { return mHal.get(); }
59 
createSyncedVibrationCallback(jlong vibrationId)60     std::function<void()> createSyncedVibrationCallback(jlong vibrationId) {
61         return [vibrationId, this]() {
62             auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
63             jniEnv->CallVoidMethod(mCallbackListener, sMethodIdOnSyncedVibrationComplete,
64                                    vibrationId);
65         };
66     }
67 
createVibrationSessionCallback(jlong sessionId)68     std::function<void()> createVibrationSessionCallback(jlong sessionId) {
69         return [sessionId, this]() {
70             auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
71             jniEnv->CallVoidMethod(mCallbackListener, sMethodIdOnVibrationSessionComplete,
72                                    sessionId);
73             std::lock_guard<std::mutex> lock(mSessionMutex);
74             auto it = mSessions.find(sessionId);
75             if (it != mSessions.end()) {
76                 mSessions.erase(it);
77             }
78         };
79     }
80 
startSession(jlong sessionId,const std::vector<int32_t> & vibratorIds)81     bool startSession(jlong sessionId, const std::vector<int32_t>& vibratorIds) {
82         VibrationSessionConfig config;
83         auto callback = createVibrationSessionCallback(sessionId);
84         auto result = hal()->startSession(vibratorIds, config, callback);
85         if (!result.isOk()) {
86             return false;
87         }
88 
89         std::lock_guard<std::mutex> lock(mSessionMutex);
90         mSessions[sessionId] = std::move(result.value());
91         return true;
92     }
93 
closeSession(jlong sessionId)94     void closeSession(jlong sessionId) {
95         std::lock_guard<std::mutex> lock(mSessionMutex);
96         auto it = mSessions.find(sessionId);
97         if (it != mSessions.end()) {
98             it->second->close();
99             // Keep session, it can still be aborted.
100         }
101     }
102 
abortSession(jlong sessionId)103     void abortSession(jlong sessionId) {
104         std::lock_guard<std::mutex> lock(mSessionMutex);
105         auto it = mSessions.find(sessionId);
106         if (it != mSessions.end()) {
107             it->second->abort();
108             mSessions.erase(it);
109         }
110     }
111 
clearSessions()112     void clearSessions() {
113         hal()->clearSessions();
114         std::lock_guard<std::mutex> lock(mSessionMutex);
115         mSessions.clear();
116     }
117 
118 private:
119     std::mutex mSessionMutex;
120     const std::unique_ptr<vibrator::ManagerHalController> mHal;
121     std::unordered_map<jlong, std::shared_ptr<IVibrationSession>> mSessions
122             GUARDED_BY(mSessionMutex);
123     const jobject mCallbackListener;
124 };
125 
android_server_vibrator_VibratorManagerService_getManager()126 vibrator::ManagerHalController* android_server_vibrator_VibratorManagerService_getManager() {
127     std::lock_guard<std::mutex> lock(gManagerMutex);
128     return gManager;
129 }
130 
destroyNativeService(void * ptr)131 static void destroyNativeService(void* ptr) {
132     NativeVibratorManagerService* service = reinterpret_cast<NativeVibratorManagerService*>(ptr);
133     if (service) {
134         std::lock_guard<std::mutex> lock(gManagerMutex);
135         gManager = nullptr;
136         delete service;
137     }
138 }
139 
nativeInit(JNIEnv * env,jclass,jobject callbackListener)140 static jlong nativeInit(JNIEnv* env, jclass /* clazz */, jobject callbackListener) {
141     std::unique_ptr<NativeVibratorManagerService> service =
142             std::make_unique<NativeVibratorManagerService>(env, callbackListener);
143     {
144         std::lock_guard<std::mutex> lock(gManagerMutex);
145         gManager = service->hal();
146     }
147     return reinterpret_cast<jlong>(service.release());
148 }
149 
nativeGetFinalizer(JNIEnv *,jclass)150 static jlong nativeGetFinalizer(JNIEnv* /* env */, jclass /* clazz */) {
151     return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyNativeService));
152 }
153 
nativeGetCapabilities(JNIEnv * env,jclass,jlong servicePtr)154 static jlong nativeGetCapabilities(JNIEnv* env, jclass /* clazz */, jlong servicePtr) {
155     NativeVibratorManagerService* service =
156             reinterpret_cast<NativeVibratorManagerService*>(servicePtr);
157     if (service == nullptr) {
158         ALOGE("nativeGetCapabilities failed because native service was not initialized");
159         return 0;
160     }
161     auto result = service->hal()->getCapabilities();
162     return result.isOk() ? static_cast<jlong>(result.value()) : 0;
163 }
164 
nativeGetVibratorIds(JNIEnv * env,jclass,jlong servicePtr)165 static jintArray nativeGetVibratorIds(JNIEnv* env, jclass /* clazz */, jlong servicePtr) {
166     NativeVibratorManagerService* service =
167             reinterpret_cast<NativeVibratorManagerService*>(servicePtr);
168     if (service == nullptr) {
169         ALOGE("nativeGetVibratorIds failed because native service was not initialized");
170         return nullptr;
171     }
172     auto result = service->hal()->getVibratorIds();
173     if (!result.isOk()) {
174         return nullptr;
175     }
176     std::vector<int32_t> vibratorIds = result.value();
177     jintArray ids = env->NewIntArray(vibratorIds.size());
178     env->SetIntArrayRegion(ids, 0, vibratorIds.size(), reinterpret_cast<jint*>(vibratorIds.data()));
179     return ids;
180 }
181 
nativePrepareSynced(JNIEnv * env,jclass,jlong servicePtr,jintArray vibratorIds)182 static jboolean nativePrepareSynced(JNIEnv* env, jclass /* clazz */, jlong servicePtr,
183                                     jintArray vibratorIds) {
184     NativeVibratorManagerService* service =
185             reinterpret_cast<NativeVibratorManagerService*>(servicePtr);
186     if (service == nullptr) {
187         ALOGE("nativePrepareSynced failed because native service was not initialized");
188         return JNI_FALSE;
189     }
190     jsize size = env->GetArrayLength(vibratorIds);
191     std::vector<int32_t> ids(size);
192     env->GetIntArrayRegion(vibratorIds, 0, size, reinterpret_cast<jint*>(ids.data()));
193     return service->hal()->prepareSynced(ids).isOk() ? JNI_TRUE : JNI_FALSE;
194 }
195 
nativeTriggerSynced(JNIEnv * env,jclass,jlong servicePtr,jlong vibrationId)196 static jboolean nativeTriggerSynced(JNIEnv* env, jclass /* clazz */, jlong servicePtr,
197                                     jlong vibrationId) {
198     NativeVibratorManagerService* service =
199             reinterpret_cast<NativeVibratorManagerService*>(servicePtr);
200     if (service == nullptr) {
201         ALOGE("nativeTriggerSynced failed because native service was not initialized");
202         return JNI_FALSE;
203     }
204     auto callback = service->createSyncedVibrationCallback(vibrationId);
205     return service->hal()->triggerSynced(callback).isOk() ? JNI_TRUE : JNI_FALSE;
206 }
207 
nativeCancelSynced(JNIEnv * env,jclass,jlong servicePtr)208 static void nativeCancelSynced(JNIEnv* env, jclass /* clazz */, jlong servicePtr) {
209     NativeVibratorManagerService* service =
210             reinterpret_cast<NativeVibratorManagerService*>(servicePtr);
211     if (service == nullptr) {
212         ALOGE("nativeCancelSynced failed because native service was not initialized");
213         return;
214     }
215     service->hal()->cancelSynced();
216 }
217 
nativeStartSession(JNIEnv * env,jclass,jlong servicePtr,jlong sessionId,jintArray vibratorIds)218 static jboolean nativeStartSession(JNIEnv* env, jclass /* clazz */, jlong servicePtr,
219                                    jlong sessionId, jintArray vibratorIds) {
220     NativeVibratorManagerService* service =
221             reinterpret_cast<NativeVibratorManagerService*>(servicePtr);
222     if (service == nullptr) {
223         ALOGE("nativeStartSession failed because native service was not initialized");
224         return JNI_FALSE;
225     }
226     jsize size = env->GetArrayLength(vibratorIds);
227     std::vector<int32_t> ids(size);
228     env->GetIntArrayRegion(vibratorIds, 0, size, reinterpret_cast<jint*>(ids.data()));
229     return service->startSession(sessionId, ids) ? JNI_TRUE : JNI_FALSE;
230 }
231 
nativeEndSession(JNIEnv * env,jclass,jlong servicePtr,jlong sessionId,jboolean shouldAbort)232 static void nativeEndSession(JNIEnv* env, jclass /* clazz */, jlong servicePtr, jlong sessionId,
233                              jboolean shouldAbort) {
234     NativeVibratorManagerService* service =
235             reinterpret_cast<NativeVibratorManagerService*>(servicePtr);
236     if (service == nullptr) {
237         ALOGE("nativeEndSession failed because native service was not initialized");
238         return;
239     }
240     if (shouldAbort) {
241         service->abortSession(sessionId);
242     } else {
243         service->closeSession(sessionId);
244     }
245 }
246 
nativeClearSessions(JNIEnv * env,jclass,jlong servicePtr)247 static void nativeClearSessions(JNIEnv* env, jclass /* clazz */, jlong servicePtr) {
248     NativeVibratorManagerService* service =
249             reinterpret_cast<NativeVibratorManagerService*>(servicePtr);
250     if (service == nullptr) {
251         ALOGE("nativeClearSessions failed because native service was not initialized");
252         return;
253     }
254     service->clearSessions();
255 }
256 
257 inline static constexpr auto sNativeInitMethodSignature =
258         "(Lcom/android/server/vibrator/VibratorManagerService$VibratorManagerNativeCallbacks;)J";
259 
260 static const JNINativeMethod method_table[] = {
261         {"nativeInit", sNativeInitMethodSignature, (void*)nativeInit},
nativeGetFinalizer()262         {"nativeGetFinalizer", "()J", (void*)nativeGetFinalizer},
nativeGetCapabilities(J)263         {"nativeGetCapabilities", "(J)J", (void*)nativeGetCapabilities},
nativeGetVibratorIds(J)264         {"nativeGetVibratorIds", "(J)[I", (void*)nativeGetVibratorIds},
nativePrepareSynced(J[I)265         {"nativePrepareSynced", "(J[I)Z", (void*)nativePrepareSynced},
nativeTriggerSynced(JJ)266         {"nativeTriggerSynced", "(JJ)Z", (void*)nativeTriggerSynced},
nativeCancelSynced(J)267         {"nativeCancelSynced", "(J)V", (void*)nativeCancelSynced},
nativeStartSession(JJ[I)268         {"nativeStartSession", "(JJ[I)Z", (void*)nativeStartSession},
nativeEndSession(JJZ)269         {"nativeEndSession", "(JJZ)V", (void*)nativeEndSession},
nativeClearSessions(J)270         {"nativeClearSessions", "(J)V", (void*)nativeClearSessions},
271 };
272 
register_android_server_vibrator_VibratorManagerService(JavaVM * jvm,JNIEnv * env)273 int register_android_server_vibrator_VibratorManagerService(JavaVM* jvm, JNIEnv* env) {
274     sJvm = jvm;
275     auto listenerClassName =
276             "com/android/server/vibrator/VibratorManagerService$VibratorManagerNativeCallbacks";
277     jclass listenerClass = FindClassOrDie(env, listenerClassName);
278     sMethodIdOnSyncedVibrationComplete =
279             GetMethodIDOrDie(env, listenerClass, "onSyncedVibrationComplete", "(J)V");
280     sMethodIdOnVibrationSessionComplete =
281             GetMethodIDOrDie(env, listenerClass, "onVibrationSessionComplete", "(J)V");
282     return jniRegisterNativeMethods(env, "com/android/server/vibrator/VibratorManagerService",
283                                     method_table, NELEM(method_table));
284 }
285 
286 }; // namespace android
287