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 <nativehelper/JNIHelp.h>
20 #include "android_runtime/AndroidRuntime.h"
21 #include "core_jni_helpers.h"
22 #include "jni.h"
23
24 #include <utils/Log.h>
25 #include <utils/misc.h>
26
27 #include <vibratorservice/VibratorManagerHalController.h>
28
29 #include "com_android_server_vibrator_VibratorManagerService.h"
30
31 namespace android {
32
33 static JavaVM* sJvm = nullptr;
34 static jmethodID sMethodIdOnComplete;
35 static std::mutex gManagerMutex;
36 static vibrator::ManagerHalController* gManager GUARDED_BY(gManagerMutex) = nullptr;
37
38 class NativeVibratorManagerService {
39 public:
NativeVibratorManagerService(JNIEnv * env,jobject callbackListener)40 NativeVibratorManagerService(JNIEnv* env, jobject callbackListener)
41 : mHal(std::make_unique<vibrator::ManagerHalController>()),
42 mCallbackListener(env->NewGlobalRef(callbackListener)) {
43 LOG_ALWAYS_FATAL_IF(mHal == nullptr, "Unable to find reference to vibrator manager hal");
44 LOG_ALWAYS_FATAL_IF(mCallbackListener == nullptr,
45 "Unable to create global reference to vibration callback handler");
46 }
47
~NativeVibratorManagerService()48 ~NativeVibratorManagerService() {
49 auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
50 jniEnv->DeleteGlobalRef(mCallbackListener);
51 }
52
hal() const53 vibrator::ManagerHalController* hal() const { return mHal.get(); }
54
createCallback(jlong vibrationId)55 std::function<void()> createCallback(jlong vibrationId) {
56 return [vibrationId, this]() {
57 auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
58 jniEnv->CallVoidMethod(mCallbackListener, sMethodIdOnComplete, vibrationId);
59 };
60 }
61
62 private:
63 const std::unique_ptr<vibrator::ManagerHalController> mHal;
64 const jobject mCallbackListener;
65 };
66
android_server_vibrator_VibratorManagerService_getManager()67 vibrator::ManagerHalController* android_server_vibrator_VibratorManagerService_getManager() {
68 std::lock_guard<std::mutex> lock(gManagerMutex);
69 return gManager;
70 }
71
destroyNativeService(void * ptr)72 static void destroyNativeService(void* ptr) {
73 NativeVibratorManagerService* service = reinterpret_cast<NativeVibratorManagerService*>(ptr);
74 if (service) {
75 std::lock_guard<std::mutex> lock(gManagerMutex);
76 gManager = nullptr;
77 delete service;
78 }
79 }
80
nativeInit(JNIEnv * env,jclass,jobject callbackListener)81 static jlong nativeInit(JNIEnv* env, jclass /* clazz */, jobject callbackListener) {
82 std::unique_ptr<NativeVibratorManagerService> service =
83 std::make_unique<NativeVibratorManagerService>(env, callbackListener);
84 {
85 std::lock_guard<std::mutex> lock(gManagerMutex);
86 gManager = service->hal();
87 }
88 return reinterpret_cast<jlong>(service.release());
89 }
90
nativeGetFinalizer(JNIEnv *,jclass)91 static jlong nativeGetFinalizer(JNIEnv* /* env */, jclass /* clazz */) {
92 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyNativeService));
93 }
94
nativeGetCapabilities(JNIEnv * env,jclass,jlong servicePtr)95 static jlong nativeGetCapabilities(JNIEnv* env, jclass /* clazz */, jlong servicePtr) {
96 NativeVibratorManagerService* service =
97 reinterpret_cast<NativeVibratorManagerService*>(servicePtr);
98 if (service == nullptr) {
99 ALOGE("nativeGetCapabilities failed because native service was not initialized");
100 return 0;
101 }
102 auto result = service->hal()->getCapabilities();
103 return result.isOk() ? static_cast<jlong>(result.value()) : 0;
104 }
105
nativeGetVibratorIds(JNIEnv * env,jclass,jlong servicePtr)106 static jintArray nativeGetVibratorIds(JNIEnv* env, jclass /* clazz */, jlong servicePtr) {
107 NativeVibratorManagerService* service =
108 reinterpret_cast<NativeVibratorManagerService*>(servicePtr);
109 if (service == nullptr) {
110 ALOGE("nativeGetVibratorIds failed because native service was not initialized");
111 return nullptr;
112 }
113 auto result = service->hal()->getVibratorIds();
114 if (!result.isOk()) {
115 return nullptr;
116 }
117 std::vector<int32_t> vibratorIds = result.value();
118 jintArray ids = env->NewIntArray(vibratorIds.size());
119 env->SetIntArrayRegion(ids, 0, vibratorIds.size(), reinterpret_cast<jint*>(vibratorIds.data()));
120 return ids;
121 }
122
nativePrepareSynced(JNIEnv * env,jclass,jlong servicePtr,jintArray vibratorIds)123 static jboolean nativePrepareSynced(JNIEnv* env, jclass /* clazz */, jlong servicePtr,
124 jintArray vibratorIds) {
125 NativeVibratorManagerService* service =
126 reinterpret_cast<NativeVibratorManagerService*>(servicePtr);
127 if (service == nullptr) {
128 ALOGE("nativePrepareSynced failed because native service was not initialized");
129 return JNI_FALSE;
130 }
131 jsize size = env->GetArrayLength(vibratorIds);
132 std::vector<int32_t> ids(size);
133 env->GetIntArrayRegion(vibratorIds, 0, size, reinterpret_cast<jint*>(ids.data()));
134 return service->hal()->prepareSynced(ids).isOk() ? JNI_TRUE : JNI_FALSE;
135 }
136
nativeTriggerSynced(JNIEnv * env,jclass,jlong servicePtr,jlong vibrationId)137 static jboolean nativeTriggerSynced(JNIEnv* env, jclass /* clazz */, jlong servicePtr,
138 jlong vibrationId) {
139 NativeVibratorManagerService* service =
140 reinterpret_cast<NativeVibratorManagerService*>(servicePtr);
141 if (service == nullptr) {
142 ALOGE("nativeTriggerSynced failed because native service was not initialized");
143 return JNI_FALSE;
144 }
145 auto callback = service->createCallback(vibrationId);
146 return service->hal()->triggerSynced(callback).isOk() ? JNI_TRUE : JNI_FALSE;
147 }
148
nativeCancelSynced(JNIEnv * env,jclass,jlong servicePtr)149 static void nativeCancelSynced(JNIEnv* env, jclass /* clazz */, jlong servicePtr) {
150 NativeVibratorManagerService* service =
151 reinterpret_cast<NativeVibratorManagerService*>(servicePtr);
152 if (service == nullptr) {
153 ALOGE("nativeCancelSynced failed because native service was not initialized");
154 return;
155 }
156 service->hal()->cancelSynced();
157 }
158
159 inline static constexpr auto sNativeInitMethodSignature =
160 "(Lcom/android/server/vibrator/VibratorManagerService$OnSyncedVibrationCompleteListener;)J";
161
162 static const JNINativeMethod method_table[] = {
163 {"nativeInit", sNativeInitMethodSignature, (void*)nativeInit},
164 {"nativeGetFinalizer", "()J", (void*)nativeGetFinalizer},
165 {"nativeGetCapabilities", "(J)J", (void*)nativeGetCapabilities},
166 {"nativeGetVibratorIds", "(J)[I", (void*)nativeGetVibratorIds},
167 {"nativePrepareSynced", "(J[I)Z", (void*)nativePrepareSynced},
168 {"nativeTriggerSynced", "(JJ)Z", (void*)nativeTriggerSynced},
169 {"nativeCancelSynced", "(J)V", (void*)nativeCancelSynced},
170 };
171
register_android_server_vibrator_VibratorManagerService(JavaVM * jvm,JNIEnv * env)172 int register_android_server_vibrator_VibratorManagerService(JavaVM* jvm, JNIEnv* env) {
173 sJvm = jvm;
174 auto listenerClassName =
175 "com/android/server/vibrator/VibratorManagerService$OnSyncedVibrationCompleteListener";
176 jclass listenerClass = FindClassOrDie(env, listenerClassName);
177 sMethodIdOnComplete = GetMethodIDOrDie(env, listenerClass, "onComplete", "(J)V");
178
179 return jniRegisterNativeMethods(env, "com/android/server/vibrator/VibratorManagerService",
180 method_table, NELEM(method_table));
181 }
182
183 }; // namespace android
184