1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef LOG_TAG
16 #define LOG_TAG "NapiAudioSpatializationManager"
17 #endif
18 
19 #include "napi_audio_spatialization_manager.h"
20 
21 #include <vector>
22 #include "napi_audio_error.h"
23 #include "napi_param_utils.h"
24 #include "napi_audio_enum.h"
25 #include "audio_errors.h"
26 #include "audio_manager_log.h"
27 #include "audio_utils.h"
28 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
29 #include "xpower_event_js.h"
30 #endif
31 #include "napi_audio_spatialization_manager_callback.h"
32 
33 namespace OHOS {
34 namespace AudioStandard {
35 using namespace std;
36 using namespace HiviewDFX;
37 static __thread napi_ref g_spatializationManagerConstructor = nullptr;
NapiAudioSpatializationManager()38 NapiAudioSpatializationManager::NapiAudioSpatializationManager()
39     : audioSpatializationMngr_(nullptr), env_(nullptr) {}
40 
41 NapiAudioSpatializationManager::~NapiAudioSpatializationManager() = default;
42 
CheckContextStatus(std::shared_ptr<AudioSpatializationManagerAsyncContext> context)43 bool NapiAudioSpatializationManager::CheckContextStatus(std::shared_ptr<AudioSpatializationManagerAsyncContext> context)
44 {
45     CHECK_AND_RETURN_RET_LOG(context != nullptr, false, "context object is nullptr.");
46     if (context->native == nullptr) {
47         context->SignError(NAPI_ERR_SYSTEM);
48         AUDIO_ERR_LOG("context object state is error.");
49         return false;
50     }
51     return true;
52 }
53 
CheckAudioSpatializationManagerStatus(NapiAudioSpatializationManager * napi,std::shared_ptr<AudioSpatializationManagerAsyncContext> context)54 bool NapiAudioSpatializationManager::CheckAudioSpatializationManagerStatus(NapiAudioSpatializationManager *napi,
55     std::shared_ptr<AudioSpatializationManagerAsyncContext> context)
56 {
57     CHECK_AND_RETURN_RET_LOG(napi != nullptr, false, "napi object is nullptr.");
58     if (napi->audioSpatializationMngr_ == nullptr) {
59         context->SignError(NAPI_ERR_SYSTEM);
60         AUDIO_ERR_LOG("audioSpatializationMngr is nullptr.");
61         return false;
62     }
63     return true;
64 }
65 
Destructor(napi_env env,void * nativeObject,void * finalizeHint)66 void NapiAudioSpatializationManager::Destructor(napi_env env, void *nativeObject, void *finalizeHint)
67 {
68     if (nativeObject != nullptr) {
69         auto obj = static_cast<NapiAudioSpatializationManager *>(nativeObject);
70         ObjectRefMap<NapiAudioSpatializationManager>::DecreaseRef(obj);
71     }
72     AUDIO_INFO_LOG("Destructor is successful");
73 }
74 
Construct(napi_env env,napi_callback_info info)75 napi_value NapiAudioSpatializationManager::Construct(napi_env env, napi_callback_info info)
76 {
77     AUDIO_INFO_LOG("Construct");
78     napi_status status;
79     napi_value result = nullptr;
80     napi_get_undefined(env, &result);
81 
82     size_t argc = ARGS_TWO;
83     napi_value argv[ARGS_TWO] = {0};
84     napi_value thisVar = nullptr;
85     void *data = nullptr;
86     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
87     unique_ptr<NapiAudioSpatializationManager> napiAudioSpatializationManager =
88         make_unique<NapiAudioSpatializationManager>();
89     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager != nullptr, result, "No memory");
90 
91     napiAudioSpatializationManager->audioSpatializationMngr_ = AudioSpatializationManager::GetInstance();
92     napiAudioSpatializationManager->env_ = env;
93 
94     ObjectRefMap<NapiAudioSpatializationManager>::Insert(napiAudioSpatializationManager.get());
95     status = napi_wrap(env, thisVar, static_cast<void*>(napiAudioSpatializationManager.get()),
96         NapiAudioSpatializationManager::Destructor, nullptr, nullptr);
97     if (status != napi_ok) {
98         ObjectRefMap<NapiAudioSpatializationManager>::Erase(napiAudioSpatializationManager.get());
99         return result;
100     }
101     napiAudioSpatializationManager.release();
102     return thisVar;
103 }
104 
GetParamWithSync(const napi_env & env,napi_callback_info info,size_t & argc,napi_value * args)105 NapiAudioSpatializationManager* NapiAudioSpatializationManager::GetParamWithSync(const napi_env &env,
106     napi_callback_info info, size_t &argc, napi_value *args)
107 {
108     napi_status status;
109     NapiAudioSpatializationManager *napiAudioSpatializationManager = nullptr;
110     napi_value jsThis = nullptr;
111 
112     status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
113     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr,
114         "GetParamWithSync fail to napi_get_cb_info");
115 
116     status = napi_unwrap(env, jsThis, (void **)&napiAudioSpatializationManager);
117     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "napi_unwrap failed");
118     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager != nullptr &&
119         napiAudioSpatializationManager->audioSpatializationMngr_ !=
120         nullptr, napiAudioSpatializationManager, "GetParamWithSync fail to napi_unwrap");
121     return napiAudioSpatializationManager;
122 }
123 
CreateSpatializationManagerWrapper(napi_env env)124 napi_value NapiAudioSpatializationManager::CreateSpatializationManagerWrapper(napi_env env)
125 {
126     napi_status status;
127     napi_value result = nullptr;
128     napi_value constructor;
129 
130     status = napi_get_reference_value(env, g_spatializationManagerConstructor, &constructor);
131     if (status != napi_ok) {
132         AUDIO_ERR_LOG("Failed in CreateSpatializationManagerWrapper, %{public}d", status);
133         goto fail;
134     }
135     status = napi_new_instance(env, constructor, 0, nullptr, &result);
136     if (status != napi_ok) {
137         AUDIO_ERR_LOG("napi_new_instance failed, status:%{public}d", status);
138         goto fail;
139     }
140     return result;
141 
142 fail:
143     napi_get_undefined(env, &result);
144     return result;
145 }
146 
Init(napi_env env,napi_value exports)147 napi_value NapiAudioSpatializationManager::Init(napi_env env, napi_value exports)
148 {
149     AUDIO_DEBUG_LOG("Init");
150 
151     napi_status status;
152     napi_value constructor;
153     napi_value result = nullptr;
154     const int32_t refCount = 1;
155     napi_get_undefined(env, &result);
156 
157     napi_property_descriptor audio_spatialization_manager_properties[] = {
158         DECLARE_NAPI_FUNCTION("isSpatializationEnabled", IsSpatializationEnabled),
159         DECLARE_NAPI_FUNCTION("setSpatializationEnabled", SetSpatializationEnabled),
160         DECLARE_NAPI_FUNCTION("isHeadTrackingEnabled", IsHeadTrackingEnabled),
161         DECLARE_NAPI_FUNCTION("setHeadTrackingEnabled", SetHeadTrackingEnabled),
162         DECLARE_NAPI_FUNCTION("isSpatializationSupported", IsSpatializationSupported),
163         DECLARE_NAPI_FUNCTION("isSpatializationSupportedForDevice", IsSpatializationSupportedForDevice),
164         DECLARE_NAPI_FUNCTION("isHeadTrackingSupported", IsHeadTrackingSupported),
165         DECLARE_NAPI_FUNCTION("isHeadTrackingSupportedForDevice", IsHeadTrackingSupportedForDevice),
166         DECLARE_NAPI_FUNCTION("updateSpatialDeviceState", UpdateSpatialDeviceState),
167         DECLARE_NAPI_FUNCTION("getSpatializationSceneType", GetSpatializationSceneType),
168         DECLARE_NAPI_FUNCTION("setSpatializationSceneType", SetSpatializationSceneType),
169         DECLARE_NAPI_FUNCTION("on", On),
170         DECLARE_NAPI_FUNCTION("off", Off),
171     };
172 
173     status = napi_define_class(env, AUDIO_SPATIALIZATION_MANAGER_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct,
174         nullptr,
175         sizeof(audio_spatialization_manager_properties) / sizeof(audio_spatialization_manager_properties[PARAM0]),
176         audio_spatialization_manager_properties, &constructor);
177     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_define_class fail");
178 
179     status = napi_create_reference(env, constructor, refCount, &g_spatializationManagerConstructor);
180     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_create_reference fail");
181     status = napi_set_named_property(env, exports, AUDIO_SPATIALIZATION_MANAGER_NAPI_CLASS_NAME.c_str(),
182         constructor);
183     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_set_named_property fail");
184     return exports;
185 }
186 
IsSpatializationEnabled(napi_env env,napi_callback_info info)187 napi_value NapiAudioSpatializationManager::IsSpatializationEnabled(napi_env env, napi_callback_info info)
188 {
189     AUDIO_INFO_LOG("IsSpatializationEnabled in");
190     napi_value result = nullptr;
191     CHECK_AND_RETURN_RET_LOG(PermissionUtil::VerifySelfPermission(),
192         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED), "No system permission");
193 
194     bool isSpatializationEnabled = false;
195     const size_t requireArgc = ARGS_ONE;
196     size_t argc = PARAM1;
197     napi_value args[ARGS_ONE] = {};
198     auto *napiAudioSpatializationManager = GetParamWithSync(env, info, argc, args);
199     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager != nullptr, result,
200         "napiAudioSpatializationManager is nullptr");
201     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager->audioSpatializationMngr_ != nullptr, result,
202         "audioSpatializationMngr is nullptr");
203 
204     if (argc == requireArgc) {
205         bool argTransFlag = true;
206         napi_valuetype valueType = napi_undefined;
207         napi_typeof(env, args[PARAM0], &valueType);
208         CHECK_AND_RETURN_RET_LOG(valueType == napi_object, NapiAudioError::ThrowErrorAndReturn(env,
209         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of deviceDescriptor must be object"),
210             "invalid valueType");
211 
212         sptr<AudioDeviceDescriptor> selectedAudioDevice = new (std::nothrow) AudioDeviceDescriptor();
213         NapiParamUtils::GetAudioDeviceDescriptor(env, selectedAudioDevice, argTransFlag, args[PARAM0]);
214         CHECK_AND_RETURN_RET_LOG(argTransFlag == true, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
215             "parameter verification failed: The param of deviceDescriptor must be interface AudioDeviceDescriptor"),
216             "invalid parameter");
217 
218         isSpatializationEnabled = napiAudioSpatializationManager->audioSpatializationMngr_
219             ->IsSpatializationEnabled(selectedAudioDevice);
220     } else if (argc < requireArgc) {
221         isSpatializationEnabled = napiAudioSpatializationManager->audioSpatializationMngr_->IsSpatializationEnabled();
222     } else {
223         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID, "invalid arguments");
224         return NapiParamUtils::GetUndefinedValue(env);
225     }
226     NapiParamUtils::SetValueBoolean(env, isSpatializationEnabled, result);
227     return result;
228 }
229 
SetSpatializationEnabled(napi_env env,napi_callback_info info)230 napi_value NapiAudioSpatializationManager::SetSpatializationEnabled(napi_env env, napi_callback_info info)
231 {
232     CHECK_AND_RETURN_RET_LOG(PermissionUtil::VerifySelfPermission(),
233         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED), "No system permission");
234 
235     size_t requireArgc = ARGS_ONE;
236     auto context = std::make_shared<AudioSpatializationManagerAsyncContext>();
237     if (context == nullptr) {
238         AUDIO_ERR_LOG("SetSpatializationEnabled failed : no memory");
239         NapiAudioError::ThrowError(env, "SetSpatializationEnabled failed : no memory", NAPI_ERR_NO_MEMORY);
240         return NapiParamUtils::GetUndefinedValue(env);
241     }
242 
243     auto inputParser = [env, context, &requireArgc](size_t argc, napi_value *argv) {
244         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "mandatory parameters are left unspecified",
245             NAPI_ERR_INPUT_INVALID);
246             bool argTransFlag = true;
247         if (argc == ARGS_ONE) {
248             context->status = NapiParamUtils::GetValueBoolean(env, context->spatializationEnable, argv[PARAM0]);
249             NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
250                 "incorrect parameter types: The type of enable must be boolean", NAPI_ERR_INPUT_INVALID);
251         } else if (argc == ARGS_TWO) {
252             context->status = NapiParamUtils::GetValueBoolean(env, context->spatializationEnable, argv[PARAM0]);
253             if (context->status == napi_ok) {
254                 requireArgc = ARGS_ONE;
255             } else {
256                 requireArgc = ARGS_TWO;
257                 context->status = NapiParamUtils::GetAudioDeviceDescriptor(env, context->deviceDescriptor, argTransFlag,
258                     argv[PARAM0]);
259                 NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
260                     "incorrect parameter types: The param of deviceDescriptor must be interface AudioDeviceDescriptor",
261                     NAPI_ERR_INPUT_INVALID);
262                 context->status = NapiParamUtils::GetValueBoolean(env, context->spatializationEnable, argv[PARAM1]);
263                 NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
264                     "incorrect parameter types: The type of enable must be boolean", NAPI_ERR_INPUT_INVALID);
265             }
266         }
267     };
268     context->GetCbInfo(env, info, inputParser);
269     if (context->status != napi_ok) {
270         NapiAudioError::ThrowError(env, context->errCode, context->errMessage);
271         return NapiParamUtils::GetUndefinedValue(env);
272     }
273 
274     return updateSpatializationEnabled(env, requireArgc, context);
275 }
276 
updateSpatializationEnabled(napi_env env,const std::size_t argc,std::shared_ptr<AudioSpatializationManagerAsyncContext> & context)277 napi_value NapiAudioSpatializationManager::updateSpatializationEnabled(napi_env env, const std::size_t argc,
278     std::shared_ptr<AudioSpatializationManagerAsyncContext> &context)
279 {
280     auto executor = [context, argc]() {
281         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
282         auto obj = reinterpret_cast<NapiAudioSpatializationManager*>(context->native);
283         ObjectRefMap objectGuard(obj);
284         auto *napiAudioSpatializationManager = objectGuard.GetPtr();
285         CHECK_AND_RETURN_LOG(CheckAudioSpatializationManagerStatus(napiAudioSpatializationManager, context),
286             "audio spatialization manager state is error.");
287         if (argc == ARGS_ONE) {
288             context->intValue = napiAudioSpatializationManager->audioSpatializationMngr_->SetSpatializationEnabled(
289                 context->spatializationEnable);
290         } else if (argc == ARGS_TWO) {
291             context->intValue = napiAudioSpatializationManager->audioSpatializationMngr_->SetSpatializationEnabled(
292                 context->deviceDescriptor, context->spatializationEnable);
293         }
294 
295         if (context->intValue == ERR_PERMISSION_DENIED) {
296             context->SignError(NAPI_ERR_NO_PERMISSION);
297         } else if (context->intValue != SUCCESS) {
298             context->SignError(NAPI_ERR_SYSTEM);
299         }
300     };
301 
302     auto complete = [env](napi_value &output) {
303         output = NapiParamUtils::GetUndefinedValue(env);
304     };
305     return NapiAsyncWork::Enqueue(env, context, "SetSpatializationEnabled", executor, complete);
306 }
307 
IsHeadTrackingEnabled(napi_env env,napi_callback_info info)308 napi_value NapiAudioSpatializationManager::IsHeadTrackingEnabled(napi_env env, napi_callback_info info)
309 {
310     AUDIO_INFO_LOG("IsHeadTrackingEnabled in");
311     napi_value result = nullptr;
312     CHECK_AND_RETURN_RET_LOG(PermissionUtil::VerifySelfPermission(),
313         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED), "No system permission");
314 
315     bool isHeadTrackingEnabled = false;
316     const size_t requireArgc = ARGS_ONE;
317     size_t argc = PARAM1;
318     napi_value args[ARGS_ONE] = {};
319     auto *napiAudioSpatializationManager = GetParamWithSync(env, info, argc, args);
320     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager != nullptr, result,
321         "napiAudioSpatializationManager is nullptr");
322     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager->audioSpatializationMngr_ != nullptr, result,
323         "audioSpatializationMngr_ is nullptr");
324 
325     if (argc == requireArgc) {
326         bool argTransFlag = true;
327         napi_valuetype valueType = napi_undefined;
328         napi_typeof(env, args[PARAM0], &valueType);
329         CHECK_AND_RETURN_RET_LOG(valueType == napi_object, NapiAudioError::ThrowErrorAndReturn(env,
330         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of deviceDescriptor must be object"),
331             "invalid valueType");
332 
333         sptr<AudioDeviceDescriptor> selectedAudioDevice = new (std::nothrow) AudioDeviceDescriptor();
334         NapiParamUtils::GetAudioDeviceDescriptor(env, selectedAudioDevice, argTransFlag, args[PARAM0]);
335         CHECK_AND_RETURN_RET_LOG(argTransFlag == true, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
336             "parameter verification failed: The param of deviceDescriptor must be interface AudioDeviceDescriptor"),
337             "invalid parameter");
338 
339         isHeadTrackingEnabled = napiAudioSpatializationManager->audioSpatializationMngr_
340             ->IsHeadTrackingEnabled(selectedAudioDevice);
341     } else if (argc < requireArgc) {
342         isHeadTrackingEnabled = napiAudioSpatializationManager->audioSpatializationMngr_->IsHeadTrackingEnabled();
343     } else {
344         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID, "invalid arguments");
345         return NapiParamUtils::GetUndefinedValue(env);
346     }
347     NapiParamUtils::SetValueBoolean(env, isHeadTrackingEnabled, result);
348     return result;
349 }
350 
SetHeadTrackingEnabled(napi_env env,napi_callback_info info)351 napi_value NapiAudioSpatializationManager::SetHeadTrackingEnabled(napi_env env, napi_callback_info info)
352 {
353     CHECK_AND_RETURN_RET_LOG(PermissionUtil::VerifySelfPermission(),
354         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED), "No system permission");
355 
356     size_t requireArgc = ARGS_ONE;
357     auto context = std::make_shared<AudioSpatializationManagerAsyncContext>();
358     if (context == nullptr) {
359         AUDIO_ERR_LOG("SetHeadTrackingEnabled failed : no memory");
360         NapiAudioError::ThrowError(env, "SetHeadTrackingEnabled failed : no memory", NAPI_ERR_NO_MEMORY);
361         return NapiParamUtils::GetUndefinedValue(env);
362     }
363 
364     auto inputParser = [env, context, &requireArgc](size_t argc, napi_value *argv) {
365         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "mandatory parameters are left unspecified",
366             NAPI_ERR_INPUT_INVALID);
367         bool argTransFlag = true;
368         if (argc == ARGS_ONE) {
369             context->status = NapiParamUtils::GetValueBoolean(env, context->headTrackingEnable, argv[PARAM0]);
370             NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
371                 "incorrect parameter types: The type of enable must be boolean", NAPI_ERR_INPUT_INVALID);
372         } else if (argc == ARGS_TWO) {
373             context->status = NapiParamUtils::GetValueBoolean(env, context->headTrackingEnable, argv[PARAM0]);
374             if (context->status == napi_ok) {
375                 requireArgc = ARGS_ONE;
376             } else {
377                 requireArgc = ARGS_TWO;
378                 context->status = NapiParamUtils::GetAudioDeviceDescriptor(env, context->deviceDescriptor, argTransFlag,
379                     argv[PARAM0]);
380                 NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
381                     "incorrect parameter types: The param of deviceDescriptor must be interface AudioDeviceDescriptor",
382                     NAPI_ERR_INPUT_INVALID);
383                 context->status = NapiParamUtils::GetValueBoolean(env, context->headTrackingEnable, argv[PARAM1]);
384                 NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
385                     "incorrect parameter types: The type of enable must be boolean", NAPI_ERR_INPUT_INVALID);
386             }
387         }
388     };
389     context->GetCbInfo(env, info, inputParser);
390     if (context->status != napi_ok) {
391         NapiAudioError::ThrowError(env, context->errCode);
392         return NapiParamUtils::GetUndefinedValue(env);
393     }
394 
395     return updateHeadTrackingEnabled(env, requireArgc, context);
396 }
397 
updateHeadTrackingEnabled(napi_env env,const std::size_t argc,std::shared_ptr<AudioSpatializationManagerAsyncContext> & context)398 napi_value NapiAudioSpatializationManager::updateHeadTrackingEnabled(napi_env env, const std::size_t argc,
399     std::shared_ptr<AudioSpatializationManagerAsyncContext> &context)
400 {
401     auto executor = [context, argc]() {
402         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
403         auto obj = reinterpret_cast<NapiAudioSpatializationManager*>(context->native);
404         ObjectRefMap objectGuard(obj);
405         auto *napiAudioSpatializationManager = objectGuard.GetPtr();
406         CHECK_AND_RETURN_LOG(CheckAudioSpatializationManagerStatus(napiAudioSpatializationManager, context),
407             "audio spatialization manager state is error.");
408         if (argc == ARGS_ONE) {
409             context->intValue = napiAudioSpatializationManager->audioSpatializationMngr_->SetHeadTrackingEnabled(
410                 context->headTrackingEnable);
411         } else if (argc == ARGS_TWO) {
412             context->intValue = napiAudioSpatializationManager->audioSpatializationMngr_->SetHeadTrackingEnabled(
413                 context->deviceDescriptor, context->headTrackingEnable);
414         }
415 
416         if (context->intValue == ERR_PERMISSION_DENIED) {
417             context->SignError(NAPI_ERR_NO_PERMISSION);
418         } else if (context->intValue != SUCCESS) {
419             context->SignError(NAPI_ERR_SYSTEM);
420         }
421     };
422 
423     auto complete = [env](napi_value &output) {
424         output = NapiParamUtils::GetUndefinedValue(env);
425     };
426     return NapiAsyncWork::Enqueue(env, context, "SetHeadTrackingEnabled", executor, complete);
427 }
428 
IsSpatializationSupported(napi_env env,napi_callback_info info)429 napi_value NapiAudioSpatializationManager::IsSpatializationSupported(napi_env env, napi_callback_info info)
430 {
431     AUDIO_DEBUG_LOG("IsSpatializationSupported in");
432     CHECK_AND_RETURN_RET_LOG(PermissionUtil::VerifySelfPermission(),
433         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED), "No system permission");
434 
435     napi_value result = nullptr;
436     size_t argc = PARAM0;
437     auto *napiAudioSpatializationManager = GetParamWithSync(env, info, argc, nullptr);
438     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID),
439         "invalid arguments");
440     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager != nullptr, result,
441         "napiAudioSpatializationManager is nullptr");
442     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager->audioSpatializationMngr_ != nullptr, result,
443         "audioSpatializationMngr_ is nullptr");
444     bool isSpatializationSupported =
445         napiAudioSpatializationManager->audioSpatializationMngr_->IsSpatializationSupported();
446     NapiParamUtils::SetValueBoolean(env, isSpatializationSupported, result);
447 
448     return result;
449 }
450 
IsSpatializationSupportedForDevice(napi_env env,napi_callback_info info)451 napi_value NapiAudioSpatializationManager::IsSpatializationSupportedForDevice(napi_env env, napi_callback_info info)
452 {
453     AUDIO_DEBUG_LOG("IsSpatializationSupportedForDevice");
454     CHECK_AND_RETURN_RET_LOG(PermissionUtil::VerifySelfPermission(),
455         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED), "No system permission");
456 
457     napi_value result = nullptr;
458     bool argTransFlag = true;
459     size_t argc = ARGS_ONE;
460     napi_value args[ARGS_ONE] = {};
461     auto *napiAudioSpatializationManager = GetParamWithSync(env, info, argc, args);
462     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
463         "mandatory parameters are left unspecified"), "invalid arguments");
464 
465     napi_valuetype valueType = napi_undefined;
466     napi_typeof(env, args[PARAM0], &valueType);
467     CHECK_AND_RETURN_RET_LOG(valueType == napi_object, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
468         "incorrect parameter types: The type of deviceDescriptor must be object"), "invalid valueType");
469 
470     sptr<AudioDeviceDescriptor> selectedAudioDevice = new (std::nothrow) AudioDeviceDescriptor();
471     NapiParamUtils::GetAudioDeviceDescriptor(env, selectedAudioDevice, argTransFlag, args[PARAM0]);
472     CHECK_AND_RETURN_RET_LOG(argTransFlag == true, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
473         "parameter verification failed: The param of deviceDescriptor must be interface AudioDeviceDescriptor"),
474         "invalid parameter");
475     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager != nullptr, result,
476         "napiAudioSpatializationManager is nullptr");
477     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager->audioSpatializationMngr_ != nullptr, result,
478         "audioSpatializationMngr_ is nullptr");
479 
480     bool isSpatializationSupportedForDevice = napiAudioSpatializationManager
481         ->audioSpatializationMngr_->IsSpatializationSupportedForDevice(selectedAudioDevice);
482     NapiParamUtils::SetValueBoolean(env, isSpatializationSupportedForDevice, result);
483     return result;
484 }
485 
IsHeadTrackingSupported(napi_env env,napi_callback_info info)486 napi_value NapiAudioSpatializationManager::IsHeadTrackingSupported(napi_env env, napi_callback_info info)
487 {
488     AUDIO_DEBUG_LOG("IsHeadTrackingSupported in");
489     CHECK_AND_RETURN_RET_LOG(PermissionUtil::VerifySelfPermission(),
490         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED), "No system permission");
491 
492     napi_value result = nullptr;
493     size_t argc = PARAM0;
494     auto *napiAudioSpatializationManager = GetParamWithSync(env, info, argc, nullptr);
495     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID),
496         "invalid arguments");
497     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager != nullptr, result,
498         "napiAudioSpatializationManager is nullptr");
499     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager->audioSpatializationMngr_ != nullptr, result,
500         "audioSpatializationMngr_ is nullptr");
501     bool isHeadTrackingSupported =
502         napiAudioSpatializationManager->audioSpatializationMngr_->IsHeadTrackingSupported();
503     NapiParamUtils::SetValueBoolean(env, isHeadTrackingSupported, result);
504     return result;
505 }
506 
IsHeadTrackingSupportedForDevice(napi_env env,napi_callback_info info)507 napi_value NapiAudioSpatializationManager::IsHeadTrackingSupportedForDevice(napi_env env, napi_callback_info info)
508 {
509     CHECK_AND_RETURN_RET_LOG(PermissionUtil::VerifySelfPermission(),
510         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED), "No system permission");
511 
512     napi_value result = nullptr;
513     bool argTransFlag = true;
514     size_t argc = ARGS_ONE;
515     napi_value args[ARGS_ONE] = {};
516     auto *napiAudioSpatializationManager = GetParamWithSync(env, info, argc, args);
517     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
518         "mandatory parameters are left unspecified"), "invalid arguments");
519 
520     napi_valuetype valueType = napi_undefined;
521     napi_typeof(env, args[PARAM0], &valueType);
522     CHECK_AND_RETURN_RET_LOG(valueType == napi_object, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
523         "incorrect parameter types: The type of deviceDescriptor must be object"), "invalid valueType");
524 
525     sptr<AudioDeviceDescriptor> selectedAudioDevice = new (std::nothrow) AudioDeviceDescriptor();
526     NapiParamUtils::GetAudioDeviceDescriptor(env, selectedAudioDevice, argTransFlag, args[PARAM0]);
527     CHECK_AND_RETURN_RET_LOG(argTransFlag == true, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
528         "parameter verification failed: The param of deviceDescriptor must be interface AudioDeviceDescriptor"),
529         "invalid parameter");
530 
531     bool isHeadTrackingSupportedForDevice = napiAudioSpatializationManager
532         ->audioSpatializationMngr_->IsHeadTrackingSupportedForDevice(selectedAudioDevice);
533     NapiParamUtils::SetValueBoolean(env, isHeadTrackingSupportedForDevice, result);
534     return result;
535 }
536 
UpdateSpatialDeviceState(napi_env env,napi_callback_info info)537 napi_value NapiAudioSpatializationManager::UpdateSpatialDeviceState(napi_env env, napi_callback_info info)
538 {
539     AUDIO_INFO_LOG("UpdateSpatialDeviceState");
540     CHECK_AND_RETURN_RET_LOG(PermissionUtil::VerifySelfPermission(),
541         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED), "No system permission");
542 
543     napi_value result = nullptr;
544     size_t argc = ARGS_ONE;
545     napi_value args[ARGS_ONE] = {};
546     auto *napiAudioSpatializationManager = GetParamWithSync(env, info, argc, args);
547     CHECK_AND_RETURN_RET_LOG(argc >= ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
548         "mandatory parameters are left unspecified"), "invalid arguments");
549 
550     AudioSpatialDeviceState audioSpatialDeviceState;
551     if (NapiParamUtils::GetSpatialDeviceState(env, &audioSpatialDeviceState, args[PARAM0]) != napi_ok) {
552         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
553             "parameter verification failed: The param of spatialDeviceState must be interface AudioSpatialDeviceState");
554     }
555     if (napiAudioSpatializationManager == nullptr || napiAudioSpatializationManager
556             ->audioSpatializationMngr_ == nullptr) {
557         AUDIO_ERR_LOG("napiAudioSpatializationManager or audioSpatializationMngr_ is  nullptr");
558         return nullptr;
559     }
560     int32_t ret = napiAudioSpatializationManager->audioSpatializationMngr_->UpdateSpatialDeviceState(
561         audioSpatialDeviceState);
562     if (ret == ERR_PERMISSION_DENIED) {
563         NapiAudioError::ThrowError(env, NAPI_ERR_NO_PERMISSION);
564     }
565     return result;
566 }
567 
GetSpatializationSceneType(napi_env env,napi_callback_info info)568 napi_value NapiAudioSpatializationManager::GetSpatializationSceneType(napi_env env, napi_callback_info info)
569 {
570     AUDIO_INFO_LOG("Start to get current spatialization rendering scene type");
571     napi_value result = nullptr;
572     CHECK_AND_RETURN_RET_LOG(PermissionUtil::VerifySelfPermission(),
573         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED), "No system permission");
574 
575     size_t argc = PARAM0;
576     auto *napiAudioSpatializationManager = GetParamWithSync(env, info, argc, nullptr);
577     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID),
578         "invalid arguments");
579     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager != nullptr, result,
580         "napiAudioSpatializationManager is nullptr");
581     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager->audioSpatializationMngr_ != nullptr, result,
582         "audioSpatializationMngr_ is nullptr");
583     AudioSpatializationSceneType sceneType =
584         napiAudioSpatializationManager->audioSpatializationMngr_->GetSpatializationSceneType();
585     NapiParamUtils::SetValueInt32(env, static_cast<int32_t>(sceneType), result);
586 
587     return result;
588 }
589 
SetSpatializationSceneType(napi_env env,napi_callback_info info)590 napi_value NapiAudioSpatializationManager::SetSpatializationSceneType(napi_env env, napi_callback_info info)
591 {
592     AUDIO_INFO_LOG("Start to set spatialization rendering scene type");
593     CHECK_AND_RETURN_RET_LOG(PermissionUtil::VerifySelfPermission(),
594         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED), "No system permission");
595 
596     napi_value result = nullptr;
597     size_t argc = ARGS_ONE;
598     napi_value args[ARGS_ONE] = {};
599     auto *napiAudioSpatializationManager = GetParamWithSync(env, info, argc, args);
600     CHECK_AND_RETURN_RET_LOG(argc >= ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
601         "mandatory parameters are left unspecified"), "invalid arguments");
602 
603     napi_valuetype valueType = napi_undefined;
604     napi_typeof(env, args[PARAM0], &valueType);
605     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
606         "incorrect parameter types: The type of spatializationSceneType must be number"), "invalid valueType");
607 
608     int32_t sceneType;
609     NapiParamUtils::GetValueInt32(env, sceneType, args[PARAM0]);
610     CHECK_AND_RETURN_RET_LOG(NapiAudioEnum::IsLegalInputArgumentSpatializationSceneType(sceneType),
611         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
612         "parameter verification failed: The param of spatializationSceneType must be \
613         enum AudioSpatializationSceneType"), "get sceneType failed");
614 
615     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager != nullptr, result,
616         "napiAudioSpatializationManager is nullptr");
617     CHECK_AND_RETURN_RET_LOG(napiAudioSpatializationManager->audioSpatializationMngr_ != nullptr, result,
618         "audioSpatializationMngr_ is nullptr");
619     int32_t ret = napiAudioSpatializationManager->audioSpatializationMngr_->SetSpatializationSceneType(
620         static_cast<AudioSpatializationSceneType>(sceneType));
621     if (ret == ERR_PERMISSION_DENIED) {
622         NapiAudioError::ThrowError(env, NAPI_ERR_NO_PERMISSION);
623     }
624     return result;
625 }
626 
RegisterCallback(napi_env env,napi_value jsThis,napi_value * args,const std::string & cbName)627 void NapiAudioSpatializationManager::RegisterCallback(napi_env env, napi_value jsThis,
628     napi_value *args, const std::string &cbName)
629 {
630     NapiAudioSpatializationManager *napiAudioSpatializationManager = nullptr;
631     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiAudioSpatializationManager));
632     if ((status != napi_ok) || (napiAudioSpatializationManager == nullptr) ||
633         (napiAudioSpatializationManager->audioSpatializationMngr_ == nullptr)) {
634         AUDIO_ERR_LOG("NapiAudioSpatializationManager::Failed to retrieve audio spatialization manager napi instance.");
635         return;
636     }
637 
638     if (!cbName.compare(SPATIALIZATION_ENABLED_CHANGE_CALLBACK_NAME)) {
639         RegisterSpatializationEnabledChangeCallback(env, args, cbName, napiAudioSpatializationManager);
640     } else if (!cbName.compare(SPATIALIZATION_ENABLED_CHANGE_FOR_ANY_DEVICES_CALLBACK_NAME)) {
641         RegisterSpatializationEnabledChangeCallback(env, args, cbName, napiAudioSpatializationManager);
642     } else if (!cbName.compare(HEAD_TRACKING_ENABLED_CHANGE_CALLBACK_NAME)) {
643         RegisterHeadTrackingEnabledChangeCallback(env, args, cbName, napiAudioSpatializationManager);
644     } else if (!cbName.compare(HEAD_TRACKING_ENABLED_CHANGE_FOR_ANY_DEVICES_CALLBACK_NAME)) {
645         RegisterHeadTrackingEnabledChangeCallback(env, args, cbName, napiAudioSpatializationManager);
646     } else {
647         AUDIO_ERR_LOG("NapiAudioSpatializationManager::No such callback supported");
648         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
649             "parameter verification failed: The param of type is not supported");
650     }
651 }
652 
RegisterSpatializationEnabledChangeCallback(napi_env env,napi_value * args,const std::string & cbName,NapiAudioSpatializationManager * napiAudioSpatializationManager)653 void NapiAudioSpatializationManager::RegisterSpatializationEnabledChangeCallback(napi_env env, napi_value *args,
654     const std::string &cbName, NapiAudioSpatializationManager *napiAudioSpatializationManager)
655 {
656     if (!napiAudioSpatializationManager->spatializationEnabledChangeCallbackNapi_) {
657         napiAudioSpatializationManager->spatializationEnabledChangeCallbackNapi_ =
658             std::make_shared<NapiAudioSpatializationEnabledChangeCallback>(env);
659         CHECK_AND_RETURN_LOG(napiAudioSpatializationManager->spatializationEnabledChangeCallbackNapi_ != nullptr,
660             "NapiAudioSpatializationManager: Memory Allocation Failed !!");
661 
662         int32_t ret = napiAudioSpatializationManager->audioSpatializationMngr_->
663             RegisterSpatializationEnabledEventListener(
664             napiAudioSpatializationManager->spatializationEnabledChangeCallbackNapi_);
665         CHECK_AND_RETURN_LOG(ret == SUCCESS,
666             "NapiAudioSpatializationManager: Registering of Spatialization Enabled Change Callback Failed");
667     }
668 
669     std::shared_ptr<NapiAudioSpatializationEnabledChangeCallback> cb =
670         std::static_pointer_cast<NapiAudioSpatializationEnabledChangeCallback>
671         (napiAudioSpatializationManager->spatializationEnabledChangeCallbackNapi_);
672     cb->SaveSpatializationEnabledChangeCallbackReference(args[PARAM1], cbName);
673 
674     AUDIO_INFO_LOG("Register spatialization enabled callback is successful");
675 }
676 
RegisterHeadTrackingEnabledChangeCallback(napi_env env,napi_value * args,const std::string & cbName,NapiAudioSpatializationManager * napiAudioSpatializationManager)677 void NapiAudioSpatializationManager::RegisterHeadTrackingEnabledChangeCallback(napi_env env, napi_value *args,
678     const std::string &cbName, NapiAudioSpatializationManager *napiAudioSpatializationManager)
679 {
680     if (!napiAudioSpatializationManager->headTrackingEnabledChangeCallbackNapi_) {
681         napiAudioSpatializationManager->headTrackingEnabledChangeCallbackNapi_ =
682             std::make_shared<NapiAudioHeadTrackingEnabledChangeCallback>(env);
683         CHECK_AND_RETURN_LOG(napiAudioSpatializationManager->headTrackingEnabledChangeCallbackNapi_ != nullptr,
684             "NapiAudioSpatializationManager: Memory Allocation Failed !!");
685 
686         int32_t ret = napiAudioSpatializationManager->audioSpatializationMngr_->
687             RegisterHeadTrackingEnabledEventListener(
688             napiAudioSpatializationManager->headTrackingEnabledChangeCallbackNapi_);
689         CHECK_AND_RETURN_LOG(ret == SUCCESS,
690             "NapiAudioSpatializationManager: Registering of Head Tracking Enabled Change Callback Failed");
691     }
692 
693     std::shared_ptr<NapiAudioHeadTrackingEnabledChangeCallback> cb =
694         std::static_pointer_cast<NapiAudioHeadTrackingEnabledChangeCallback>
695         (napiAudioSpatializationManager->headTrackingEnabledChangeCallbackNapi_);
696     cb->SaveHeadTrackingEnabledChangeCallbackReference(args[PARAM1], cbName);
697 
698     AUDIO_INFO_LOG("Register head tracking enabled callback is successful");
699 }
700 
On(napi_env env,napi_callback_info info)701 napi_value NapiAudioSpatializationManager::On(napi_env env, napi_callback_info info)
702 {
703     CHECK_AND_RETURN_RET_LOG(PermissionUtil::VerifySelfPermission(),
704         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED), "No system permission");
705 
706     const size_t requireArgc = ARGS_TWO;
707     size_t argc = ARGS_THREE;
708     napi_value undefinedResult = nullptr;
709     napi_get_undefined(env, &undefinedResult);
710 
711     napi_value args[requireArgc + 1] = {nullptr, nullptr, nullptr};
712     napi_value jsThis = nullptr;
713     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
714     if (status != napi_ok || argc < requireArgc) {
715         AUDIO_ERR_LOG("On fail to napi_get_cb_info/Requires min 2 parameters");
716         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified");
717     }
718 
719     napi_valuetype eventType = napi_undefined;
720     if (napi_typeof(env, args[PARAM0], &eventType) != napi_ok || eventType != napi_string) {
721         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
722             "incorrect parameter types: The type of eventType must be string");
723         return undefinedResult;
724     }
725     std::string callbackName = NapiParamUtils::GetStringArgument(env, args[PARAM0]);
726     AUDIO_DEBUG_LOG("On callbackName: %{public}s", callbackName.c_str());
727 
728     napi_valuetype handler = napi_undefined;
729     if (napi_typeof(env, args[PARAM1], &handler) != napi_ok || handler != napi_function) {
730         AUDIO_ERR_LOG("On type mismatch for parameter 2");
731         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
732             "incorrect parameter types: The type of callback must be function");
733         return undefinedResult;
734     }
735 
736     RegisterCallback(env, jsThis, args, callbackName);
737 
738     return undefinedResult;
739 }
740 
UnRegisterCallback(napi_env env,napi_value jsThis,napi_value * args,const std::string & cbName)741 void NapiAudioSpatializationManager::UnRegisterCallback(napi_env env, napi_value jsThis,
742     napi_value *args, const std::string &cbName)
743 {
744     NapiAudioSpatializationManager *napiAudioSpatializationManager = nullptr;
745     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiAudioSpatializationManager));
746     CHECK_AND_RETURN_LOG(status == napi_ok && napiAudioSpatializationManager != nullptr,
747         "Failed to retrieve napi instance.");
748     CHECK_AND_RETURN_LOG(napiAudioSpatializationManager->audioSpatializationMngr_ != nullptr,
749         "spatialization instance null.");
750 
751     if (!cbName.compare(SPATIALIZATION_ENABLED_CHANGE_CALLBACK_NAME)) {
752         UnregisterSpatializationEnabledChangeCallback(env, args[PARAM1], cbName, napiAudioSpatializationManager);
753     } else if (!cbName.compare(SPATIALIZATION_ENABLED_CHANGE_FOR_ANY_DEVICES_CALLBACK_NAME)) {
754         UnregisterSpatializationEnabledChangeCallback(env, args[PARAM1], cbName, napiAudioSpatializationManager);
755     } else if (!cbName.compare(HEAD_TRACKING_ENABLED_CHANGE_CALLBACK_NAME)) {
756         UnregisterHeadTrackingEnabledChangeCallback(env, args[PARAM1], cbName, napiAudioSpatializationManager);
757     } else if (!cbName.compare(HEAD_TRACKING_ENABLED_CHANGE_FOR_ANY_DEVICES_CALLBACK_NAME)) {
758         UnregisterHeadTrackingEnabledChangeCallback(env, args[PARAM1], cbName, napiAudioSpatializationManager);
759     } else {
760         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
761             "parameter verification failed: The param of type is not supported");
762     }
763 }
764 
UnregisterSpatializationEnabledChangeCallback(napi_env env,napi_value callback,const std::string & cbName,NapiAudioSpatializationManager * napiAudioSpatializationManager)765 void NapiAudioSpatializationManager::UnregisterSpatializationEnabledChangeCallback(napi_env env, napi_value callback,
766     const std::string &cbName, NapiAudioSpatializationManager *napiAudioSpatializationManager)
767 {
768     if (napiAudioSpatializationManager->spatializationEnabledChangeCallbackNapi_ != nullptr) {
769         std::shared_ptr<NapiAudioSpatializationEnabledChangeCallback> cb =
770             std::static_pointer_cast<NapiAudioSpatializationEnabledChangeCallback>(
771             napiAudioSpatializationManager->spatializationEnabledChangeCallbackNapi_);
772         if (callback != nullptr) {
773             cb->RemoveSpatializationEnabledChangeCallbackReference(env, callback, cbName);
774         }
775         if (callback == nullptr || cb->GetSpatializationEnabledChangeCbListSize(cbName) == 0) {
776             int32_t ret = napiAudioSpatializationManager->audioSpatializationMngr_->
777                 UnregisterSpatializationEnabledEventListener();
778             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnregisterSpatializationEnabledEventListener Failed");
779             napiAudioSpatializationManager->spatializationEnabledChangeCallbackNapi_.reset();
780             napiAudioSpatializationManager->spatializationEnabledChangeCallbackNapi_ = nullptr;
781             cb->RemoveAllSpatializationEnabledChangeCallbackReference(cbName);
782         }
783     } else {
784         AUDIO_ERR_LOG("UnregisterSpatializationEnabledChangeCb: spatializationEnabledChangeCallbackNapi_ is null");
785     }
786 }
787 
UnregisterHeadTrackingEnabledChangeCallback(napi_env env,napi_value callback,const std::string & cbName,NapiAudioSpatializationManager * napiAudioSpatializationManager)788 void NapiAudioSpatializationManager::UnregisterHeadTrackingEnabledChangeCallback(napi_env env, napi_value callback,
789     const std::string &cbName, NapiAudioSpatializationManager *napiAudioSpatializationManager)
790 {
791     if (napiAudioSpatializationManager->headTrackingEnabledChangeCallbackNapi_ != nullptr) {
792         std::shared_ptr<NapiAudioHeadTrackingEnabledChangeCallback> cb =
793             std::static_pointer_cast<NapiAudioHeadTrackingEnabledChangeCallback>(
794             napiAudioSpatializationManager->headTrackingEnabledChangeCallbackNapi_);
795         if (callback != nullptr) {
796             cb->RemoveHeadTrackingEnabledChangeCallbackReference(env, callback, cbName);
797         }
798         if (callback == nullptr || cb->GetHeadTrackingEnabledChangeCbListSize(cbName) == 0) {
799             int32_t ret = napiAudioSpatializationManager->audioSpatializationMngr_->
800                 UnregisterHeadTrackingEnabledEventListener();
801             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnregisterHeadTrackingEnabledEventListener Failed");
802             napiAudioSpatializationManager->headTrackingEnabledChangeCallbackNapi_.reset();
803             napiAudioSpatializationManager->headTrackingEnabledChangeCallbackNapi_ = nullptr;
804             cb->RemoveAllHeadTrackingEnabledChangeCallbackReference(cbName);
805         }
806     } else {
807         AUDIO_ERR_LOG("UnregisterHeadTrackingEnabledChangeCb: headTrackingEnabledChangeCallbackNapi_ is null");
808     }
809 }
810 
Off(napi_env env,napi_callback_info info)811 napi_value NapiAudioSpatializationManager::Off(napi_env env, napi_callback_info info)
812 {
813     CHECK_AND_RETURN_RET_LOG(PermissionUtil::VerifySelfPermission(),
814         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED), "No system permission");
815     const size_t requireArgc = ARGS_ONE;
816     size_t argc = PARAM2;
817 
818     napi_value undefinedResult = nullptr;
819     napi_get_undefined(env, &undefinedResult);
820 
821     napi_value args[requireArgc + 1] = {nullptr, nullptr};
822     napi_value jsThis = nullptr;
823     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
824     if (status != napi_ok || argc < requireArgc) {
825         AUDIO_ERR_LOG("Off fail to napi_get_cb_info/Requires min 1 parameters");
826         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified");
827         return undefinedResult;
828     }
829 
830     napi_valuetype eventType = napi_undefined;
831     if (napi_typeof(env, args[PARAM0], &eventType) != napi_ok || eventType != napi_string) {
832         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
833             "incorrect parameter types: The type of eventType must be string");
834         return undefinedResult;
835     }
836 
837     napi_valuetype secondArgsType = napi_undefined;
838     if (argc > requireArgc &&
839         (napi_typeof(env, args[PARAM1], &secondArgsType) != napi_ok || secondArgsType != napi_function)) {
840         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
841             "incorrect parameter types: The type of callback must be function");
842         return undefinedResult;
843     }
844     std::string callbackName = NapiParamUtils::GetStringArgument(env, args[PARAM0]);
845 
846     if (argc == requireArgc) {
847         args[PARAM1] = nullptr;
848     }
849     AUDIO_DEBUG_LOG("AudioSpatializationManagerNapi: Off callbackName: %{public}s", callbackName.c_str());
850 
851     UnRegisterCallback(env, jsThis, args, callbackName);
852 
853     return undefinedResult;
854 }
855 } // namespace AudioStandard
856 } // namespace OHOS
857