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 "NapiAudioRoutingManager"
17 #endif
18 
19 #include "napi_audio_routing_manager.h"
20 #include "napi_audio_error.h"
21 #include "napi_param_utils.h"
22 #include "napi_audio_enum.h"
23 #include "audio_errors.h"
24 #include "audio_manager_log.h"
25 #include "napi_audio_manager_callbacks.h"
26 #include "napi_audio_rounting_available_devicechange_callback.h"
27 #include "napi_audio_routing_manager_callbacks.h"
28 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
29 #include "parameters.h"
30 #endif
31 
32 namespace OHOS {
33 namespace AudioStandard {
34 using namespace std;
35 using namespace HiviewDFX;
36 static __thread napi_ref g_routingManagerConstructor = nullptr;
37 
NapiAudioRoutingManager()38 NapiAudioRoutingManager::NapiAudioRoutingManager()
39     : audioMngr_(nullptr), env_(nullptr) {}
40 
41 NapiAudioRoutingManager::~NapiAudioRoutingManager() = default;
42 
Destructor(napi_env env,void * nativeObject,void * finalizeHint)43 void NapiAudioRoutingManager::Destructor(napi_env env, void *nativeObject, void *finalizeHint)
44 {
45     if (nativeObject != nullptr) {
46         auto obj = static_cast<NapiAudioRoutingManager *>(nativeObject);
47         ObjectRefMap<NapiAudioRoutingManager>::DecreaseRef(obj);
48     }
49     AUDIO_INFO_LOG("Destructor is successful");
50 }
51 
Construct(napi_env env,napi_callback_info info)52 napi_value NapiAudioRoutingManager::Construct(napi_env env, napi_callback_info info)
53 {
54     napi_status status;
55     napi_value result = nullptr;
56     napi_get_undefined(env, &result);
57 
58     size_t argc = ARGS_TWO;
59     napi_value argv[ARGS_TWO] = {0};
60     napi_value thisVar = nullptr;
61     void *data = nullptr;
62     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
63     unique_ptr<NapiAudioRoutingManager> napiAudioRoutingManager = make_unique<NapiAudioRoutingManager>();
64     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "No memory");
65 
66     napiAudioRoutingManager->audioMngr_ = AudioSystemManager::GetInstance();
67     napiAudioRoutingManager->audioRoutingMngr_ = AudioRoutingManager::GetInstance();
68     napiAudioRoutingManager->env_ = env;
69     ObjectRefMap<NapiAudioRoutingManager>::Insert(napiAudioRoutingManager.get());
70 
71     status = napi_wrap(env, thisVar, static_cast<void*>(napiAudioRoutingManager.get()),
72         NapiAudioRoutingManager::Destructor, nullptr, nullptr);
73     if (status != napi_ok) {
74         ObjectRefMap<NapiAudioRoutingManager>::Erase(napiAudioRoutingManager.get());
75         return result;
76     }
77     napiAudioRoutingManager.release();
78     return thisVar;
79 }
80 
Init(napi_env env,napi_value exports)81 napi_value NapiAudioRoutingManager::Init(napi_env env, napi_value exports)
82 {
83     napi_status status;
84     napi_value constructor;
85     napi_value result = nullptr;
86     const int32_t refCount = ARGS_ONE;
87     napi_get_undefined(env, &result);
88 
89     napi_property_descriptor audio_routing_manager_properties[] = {
90         DECLARE_NAPI_FUNCTION("getDevices", GetDevices),
91         DECLARE_NAPI_FUNCTION("getDevicesSync", GetDevicesSync),
92         DECLARE_NAPI_FUNCTION("selectOutputDevice", SelectOutputDevice),
93         DECLARE_NAPI_FUNCTION("selectOutputDeviceByFilter", SelectOutputDeviceByFilter),
94         DECLARE_NAPI_FUNCTION("selectInputDevice", SelectInputDevice),
95         DECLARE_NAPI_FUNCTION("selectInputDeviceByFilter", SelectInputDeviceByFilter),
96         DECLARE_NAPI_FUNCTION("setCommunicationDevice", SetCommunicationDevice),
97         DECLARE_NAPI_FUNCTION("isCommunicationDeviceActive", IsCommunicationDeviceActive),
98         DECLARE_NAPI_FUNCTION("isCommunicationDeviceActiveSync", IsCommunicationDeviceActiveSync),
99         DECLARE_NAPI_FUNCTION("getActiveOutputDeviceDescriptors", GetActiveOutputDeviceDescriptors),
100         DECLARE_NAPI_FUNCTION("getPreferredOutputDeviceForRendererInfo", GetPreferredOutputDeviceForRendererInfo),
101         DECLARE_NAPI_FUNCTION("getPreferOutputDeviceForRendererInfo", GetPreferOutputDeviceForRendererInfo),
102         DECLARE_NAPI_FUNCTION("getPreferredOutputDeviceForRendererInfoSync",
103             GetPreferredOutputDeviceForRendererInfoSync),
104         DECLARE_NAPI_FUNCTION("getPreferredInputDeviceForCapturerInfo", GetPreferredInputDeviceForCapturerInfo),
105         DECLARE_NAPI_FUNCTION("getPreferredInputDeviceForCapturerInfoSync", GetPreferredInputDeviceForCapturerInfoSync),
106         DECLARE_NAPI_FUNCTION("getAvailableMicrophones", GetAvailableMicrophones),
107         DECLARE_NAPI_FUNCTION("getAvailableDevices", GetAvailableDevices),
108         DECLARE_NAPI_FUNCTION("on", On),
109         DECLARE_NAPI_FUNCTION("off", Off),
110 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
111         DECLARE_NAPI_FUNCTION("isMicBlockDetectionSupported", IsMicBlockDetectionSupported),
112 #endif
113     };
114 
115     status = napi_define_class(env, NAPI_AUDIO_ROUTING_MANAGER_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct,
116         nullptr, sizeof(audio_routing_manager_properties) / sizeof(audio_routing_manager_properties[PARAM0]),
117         audio_routing_manager_properties, &constructor);
118     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_define_class fail");
119 
120     status = napi_create_reference(env, constructor, refCount, &g_routingManagerConstructor);
121     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_create_reference fail");
122     status = napi_set_named_property(env, exports, NAPI_AUDIO_ROUTING_MANAGER_CLASS_NAME.c_str(), constructor);
123     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_set_named_property fail");
124     return exports;
125 }
126 
CheckContextStatus(std::shared_ptr<AudioRoutingManagerAsyncContext> context)127 bool NapiAudioRoutingManager::CheckContextStatus(std::shared_ptr<AudioRoutingManagerAsyncContext> context)
128 {
129     CHECK_AND_RETURN_RET_LOG(context != nullptr, false, "context object is nullptr.");
130     if (context->native == nullptr) {
131         context->SignError(NAPI_ERR_SYSTEM);
132         AUDIO_ERR_LOG("context object state is error.");
133         return false;
134     }
135     return true;
136 }
137 
CheckAudioRoutingManagerStatus(NapiAudioRoutingManager * napi,std::shared_ptr<AudioRoutingManagerAsyncContext> context)138 bool NapiAudioRoutingManager::CheckAudioRoutingManagerStatus(NapiAudioRoutingManager *napi,
139     std::shared_ptr<AudioRoutingManagerAsyncContext> context)
140 {
141     CHECK_AND_RETURN_RET_LOG(napi != nullptr, false, "napi object is nullptr.");
142     if ((napi->audioMngr_ == nullptr) || (napi->audioRoutingMngr_ == nullptr)) {
143         context->SignError(NAPI_ERR_SYSTEM);
144         AUDIO_ERR_LOG("audioMngr_ is nullptr");
145         return false;
146     }
147 
148     return true;
149 }
150 
GetParamWithSync(const napi_env & env,napi_callback_info info,size_t & argc,napi_value * args)151 NapiAudioRoutingManager* NapiAudioRoutingManager::GetParamWithSync(const napi_env &env, napi_callback_info info,
152     size_t &argc, napi_value *args)
153 {
154     napi_status status;
155     NapiAudioRoutingManager *napiAudioRoutingManager = nullptr;
156     napi_value jsThis = nullptr;
157     status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
158     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr,
159         "GetParamWithSync fail to napi_get_cb_info");
160 
161     status = napi_unwrap(env, jsThis, (void **)&napiAudioRoutingManager);
162     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "napi_unwrap failed");
163     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr && napiAudioRoutingManager->audioMngr_  !=
164         nullptr, napiAudioRoutingManager, "GetParamWithSync fail to napi_unwrap");
165     return napiAudioRoutingManager;
166 }
167 
CreateRoutingManagerWrapper(napi_env env)168 napi_value NapiAudioRoutingManager::CreateRoutingManagerWrapper(napi_env env)
169 {
170     napi_status status;
171     napi_value result = nullptr;
172     napi_value constructor;
173 
174     status = napi_get_reference_value(env, g_routingManagerConstructor, &constructor);
175     if (status != napi_ok) {
176         AUDIO_ERR_LOG("Failed in CreateRoutingManagerWrapper, %{public}d", status);
177         goto fail;
178     }
179     status = napi_new_instance(env, constructor, PARAM0, nullptr, &result);
180     if (status != napi_ok) {
181         AUDIO_ERR_LOG("napi_new_instance failed, status:%{public}d", status);
182         goto fail;
183     }
184     return result;
185 
186 fail:
187     napi_get_undefined(env, &result);
188     return result;
189 }
190 
GetDevices(napi_env env,napi_callback_info info)191 napi_value NapiAudioRoutingManager::GetDevices(napi_env env, napi_callback_info info)
192 {
193     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
194     if (context == nullptr) {
195         AUDIO_ERR_LOG("GetDevices failed : no memory");
196         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
197         return NapiParamUtils::GetUndefinedValue(env);
198     }
199 
200     auto inputParser = [env, context](size_t argc, napi_value *argv) {
201         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments", NAPI_ERR_INVALID_PARAM);
202         context->status = NapiParamUtils::GetValueInt32(env, context->deviceFlag, argv[PARAM0]);
203         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "get deviceFlag failed",
204             NAPI_ERR_INVALID_PARAM);
205         if (!NapiAudioEnum::IsLegalInputArgumentDeviceFlag(context->deviceFlag)) {
206             context->SignError(context->errCode ==
207                 NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED);
208         }
209     };
210     context->GetCbInfo(env, info, inputParser);
211 
212     auto executor = [context]() {
213         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
214         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
215         ObjectRefMap objectGuard(obj);
216         auto *napiAudioRoutingManager = objectGuard.GetPtr();
217         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
218             "context object state is error.");
219         context->deviceDescriptors = napiAudioRoutingManager->audioMngr_->GetDevices(
220             static_cast<DeviceFlag>(context->deviceFlag));
221     };
222     auto complete = [env, context](napi_value &output) {
223         NapiParamUtils::SetDeviceDescriptors(env, context->deviceDescriptors, output);
224     };
225     return NapiAsyncWork::Enqueue(env, context, "GetDevices", executor, complete);
226 }
227 
GetDevicesSync(napi_env env,napi_callback_info info)228 napi_value NapiAudioRoutingManager::GetDevicesSync(napi_env env, napi_callback_info info)
229 {
230     napi_value result = nullptr;
231     size_t argc = ARGS_ONE;
232     napi_value argv[ARGS_ONE] = {};
233     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
234     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
235         "mandatory parameters are left unspecified"), "argCount invalid");
236 
237     napi_valuetype valueType = napi_undefined;
238     napi_typeof(env, argv[PARAM0], &valueType);
239     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
240         "incorrect parameter types: The type of deviceFlag must be number"), "valueType invalid");
241 
242     int32_t deviceFlag;
243     napi_status status = NapiParamUtils::GetValueInt32(env, deviceFlag, argv[PARAM0]);
244     CHECK_AND_RETURN_RET_LOG(NapiAudioEnum::IsLegalInputArgumentDeviceFlag(deviceFlag) && (status == napi_ok),
245         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
246         "parameter verification failed: The param of deviceFlag must be enum DeviceFlag"), "deviceFlag invalid");
247 
248     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
249     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioMngr_ != nullptr, result, "audioMngr_ nullptr");
250     vector<sptr<AudioDeviceDescriptor>> deviceDescriptors = napiAudioRoutingManager->audioMngr_->GetDevices(
251         static_cast<DeviceFlag>(deviceFlag));
252 
253     NapiParamUtils::SetDeviceDescriptors(env, deviceDescriptors, result);
254 
255     return result;
256 }
257 
SelectOutputDevice(napi_env env,napi_callback_info info)258 napi_value NapiAudioRoutingManager::SelectOutputDevice(napi_env env, napi_callback_info info)
259 {
260     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
261     if (context == nullptr) {
262         AUDIO_ERR_LOG("SelectOutputDevice failed : no memory");
263         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
264         return NapiParamUtils::GetUndefinedValue(env);
265     }
266 
267     auto inputParser = [env, context](size_t argc, napi_value *argv) {
268         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments", NAPI_ERR_INVALID_PARAM);
269         NapiParamUtils::GetAudioDeviceDescriptorVector(env, context->deviceDescriptors,
270             context->bArgTransFlag, argv[PARAM0]);
271         NAPI_CHECK_ARGS_RETURN_VOID(context, context->bArgTransFlag, "select output device failed",
272             NAPI_ERR_UNSUPPORTED);
273     };
274     context->GetCbInfo(env, info, inputParser);
275 
276     auto executor = [context]() {
277         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
278         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
279         ObjectRefMap objectGuard(obj);
280         auto *napiAudioRoutingManager = objectGuard.GetPtr();
281         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
282             "context object state is error.");
283         context->intValue = napiAudioRoutingManager->audioMngr_->SelectOutputDevice(context->deviceDescriptors);
284         NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS, "SelectOutputDevice failed",
285             NAPI_ERR_SYSTEM);
286     };
287 
288     auto complete = [env](napi_value &output) {
289         output = NapiParamUtils::GetUndefinedValue(env);
290     };
291     return NapiAsyncWork::Enqueue(env, context, "SelectOutputDevice", executor, complete);
292 }
293 
SelectOutputDeviceByFilter(napi_env env,napi_callback_info info)294 napi_value NapiAudioRoutingManager::SelectOutputDeviceByFilter(napi_env env, napi_callback_info info)
295 {
296     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
297     if (context == nullptr) {
298         AUDIO_ERR_LOG("SelectOutputDeviceByFilter failed : no memory");
299         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
300         return NapiParamUtils::GetUndefinedValue(env);
301     }
302 
303     auto inputParser = [env, context](size_t argc, napi_value *argv) {
304         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_TWO, "invalid arguments", NAPI_ERR_INVALID_PARAM);
305         NapiParamUtils::GetAudioRendererFilter(env, context->audioRendererFilter,
306             context->bArgTransFlag, argv[PARAM0]);
307         NapiParamUtils::GetAudioDeviceDescriptorVector(env, context->deviceDescriptors,
308             context->bArgTransFlag, argv[PARAM1]);
309     };
310     context->GetCbInfo(env, info, inputParser);
311 
312     auto executor = [context]() {
313         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
314         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
315         ObjectRefMap objectGuard(obj);
316         auto *napiAudioRoutingManager = objectGuard.GetPtr();
317         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
318             "context object state is error.");
319         if (!context->bArgTransFlag) {
320             context->SignError(NAPI_ERR_UNSUPPORTED);
321         }
322         context->intValue = napiAudioRoutingManager->audioMngr_->SelectOutputDevice(context->audioRendererFilter,
323             context->deviceDescriptors);
324         NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS, "SelectOutputDeviceByFilter failed",
325             NAPI_ERR_SYSTEM);
326     };
327 
328     auto complete = [env](napi_value &output) {
329         output = NapiParamUtils::GetUndefinedValue(env);
330     };
331     return NapiAsyncWork::Enqueue(env, context, "SelectOutputDeviceByFilter", executor, complete);
332 }
333 
SelectInputDevice(napi_env env,napi_callback_info info)334 napi_value NapiAudioRoutingManager::SelectInputDevice(napi_env env, napi_callback_info info)
335 {
336     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
337     if (context == nullptr) {
338         AUDIO_ERR_LOG("SelectInputDevice failed : no memory");
339         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
340         return NapiParamUtils::GetUndefinedValue(env);
341     }
342 
343     auto inputParser = [env, context](size_t argc, napi_value *argv) {
344         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments", NAPI_ERR_INVALID_PARAM);
345         NapiParamUtils::GetAudioDeviceDescriptorVector(env, context->deviceDescriptors,
346             context->bArgTransFlag, argv[PARAM0]);
347     };
348     context->GetCbInfo(env, info, inputParser);
349 
350     auto executor = [context]() {
351         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
352         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
353         ObjectRefMap objectGuard(obj);
354         auto *napiAudioRoutingManager = objectGuard.GetPtr();
355         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
356             "context object state is error.");
357         if (!context->bArgTransFlag) {
358             context->SignError(NAPI_ERR_INVALID_PARAM);
359         }
360         context->intValue = napiAudioRoutingManager->audioMngr_->SelectInputDevice(context->deviceDescriptors);
361         NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS, "SelectInputDevice failed", NAPI_ERR_SYSTEM);
362     };
363 
364     auto complete = [env](napi_value &output) {
365         output = NapiParamUtils::GetUndefinedValue(env);
366     };
367     return NapiAsyncWork::Enqueue(env, context, "SelectInputDevice", executor, complete);
368 }
369 
SelectInputDeviceByFilter(napi_env env,napi_callback_info info)370 napi_value NapiAudioRoutingManager::SelectInputDeviceByFilter(napi_env env, napi_callback_info info)
371 {
372     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
373     if (context == nullptr) {
374         AUDIO_ERR_LOG("SelectInputDeviceByFilter failed : no memory");
375         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
376         return NapiParamUtils::GetUndefinedValue(env);
377     }
378 
379     auto inputParser = [env, context](size_t argc, napi_value *argv) {
380         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_TWO, "invalid arguments", NAPI_ERR_INVALID_PARAM);
381         context->status = NapiParamUtils::GetAudioCapturerFilter(env, context->audioCapturerFilter, argv[PARAM0]);
382         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "select input device by filter failed",
383             NAPI_ERR_INVALID_PARAM);
384         NapiParamUtils::GetAudioDeviceDescriptorVector(env, context->deviceDescriptors,
385             context->bArgTransFlag, argv[PARAM1]);
386     };
387     context->GetCbInfo(env, info, inputParser);
388 
389     auto executor = [context]() {
390         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
391         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
392         ObjectRefMap objectGuard(obj);
393         auto *napiAudioRoutingManager = objectGuard.GetPtr();
394         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
395             "context object state is error.");
396         if (!context->bArgTransFlag) {
397             context->SignError(NAPI_ERR_UNSUPPORTED);
398         }
399         context->intValue = napiAudioRoutingManager->audioMngr_->SelectInputDevice(context->audioCapturerFilter,
400             context->deviceDescriptors);
401         NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS, "SelectInputDevice failed", NAPI_ERR_SYSTEM);
402     };
403 
404     auto complete = [env](napi_value &output) {
405         output = NapiParamUtils::GetUndefinedValue(env);
406     };
407     return NapiAsyncWork::Enqueue(env, context, "SelectInputDeviceByFilter", executor, complete);
408 }
409 
SetCommunicationDevice(napi_env env,napi_callback_info info)410 napi_value NapiAudioRoutingManager::SetCommunicationDevice(napi_env env, napi_callback_info info)
411 {
412     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
413     if (context == nullptr) {
414         AUDIO_ERR_LOG("SetCommunicationDevice failed : no memory");
415         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
416         return NapiParamUtils::GetUndefinedValue(env);
417     }
418 
419     auto inputParser = [env, context](size_t argc, napi_value *argv) {
420         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_TWO, "invalid arguments", NAPI_ERR_INVALID_PARAM);
421         context->status = NapiParamUtils::GetValueInt32(env, context->deviceType, argv[PARAM0]);
422         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "set communication device failed",
423             NAPI_ERR_INVALID_PARAM);
424         if (!NapiAudioEnum::IsLegalInputArgumentCommunicationDeviceType(context->deviceType)) {
425             context->SignError(context->errCode ==
426                 NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED);
427         }
428         context->status = NapiParamUtils::GetValueBoolean(env, context->isActive, argv[PARAM1]);
429         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "set communication device failed",
430             NAPI_ERR_INVALID_PARAM);
431     };
432     context->GetCbInfo(env, info, inputParser);
433 
434     auto executor = [context]() {
435         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
436         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
437         ObjectRefMap objectGuard(obj);
438         auto *napiAudioRoutingManager = objectGuard.GetPtr();
439         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
440             "context object state is error.");
441         context->intValue = napiAudioRoutingManager->audioMngr_->SetDeviceActive(
442             static_cast<ActiveDeviceType>(context->deviceType), context->isActive);
443         NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS, "SelectInputDevice failed", NAPI_ERR_SYSTEM);
444     };
445 
446     auto complete = [env](napi_value &output) {
447         output = NapiParamUtils::GetUndefinedValue(env);
448     };
449     return NapiAsyncWork::Enqueue(env, context, "SetCommunicationDevice", executor, complete);
450 }
451 
IsCommunicationDeviceActive(napi_env env,napi_callback_info info)452 napi_value NapiAudioRoutingManager::IsCommunicationDeviceActive(napi_env env, napi_callback_info info)
453 {
454     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
455     if (context == nullptr) {
456         AUDIO_ERR_LOG("IsCommunicationDeviceActive failed : no memory");
457         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
458         return NapiParamUtils::GetUndefinedValue(env);
459     }
460 
461     auto inputParser = [env, context](size_t argc, napi_value *argv) {
462         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments", NAPI_ERR_INVALID_PARAM);
463         context->status = NapiParamUtils::GetValueInt32(env, context->deviceType, argv[PARAM0]);
464         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "IsCommunicationDeviceActive failed",
465             NAPI_ERR_INVALID_PARAM);
466         if (!NapiAudioEnum::IsLegalInputArgumentActiveDeviceType(context->deviceType)) {
467             context->SignError(context->errCode ==
468                 NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED);
469         }
470     };
471     context->GetCbInfo(env, info, inputParser);
472 
473     auto executor = [context]() {
474         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
475         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
476         ObjectRefMap objectGuard(obj);
477         auto *napiAudioRoutingManager = objectGuard.GetPtr();
478         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
479             "context object state is error.");
480         context->isActive = napiAudioRoutingManager->audioMngr_->IsDeviceActive(
481             static_cast<ActiveDeviceType>(context->deviceType));
482         context->isTrue = context->isActive;
483     };
484 
485     auto complete = [env, context](napi_value &output) {
486         NapiParamUtils::SetValueBoolean(env, context->isTrue, output);
487     };
488     return NapiAsyncWork::Enqueue(env, context, "IsCommunicationDeviceActive", executor, complete);
489 }
490 
IsCommunicationDeviceActiveSync(napi_env env,napi_callback_info info)491 napi_value NapiAudioRoutingManager::IsCommunicationDeviceActiveSync(napi_env env, napi_callback_info info)
492 {
493     napi_value result = nullptr;
494     size_t argc = ARGS_ONE;
495     napi_value argv[ARGS_ONE] = {};
496     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
497     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
498         "mandatory parameters are left unspecified"), "argCount invalid");
499 
500     napi_valuetype valueType = napi_undefined;
501     napi_typeof(env, argv[PARAM0], &valueType);
502     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
503         "incorrect parameter types: The type of deviceType must be number"), "valueType invalid");
504 
505     int32_t deviceType;
506     napi_status status = NapiParamUtils::GetValueInt32(env, deviceType, argv[PARAM0]);
507     CHECK_AND_RETURN_RET_LOG(NapiAudioEnum::IsLegalInputArgumentActiveDeviceType(deviceType) && status == napi_ok,
508         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
509         "parameter verification failed: The param of deviceType must be enum CommunicationDeviceType"),
510         "valueType invalid");
511 
512     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
513     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioMngr_ != nullptr, result, "audioMngr_ nullptr");
514     bool isActive = napiAudioRoutingManager->audioMngr_->IsDeviceActive(static_cast<ActiveDeviceType>(deviceType));
515 
516     NapiParamUtils::SetValueBoolean(env, isActive, result);
517     return result;
518 }
519 
GetActiveOutputDeviceDescriptors(napi_env env,napi_callback_info info)520 napi_value NapiAudioRoutingManager::GetActiveOutputDeviceDescriptors(napi_env env, napi_callback_info info)
521 {
522     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
523     if (context == nullptr) {
524         AUDIO_ERR_LOG("GetActiveOutputDeviceDescriptors failed : no memory");
525         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
526         return NapiParamUtils::GetUndefinedValue(env);
527     }
528 
529     context->GetCbInfo(env, info);
530 
531     auto executor = [context]() {
532         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
533         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
534         ObjectRefMap objectGuard(obj);
535         auto *napiAudioRoutingManager = objectGuard.GetPtr();
536         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
537             "context object state is error.");
538         context->outDeviceDescriptors = napiAudioRoutingManager->audioMngr_->GetActiveOutputDeviceDescriptors();
539     };
540 
541     auto complete = [env, context](napi_value &output) {
542         NapiParamUtils::SetDeviceDescriptors(env, context->outDeviceDescriptors, output);
543     };
544     return NapiAsyncWork::Enqueue(env, context, "GetActiveOutputDeviceDescriptors", executor, complete);
545 }
546 
GetPreferredOutputDeviceForRendererInfo(napi_env env,napi_callback_info info)547 napi_value NapiAudioRoutingManager::GetPreferredOutputDeviceForRendererInfo(napi_env env, napi_callback_info info)
548 {
549     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
550     if (context == nullptr) {
551         AUDIO_ERR_LOG("GetPreferredOutputDeviceForRendererInfo failed : no memory");
552         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
553         return NapiParamUtils::GetUndefinedValue(env);
554     }
555 
556     auto inputParser = [env, context](size_t argc, napi_value *argv) {
557         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "mandatory parameters are left unspecified",
558             NAPI_ERR_INPUT_INVALID);
559         context->status = NapiParamUtils::GetRendererInfo(env, &(context->rendererInfo), argv[PARAM0]);
560         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
561             "incorrect parameter types: The type of rendererInfo must be interface AudioRendererInfo",
562             NAPI_ERR_INPUT_INVALID);
563     };
564     context->GetCbInfo(env, info, inputParser);
565     if (context->status != napi_ok) {
566         NapiAudioError::ThrowError(env, context->errCode, context->errMessage);
567         return NapiParamUtils::GetUndefinedValue(env);
568     }
569 
570     auto executor = [context]() {
571         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
572         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
573         ObjectRefMap objectGuard(obj);
574         auto *napiAudioRoutingManager = objectGuard.GetPtr();
575         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
576             "context object state is error.");
577         if (context->rendererInfo.streamUsage == StreamUsage::STREAM_USAGE_INVALID) {
578             context->SignError(NAPI_ERR_INVALID_PARAM, "parameter verification failed: The param of usage invalid");
579         } else {
580             context->intValue = napiAudioRoutingManager->audioRoutingMngr_->GetPreferredOutputDeviceForRendererInfo(
581                 context->rendererInfo, context->outDeviceDescriptors);
582             NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS,
583                 "GetPreferredOutputDeviceForRendererInfo failed", NAPI_ERR_SYSTEM);
584         }
585     };
586 
587     auto complete = [env, context](napi_value &output) {
588         NapiParamUtils::SetDeviceDescriptors(env, context->outDeviceDescriptors, output);
589     };
590     return NapiAsyncWork::Enqueue(env, context, "GetPreferredOutputDeviceForRendererInfo", executor, complete);
591 }
592 
GetPreferOutputDeviceForRendererInfo(napi_env env,napi_callback_info info)593 napi_value NapiAudioRoutingManager::GetPreferOutputDeviceForRendererInfo(napi_env env, napi_callback_info info)
594 {
595     // for api compatibility, leave some time for applications to adapt to new one
596     return GetPreferredOutputDeviceForRendererInfo(env, info);
597 }
598 
GetPreferredOutputDeviceForRendererInfoSync(napi_env env,napi_callback_info info)599 napi_value NapiAudioRoutingManager::GetPreferredOutputDeviceForRendererInfoSync(napi_env env, napi_callback_info info)
600 {
601     AUDIO_INFO_LOG("GetPreferredOutputDeviceForRendererInfoSync");
602     napi_value result = nullptr;
603     size_t argc = ARGS_ONE;
604     napi_value argv[ARGS_ONE] = {};
605     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
606     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
607         "mandatory parameters are left unspecified"), "argCount invalid");
608 
609     napi_valuetype valueType = napi_undefined;
610     napi_typeof(env, argv[PARAM0], &valueType);
611     CHECK_AND_RETURN_RET_LOG(valueType == napi_object, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
612         "incorrect parameter types: The type of rendererInfo must be object"),
613         "valueType invalid");
614 
615     AudioRendererInfo rendererInfo;
616     if (NapiParamUtils::GetRendererInfo(env, &rendererInfo, argv[PARAM0]) != napi_ok) {
617         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
618             "incorrect parameter types: The type of rendererInfo must be interface AudioRendererInfo");
619         return result;
620     } else if (rendererInfo.streamUsage == StreamUsage::STREAM_USAGE_INVALID) {
621         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
622             "parameter verification failed: The param of usage invalid");
623         return result;
624     }
625 
626     vector<sptr<AudioDeviceDescriptor>> outDeviceDescriptors;
627     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
628     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioRoutingMngr_ != nullptr, result,
629         "audioRoutingMngr_ nullptr");
630     napiAudioRoutingManager->audioRoutingMngr_->GetPreferredOutputDeviceForRendererInfo(
631         rendererInfo, outDeviceDescriptors);
632 
633     NapiParamUtils::SetDeviceDescriptors(env, outDeviceDescriptors, result);
634 
635     return result;
636 }
637 
GetPreferredInputDeviceForCapturerInfo(napi_env env,napi_callback_info info)638 napi_value NapiAudioRoutingManager::GetPreferredInputDeviceForCapturerInfo(napi_env env, napi_callback_info info)
639 {
640     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
641     if (context == nullptr) {
642         AUDIO_ERR_LOG("GetPreferredInputDeviceForCapturerInfo failed : no memory");
643         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
644         return NapiParamUtils::GetUndefinedValue(env);
645     }
646 
647     auto inputParser = [env, context](size_t argc, napi_value *argv) {
648         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "mandatory parameters are left unspecified",
649             NAPI_ERR_INPUT_INVALID);
650         context->status = NapiParamUtils::GetAudioCapturerInfo(env, &context->captureInfo, argv[PARAM0]);
651         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
652             "incorrect parameter types: The type of capturerInfo must be interface AudioCapturerInfo",
653             NAPI_ERR_INPUT_INVALID);
654     };
655     context->GetCbInfo(env, info, inputParser);
656 
657     if (context->status != napi_ok) {
658         NapiAudioError::ThrowError(env, context->errCode, context->errMessage);
659         return NapiParamUtils::GetUndefinedValue(env);
660     }
661 
662     auto executor = [context]() {
663         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
664         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
665         ObjectRefMap objectGuard(obj);
666         auto *napiAudioRoutingManager = objectGuard.GetPtr();
667         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
668             "context object state is error.");
669         if (context->captureInfo.sourceType == SourceType::SOURCE_TYPE_INVALID) {
670             context->SignError(NAPI_ERR_INVALID_PARAM,
671                 "parameter verification failed: The param of sourceType invalid");
672         } else {
673             context->intValue = napiAudioRoutingManager->audioRoutingMngr_->GetPreferredInputDeviceForCapturerInfo(
674                 context->captureInfo, context->inputDeviceDescriptors);
675             NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS,
676                 "GetPreferredInputDeviceForCapturerInfo failed", NAPI_ERR_SYSTEM);
677         }
678     };
679 
680     auto complete = [env, context](napi_value &output) {
681         NapiParamUtils::SetDeviceDescriptors(env, context->inputDeviceDescriptors, output);
682     };
683     return NapiAsyncWork::Enqueue(env, context, "GetPreferredInputDeviceForCapturerInfo", executor, complete);
684 }
685 
GetPreferredInputDeviceForCapturerInfoSync(napi_env env,napi_callback_info info)686 napi_value NapiAudioRoutingManager::GetPreferredInputDeviceForCapturerInfoSync(napi_env env, napi_callback_info info)
687 {
688     napi_value result = nullptr;
689     size_t argc = ARGS_ONE;
690     napi_value argv[ARGS_ONE] = {};
691     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
692     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
693         "mandatory parameters are left unspecified"), "argCount invalid");
694 
695     napi_valuetype valueType = napi_undefined;
696     napi_typeof(env, argv[PARAM0], &valueType);
697     CHECK_AND_RETURN_RET_LOG(valueType == napi_object,
698         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
699         "incorrect parameter types: The type of capturerInfo must be object"), "valueType invalid");
700 
701     AudioCapturerInfo capturerInfo;
702     napi_status status = NapiParamUtils::GetAudioCapturerInfo(env, &capturerInfo, argv[PARAM0]);
703     CHECK_AND_RETURN_RET_LOG((capturerInfo.sourceType != SourceType::SOURCE_TYPE_INVALID) && (status == napi_ok),
704         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
705         "parameter verification failed: The param of capturerInfo must be interface AudioCapturerInfo"),
706         "sourceType invalid");
707 
708     vector<sptr<AudioDeviceDescriptor>> outDeviceDescriptors;
709     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
710     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioRoutingMngr_ != nullptr, result,
711         "audioRoutingMngr_ nullptr");
712     napiAudioRoutingManager->audioRoutingMngr_->GetPreferredInputDeviceForCapturerInfo(
713         capturerInfo, outDeviceDescriptors);
714 
715     NapiParamUtils::SetDeviceDescriptors(env, outDeviceDescriptors, result);
716 
717     return result;
718 }
719 
GetAvailableMicrophones(napi_env env,napi_callback_info info)720 napi_value NapiAudioRoutingManager::GetAvailableMicrophones(napi_env env, napi_callback_info info)
721 {
722     AUDIO_INFO_LOG("GetAvailableMicrophones");
723     napi_value result = nullptr;
724     size_t argc = PARAM0;
725     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, nullptr);
726     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
727         "mandatory parameters are left unspecified"), "argCount invalid");
728     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
729     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioRoutingMngr_ != nullptr, result,
730         "audioRoutingMngr_ is nullptr");
731 
732     vector<sptr<MicrophoneDescriptor>> micDescs =
733         napiAudioRoutingManager->audioRoutingMngr_->GetAvailableMicrophones();
734 
735     NapiParamUtils::SetMicrophoneDescriptors(env, micDescs, result);
736 
737     return result;
738 }
739 
GetAvailableDevices(napi_env env,napi_callback_info info)740 napi_value NapiAudioRoutingManager::GetAvailableDevices(napi_env env, napi_callback_info info)
741 {
742     napi_value result = nullptr;
743     size_t argc = ARGS_ONE;
744     napi_value argv[ARGS_ONE] = {};
745     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
746     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
747         "mandatory parameters are left unspecified"), "argcCount invalid");
748 
749     napi_valuetype valueType = napi_undefined;
750     napi_status status = napi_typeof(env, argv[PARAM0], &valueType);
751     CHECK_AND_RETURN_RET_LOG(status == napi_ok && valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env,
752         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of deviceUsage must be number"),
753         "valueType invalid");
754 
755     int32_t intValue = 0;
756     status = napi_get_value_int32(env, argv[PARAM0], &intValue);
757     CHECK_AND_RETURN_RET_LOG(status == napi_ok && NapiAudioEnum::IsLegalDeviceUsage(intValue),
758         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
759         "parameter verification failed: The param of deviceUsage must be enum DeviceUsage"), "invalid deviceusage");
760 
761     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
762     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioRoutingMngr_ != nullptr, result,
763         "audioRoutingMngr_ is nullptr");
764     AudioDeviceUsage usage = static_cast<AudioDeviceUsage>(intValue);
765 
766     vector<std::unique_ptr<AudioDeviceDescriptor>> availableDescs =
767         napiAudioRoutingManager->audioRoutingMngr_->GetAvailableDevices(usage);
768 
769     vector<sptr<AudioDeviceDescriptor>> availableSptrDescs;
770     for (const auto &availableDesc : availableDescs) {
771         sptr<AudioDeviceDescriptor> dec = new(std::nothrow) AudioDeviceDescriptor(*availableDesc);
772         CHECK_AND_BREAK_LOG(dec != nullptr, "dec mallac failed,no memery.");
773         availableSptrDescs.push_back(dec);
774     }
775     NapiParamUtils::SetDeviceDescriptors(env, availableSptrDescs, result);
776     return result;
777 }
778 
RegisterCallback(napi_env env,napi_value jsThis,size_t argc,napi_value * args,const std::string & cbName)779 napi_value NapiAudioRoutingManager::RegisterCallback(napi_env env, napi_value jsThis, size_t argc,
780     napi_value *args, const std::string &cbName)
781 {
782     napi_value undefinedResult = nullptr;
783     NapiAudioRoutingManager *napiRoutingMgr = nullptr;
784     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void**>(&napiRoutingMgr));
785     if ((status != napi_ok) || (napiRoutingMgr == nullptr) || (napiRoutingMgr->audioMngr_ == nullptr) ||
786         (napiRoutingMgr->audioRoutingMngr_ == nullptr)) {
787         AUDIO_ERR_LOG("NapiAudioRoutingManager::Failed to retrieve stream mgr napi instance.");
788         return undefinedResult;
789     }
790 
791     if (!cbName.compare(DEVICE_CHANGE_CALLBACK_NAME)) {
792         RegisterDeviceChangeCallback(env, argc, args, cbName, napiRoutingMgr);
793     } else if (!cbName.compare(PREFERRED_OUTPUT_DEVICE_CALLBACK_NAME) ||
794         !cbName.compare(PREFER_OUTPUT_DEVICE_CALLBACK_NAME)) {
795         RegisterPreferredOutputDeviceChangeCallback(env, argc, args, cbName, napiRoutingMgr);
796     } else if (!cbName.compare(PREFERRED_INPUT_DEVICE_CALLBACK_NAME)) {
797         RegisterPreferredInputDeviceChangeCallback(env, argc, args, cbName, napiRoutingMgr);
798     } else if (!cbName.compare(AVAILABLE_DEVICE_CHANGE_CALLBACK_NAME)) {
799         RegisterAvaiableDeviceChangeCallback(env, argc, args, cbName, napiRoutingMgr);
800     } else if (!cbName.compare(MICROPHONE_BLOCKED_CALLBACK_NAME)) {
801         RegisterMicrophoneBlockedCallback(env, argc, args, cbName, napiRoutingMgr);
802     } else {
803         AUDIO_ERR_LOG("NapiAudioRoutingManager::No such supported");
804         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
805             "parameter verification failed: The param of type is not supported");
806     }
807     return undefinedResult;
808 }
809 
RegisterDeviceChangeCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,NapiAudioRoutingManager * napiRoutingMgr)810 void NapiAudioRoutingManager::RegisterDeviceChangeCallback(napi_env env, size_t argc, napi_value *args,
811     const std::string &cbName, NapiAudioRoutingManager *napiRoutingMgr)
812 {
813     int32_t flag = ARGS_THREE;
814     napi_valuetype valueType = napi_undefined;
815     napi_typeof(env, args[PARAM1], &valueType);
816     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
817         "incorrect parameter types: The type of deviceFlag must be number"), "invalid valueType");
818     if (valueType == napi_number) {
819         NapiParamUtils::GetValueInt32(env, flag, args[PARAM1]);
820         AUDIO_INFO_LOG("RegisterDeviceChangeCallback:On deviceFlag: %{public}d", flag);
821         if (!NapiAudioEnum::IsLegalInputArgumentDeviceFlag(flag)) {
822             NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
823                 "parameter verification failed: The param of deviceFlag must be enum DeviceFlag");
824         }
825     }
826 
827     napi_valuetype handler = napi_undefined;
828     napi_typeof(env, args[PARAM2], &handler);
829 
830     if (handler != napi_function) {
831         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
832             "incorrect parameter types: The type of callback must be function");
833     }
834     DeviceFlag deviceFlag = DeviceFlag(flag);
835     if (!napiRoutingMgr->deviceChangeCallbackNapi_) {
836         napiRoutingMgr->deviceChangeCallbackNapi_ = std::make_shared<NapiAudioManagerCallback>(env);
837     }
838     CHECK_AND_RETURN_LOG(napiRoutingMgr->deviceChangeCallbackNapi_,
839         "RegisterDeviceChangeCallback: Memory Allocation Failed !");
840 
841     int32_t ret = napiRoutingMgr->audioMngr_->SetDeviceChangeCallback(deviceFlag,
842         napiRoutingMgr->deviceChangeCallbackNapi_);
843     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
844         "RegisterDeviceChangeCallback: Registering Device Change Callback Failed %{public}d", ret);
845 
846     std::shared_ptr<NapiAudioManagerCallback> cb =
847         std::static_pointer_cast<NapiAudioManagerCallback>(napiRoutingMgr->deviceChangeCallbackNapi_);
848     cb->SaveRoutingManagerDeviceChangeCbRef(deviceFlag, args[PARAM2]);
849 }
850 
RegisterPreferredOutputDeviceChangeCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,NapiAudioRoutingManager * napiRoutingMgr)851 void NapiAudioRoutingManager::RegisterPreferredOutputDeviceChangeCallback(napi_env env, size_t argc, napi_value *args,
852     const std::string &cbName, NapiAudioRoutingManager *napiRoutingMgr)
853 {
854     napi_valuetype valueType = napi_undefined;
855     napi_typeof(env, args[PARAM1], &valueType);
856     if (valueType != napi_object) {
857         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
858             "incorrect parameter types: The type of rendererInfo must be object");
859     }
860 
861     AudioRendererInfo rendererInfo;
862     NapiParamUtils::GetRendererInfo(env, &rendererInfo, args[PARAM1]);
863     CHECK_AND_RETURN_RET_LOG(rendererInfo.streamUsage != StreamUsage::STREAM_USAGE_INVALID,
864         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
865         "parameter verification failed: The param of streamUsage invalid"), "invalid streamUsage");
866     AudioStreamType streamType = AudioSystemManager::GetStreamType(rendererInfo.contentType,
867         rendererInfo.streamUsage);
868 
869     if (!napiRoutingMgr->preferredOutputDeviceCallbackNapi_) {
870         napiRoutingMgr->preferredOutputDeviceCallbackNapi_ =
871             std::make_shared<NapiAudioPreferredOutputDeviceChangeCallback>(env);
872         CHECK_AND_RETURN_LOG(napiRoutingMgr->preferredOutputDeviceCallbackNapi_ != nullptr,
873             "RegisterPreferredOutputDeviceChangeCallback: Memory Allocation Failed !!");
874 
875         int32_t ret = napiRoutingMgr->audioRoutingMngr_->SetPreferredOutputDeviceChangeCallback(
876             rendererInfo, napiRoutingMgr->preferredOutputDeviceCallbackNapi_);
877         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
878             "Registering Active Output DeviceChange Callback Failed %{public}d", ret);
879     }
880 
881     std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb =
882         std::static_pointer_cast<NapiAudioPreferredOutputDeviceChangeCallback>(
883         napiRoutingMgr->preferredOutputDeviceCallbackNapi_);
884     cb->SaveCallbackReference(streamType, args[PARAM2]);
885 }
886 
RegisterPreferredInputDeviceChangeCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,NapiAudioRoutingManager * napiRoutingMgr)887 void NapiAudioRoutingManager::RegisterPreferredInputDeviceChangeCallback(napi_env env, size_t argc, napi_value *args,
888     const std::string &cbName, NapiAudioRoutingManager *napiRoutingMgr)
889 {
890     napi_valuetype valueType = napi_undefined;
891     napi_typeof(env, args[PARAM1], &valueType);
892     if (valueType != napi_object) {
893         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
894             "incorrect parameter types: The type of capturerInfo must be object");
895     }
896 
897     AudioCapturerInfo captureInfo;
898     NapiParamUtils::GetAudioCapturerInfo(env, &captureInfo, args[PARAM1]);
899 
900     CHECK_AND_RETURN_RET_LOG(captureInfo.sourceType != SourceType::SOURCE_TYPE_INVALID,
901         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
902         "parameter verification failed: The param of sourceType invalid"), "invalid sourceType");
903 
904     if (!napiRoutingMgr->preferredInputDeviceCallbackNapi_) {
905         napiRoutingMgr->preferredInputDeviceCallbackNapi_ =
906             std::make_shared<NapiAudioPreferredInputDeviceChangeCallback>(env);
907         CHECK_AND_RETURN_LOG(napiRoutingMgr->preferredInputDeviceCallbackNapi_ != nullptr,
908             "RegisterPreferredInputDeviceChangeCallback: Memory Allocation Failed !!");
909 
910         int32_t ret = napiRoutingMgr->audioRoutingMngr_->SetPreferredInputDeviceChangeCallback(
911             captureInfo, napiRoutingMgr->preferredInputDeviceCallbackNapi_);
912         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
913             "Registering Active Input DeviceChange Callback Failed %{public}d", ret);
914     }
915 
916     std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb =
917         std::static_pointer_cast<NapiAudioPreferredInputDeviceChangeCallback>(
918         napiRoutingMgr->preferredInputDeviceCallbackNapi_);
919     cb->SaveCallbackReference(captureInfo.sourceType, args[PARAM2]);
920 }
921 
RegisterAvaiableDeviceChangeCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,NapiAudioRoutingManager * napiRoutingMgr)922 void NapiAudioRoutingManager::RegisterAvaiableDeviceChangeCallback(napi_env env, size_t argc, napi_value *args,
923     const std::string &cbName, NapiAudioRoutingManager *napiRoutingMgr)
924 {
925     int32_t flag = 0;
926     napi_valuetype valueType = napi_undefined;
927     napi_typeof(env, args[PARAM1], &valueType);
928     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
929         "incorrect parameter types: The type of deviceUsage must be number"), "invalid Type");
930 
931     NapiParamUtils::GetValueInt32(env, flag, args[PARAM1]);
932     AUDIO_INFO_LOG("RegisterDeviceChangeCallback:On deviceFlag: %{public}d", flag);
933     if (!NapiAudioEnum::IsLegalDeviceUsage(flag)) {
934         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
935             "parameter verification failed: The param of deviceUsage must be enum DeviceUsage");
936     }
937 
938     napi_valuetype handler = napi_undefined;
939     napi_typeof(env, args[PARAM2], &handler);
940     if (handler != napi_function) {
941         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
942             "incorrect parameter types: The type of callback must be function");
943     }
944     AudioDeviceUsage usage = static_cast<AudioDeviceUsage>(flag);
945     if (!napiRoutingMgr->availableDeviceChangeCallbackNapi_) {
946         napiRoutingMgr->availableDeviceChangeCallbackNapi_ =
947             std::make_shared<NapiAudioRountingAvailableDeviceChangeCallback>(env);
948     }
949     CHECK_AND_RETURN_LOG(napiRoutingMgr->availableDeviceChangeCallbackNapi_ != nullptr,
950         "RegisterDeviceChangeCallback: Memory Allocation Failed !");
951 
952     int32_t ret = napiRoutingMgr->audioMngr_->SetAvailableDeviceChangeCallback(usage,
953         napiRoutingMgr->availableDeviceChangeCallbackNapi_);
954     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
955         "RegisterDeviceChangeCallback: Registering Device Change Callback Failed %{public}d", ret);
956 
957     std::shared_ptr<NapiAudioRountingAvailableDeviceChangeCallback> cb =
958         std::static_pointer_cast<NapiAudioRountingAvailableDeviceChangeCallback>(
959         napiRoutingMgr->availableDeviceChangeCallbackNapi_);
960     cb->SaveRoutingAvailbleDeviceChangeCbRef(usage, args[PARAM2]);
961 }
962 
RegisterMicrophoneBlockedCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,NapiAudioRoutingManager * napiRoutingMgr)963 void NapiAudioRoutingManager::RegisterMicrophoneBlockedCallback(napi_env env, size_t argc, napi_value *args,
964     const std::string &cbName, NapiAudioRoutingManager *napiRoutingMgr)
965 {
966     napi_valuetype valueType = napi_undefined;
967     napi_typeof(env, args[PARAM1], &valueType);
968     if (valueType != napi_function) {
969         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
970             "parameter verification failed: The param of deviceFlag must be enum DeviceFlag");
971     }
972     if (!napiRoutingMgr->microphoneBlockedCallbackNapi_) {
973         napiRoutingMgr->microphoneBlockedCallbackNapi_ = std::make_shared<NapiAudioManagerCallback>(env);
974     }
975     int32_t ret = napiRoutingMgr->audioMngr_->SetMicrophoneBlockedCallback(
976         napiRoutingMgr->microphoneBlockedCallbackNapi_);
977     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
978         "Registering micro phone blocked Callback Failed %{public}d", ret);
979     std::shared_ptr<NapiAudioManagerCallback> cb =
980         std::static_pointer_cast<NapiAudioManagerCallback>(napiRoutingMgr->microphoneBlockedCallbackNapi_);
981     cb->SaveMicrophoneBlockedCallbackReference(args[PARAM1]);
982 }
983 
On(napi_env env,napi_callback_info info)984 napi_value NapiAudioRoutingManager::On(napi_env env, napi_callback_info info)
985 {
986     const size_t requireArgc = ARGS_TWO;
987     const size_t maxArgc = ARGS_THREE;
988     size_t argc = ARGS_THREE;
989 
990     napi_value undefinedResult = nullptr;
991     napi_get_undefined(env, &undefinedResult);
992 
993     napi_value args[requireArgc + PARAM1] = { nullptr, nullptr, nullptr };
994     napi_value jsThis = nullptr;
995     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
996     bool isArgcCountRight = argc == requireArgc || argc == maxArgc;
997     CHECK_AND_RETURN_RET_LOG(status == napi_ok && isArgcCountRight, NapiAudioError::ThrowErrorAndReturn(env,
998         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "status or isArgcCountRight error");
999 
1000     napi_valuetype eventType = napi_undefined;
1001     napi_typeof(env, args[PARAM0], &eventType);
1002     CHECK_AND_RETURN_RET_LOG(eventType == napi_string, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
1003         "incorrect parameter types: The type of eventType must be string"), "eventType is invalid");
1004     std::string callbackName = NapiParamUtils::GetStringArgument(env, args[PARAM0]);
1005     AUDIO_INFO_LOG("On callbackName: %{public}s", callbackName.c_str());
1006 
1007     if (argc == requireArgc) {
1008         napi_valuetype handler = napi_undefined;
1009         napi_typeof(env, args[PARAM1], &handler);
1010         CHECK_AND_RETURN_RET_LOG(handler == napi_function, NapiAudioError::ThrowErrorAndReturn(env,
1011             NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of callback must be function"),
1012             "handler is invalid");
1013     }
1014 
1015     return RegisterCallback(env, jsThis, argc, args, callbackName);
1016 }
1017 
UnregisterCallback(napi_env env,napi_value jsThis,const std::string & callbackName,napi_value callback)1018 napi_value NapiAudioRoutingManager::UnregisterCallback(napi_env env, napi_value jsThis,
1019     const std::string &callbackName, napi_value callback)
1020 {
1021     napi_value undefinedResult = nullptr;
1022     napi_get_undefined(env, &undefinedResult);
1023     NapiAudioRoutingManager *napiRoutingMgr = nullptr;
1024     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiRoutingMgr));
1025     CHECK_AND_RETURN_RET_LOG(status == napi_ok && napiRoutingMgr != nullptr, undefinedResult,
1026         "Failed to retrieve audio mgr napi instance.");
1027     CHECK_AND_RETURN_RET_LOG(napiRoutingMgr->audioMngr_ != nullptr, undefinedResult,
1028         "audio system mgr instance is null.");
1029     if (!callbackName.compare(DEVICE_CHANGE_CALLBACK_NAME)) {
1030         UnregisterDeviceChangeCallback(env, callback, napiRoutingMgr);
1031     } else if (!callbackName.compare(PREFERRED_OUTPUT_DEVICE_CALLBACK_NAME) ||
1032         !callbackName.compare(PREFER_OUTPUT_DEVICE_CALLBACK_NAME)) {
1033         UnregisterPreferredOutputDeviceChangeCallback(env, callback, napiRoutingMgr);
1034     } else if (!callbackName.compare(PREFERRED_INPUT_DEVICE_CALLBACK_NAME)) {
1035         UnregisterPreferredInputDeviceChangeCallback(env, callback, napiRoutingMgr);
1036     } else if (!callbackName.compare(AVAILABLE_DEVICE_CHANGE_CALLBACK_NAME)) {
1037         UnregisterAvailableDeviceChangeCallback(env, callback, napiRoutingMgr);
1038     } else if (!callbackName.compare(MICROPHONE_BLOCKED_CALLBACK_NAME)) {
1039         UnregisterMicrophoneBlockedCallback(env, callback, napiRoutingMgr);
1040     } else {
1041         AUDIO_ERR_LOG("off no such supported");
1042         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
1043             "parameter verification failed: The param of type is not supported");
1044     }
1045 
1046     return undefinedResult;
1047 }
1048 
UnregisterDeviceChangeCallback(napi_env env,napi_value callback,NapiAudioRoutingManager * napiRoutingMgr)1049 void NapiAudioRoutingManager::UnregisterDeviceChangeCallback(napi_env env, napi_value callback,
1050     NapiAudioRoutingManager *napiRoutingMgr)
1051 {
1052     if (napiRoutingMgr->deviceChangeCallbackNapi_ != nullptr) {
1053         std::shared_ptr<NapiAudioManagerCallback> cb =
1054             std::static_pointer_cast<NapiAudioManagerCallback>(
1055             napiRoutingMgr->deviceChangeCallbackNapi_);
1056         if (callback != nullptr) {
1057             cb->RemoveRoutingManagerDeviceChangeCbRef(env, callback);
1058         }
1059         if (callback == nullptr || cb->GetRoutingManagerDeviceChangeCbListSize() == 0) {
1060             int32_t ret = napiRoutingMgr->audioMngr_->UnsetDeviceChangeCallback(DeviceFlag::ALL_L_D_DEVICES_FLAG,
1061                 napiRoutingMgr->deviceChangeCallbackNapi_);
1062             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetDeviceChangeCallback Failed");
1063             napiRoutingMgr->deviceChangeCallbackNapi_.reset();
1064             napiRoutingMgr->deviceChangeCallbackNapi_ = nullptr;
1065 
1066             cb->RemoveAllRoutingManagerDeviceChangeCb();
1067         }
1068     } else {
1069         AUDIO_ERR_LOG("UnregisterDeviceChangeCallback: deviceChangeCallbackNapi_ is null");
1070     }
1071 }
1072 
UnregisterPreferredOutputDeviceChangeCallback(napi_env env,napi_value callback,NapiAudioRoutingManager * napiRoutingMgr)1073 void NapiAudioRoutingManager::UnregisterPreferredOutputDeviceChangeCallback(napi_env env, napi_value callback,
1074     NapiAudioRoutingManager *napiRoutingMgr)
1075 {
1076     if (napiRoutingMgr->preferredOutputDeviceCallbackNapi_ != nullptr) {
1077         std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb =
1078             std::static_pointer_cast<NapiAudioPreferredOutputDeviceChangeCallback>(
1079             napiRoutingMgr->preferredOutputDeviceCallbackNapi_);
1080         if (callback == nullptr) {
1081             int32_t ret = napiRoutingMgr->audioRoutingMngr_->UnsetPreferredOutputDeviceChangeCallback();
1082             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetPreferredOutputDeviceChangeCallback Failed");
1083 
1084             napiRoutingMgr->preferredOutputDeviceCallbackNapi_.reset();
1085             napiRoutingMgr->preferredOutputDeviceCallbackNapi_ = nullptr;
1086             cb->RemoveAllCallbacks();
1087             return;
1088         }
1089         cb->RemoveCallbackReference(env, callback);
1090     } else {
1091         AUDIO_ERR_LOG("UnregisterPreferredOutputDeviceChangeCallback: preferredOutputDeviceCallbackNapi_ is null");
1092     }
1093 }
1094 
UnregisterPreferredInputDeviceChangeCallback(napi_env env,napi_value callback,NapiAudioRoutingManager * napiRoutingMgr)1095 void NapiAudioRoutingManager::UnregisterPreferredInputDeviceChangeCallback(napi_env env, napi_value callback,
1096     NapiAudioRoutingManager *napiRoutingMgr)
1097 {
1098     if (napiRoutingMgr->preferredInputDeviceCallbackNapi_ != nullptr) {
1099         std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb =
1100             std::static_pointer_cast<NapiAudioPreferredInputDeviceChangeCallback>(
1101             napiRoutingMgr->preferredInputDeviceCallbackNapi_);
1102         if (callback == nullptr) {
1103             int32_t ret = napiRoutingMgr->audioRoutingMngr_->UnsetPreferredInputDeviceChangeCallback();
1104             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetPreferredInputDeviceChangeCallback Failed");
1105 
1106             napiRoutingMgr->preferredInputDeviceCallbackNapi_.reset();
1107             napiRoutingMgr->preferredInputDeviceCallbackNapi_ = nullptr;
1108             cb->RemoveAllCallbacks();
1109             return;
1110         }
1111         cb->RemoveCallbackReference(env, callback);
1112     } else {
1113         AUDIO_ERR_LOG("UnregisterPreferredInputDeviceChangeCallback: preferredInputDeviceCallbackNapi_ is null");
1114     }
1115 }
1116 
UnregisterAvailableDeviceChangeCallback(napi_env env,napi_value callback,NapiAudioRoutingManager * napiRoutingMgr)1117 void NapiAudioRoutingManager::UnregisterAvailableDeviceChangeCallback(napi_env env, napi_value callback,
1118     NapiAudioRoutingManager *napiRoutingMgr)
1119 {
1120     if (napiRoutingMgr->availableDeviceChangeCallbackNapi_ != nullptr) {
1121         std::shared_ptr<NapiAudioRountingAvailableDeviceChangeCallback> cb =
1122             std::static_pointer_cast<NapiAudioRountingAvailableDeviceChangeCallback>(
1123             napiRoutingMgr->availableDeviceChangeCallbackNapi_);
1124         if (callback == nullptr || cb->GetRoutingAvailbleDeviceChangeCbListSize() == 0) {
1125             int32_t ret = napiRoutingMgr->audioMngr_->UnsetAvailableDeviceChangeCallback(D_ALL_DEVICES);
1126             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetAvailableDeviceChangeCallback Failed");
1127 
1128             napiRoutingMgr->availableDeviceChangeCallbackNapi_.reset();
1129             napiRoutingMgr->availableDeviceChangeCallbackNapi_ = nullptr;
1130             cb->RemoveAllRoutinAvailbleDeviceChangeCb();
1131             return;
1132         }
1133         cb->RemoveRoutingAvailbleDeviceChangeCbRef(env, callback);
1134     } else {
1135         AUDIO_ERR_LOG("UnregisterAvailableDeviceChangeCallback: availableDeviceChangeCallbackNapi_ is null");
1136     }
1137 }
1138 
UnregisterMicrophoneBlockedCallback(napi_env env,napi_value callback,NapiAudioRoutingManager * napiRoutingMgr)1139 void NapiAudioRoutingManager::UnregisterMicrophoneBlockedCallback(napi_env env, napi_value callback,
1140     NapiAudioRoutingManager *napiRoutingMgr)
1141 {
1142     if (napiRoutingMgr->microphoneBlockedCallbackNapi_ != nullptr) {
1143         std::shared_ptr<NapiAudioManagerCallback> cb =
1144             std::static_pointer_cast<NapiAudioManagerCallback>(
1145             napiRoutingMgr->microphoneBlockedCallbackNapi_);
1146         if (callback == nullptr || cb->GetMicrophoneBlockedCbListSize() == 0) {
1147             int32_t ret = napiRoutingMgr->audioMngr_->UnsetMicrophoneBlockedCallback(
1148                 napiRoutingMgr->microphoneBlockedCallbackNapi_);
1149             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetMicrophoneBlockedCallback Failed");
1150             napiRoutingMgr->microphoneBlockedCallbackNapi_.reset();
1151             napiRoutingMgr->microphoneBlockedCallbackNapi_ = nullptr;
1152             cb->RemoveAllMicrophoneBlockedCallback();
1153             return;
1154         }
1155         cb->RemoveMicrophoneBlockedCallbackReference(env, callback);
1156     } else {
1157         AUDIO_ERR_LOG("microphoneBlockedCallbackNapi_ is null");
1158     }
1159 }
1160 
Off(napi_env env,napi_callback_info info)1161 napi_value NapiAudioRoutingManager::Off(napi_env env, napi_callback_info info)
1162 {
1163     napi_value undefinedResult = nullptr;
1164     napi_get_undefined(env, &undefinedResult);
1165 
1166     const size_t minArgCount = ARGS_ONE;
1167     size_t argCount = ARGS_TWO;
1168     napi_value args[minArgCount + PARAM1] = {nullptr, nullptr};
1169     napi_value jsThis = nullptr;
1170     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
1171     if (status != napi_ok || argCount < minArgCount) {
1172         AUDIO_ERR_LOG("Off fail to napi_get_cb_info/Requires min 1 parameters");
1173         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified");
1174         return undefinedResult;
1175     }
1176 
1177     napi_valuetype eventType = napi_undefined;
1178     if (napi_typeof(env, args[PARAM0], &eventType) != napi_ok || eventType != napi_string) {
1179         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1180             "incorrect parameter types: The type of eventType must be string");
1181         return undefinedResult;
1182     }
1183 
1184     napi_valuetype secondArgsType = napi_undefined;
1185     if (argCount > minArgCount &&
1186         (napi_typeof(env, args[PARAM1], &secondArgsType) != napi_ok || secondArgsType != napi_function)) {
1187         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1188             "incorrect parameter types: The type of callback must be function");
1189         return undefinedResult;
1190     }
1191     std::string callbackName = NapiParamUtils::GetStringArgument(env, args[PARAM0]);
1192 
1193     if (argCount == minArgCount) {
1194         args[PARAM1] = nullptr;
1195     }
1196     AUDIO_INFO_LOG("Off callbackName: %{public}s", callbackName.c_str());
1197 
1198     return UnregisterCallback(env, jsThis, callbackName, args[PARAM1]);
1199 }
1200 
GetMicrophoneBlockedCbListSize()1201 int32_t NapiAudioManagerCallback::GetMicrophoneBlockedCbListSize()
1202 {
1203     std::lock_guard<std::mutex> lock(mutex_);
1204     return microphoneBlockedCbList_.size();
1205 }
1206 
1207 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
IsMicBlockDetectionSupported(napi_env env,napi_callback_info info)1208 napi_value NapiAudioRoutingManager::IsMicBlockDetectionSupported(napi_env env, napi_callback_info info)
1209 {
1210     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
1211     context->GetCbInfo(env, info);
1212     auto executor = [context]() {
1213         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
1214         context->supported = OHOS::system::GetBoolParameter("const.multimedia.audio.mic_block_detection", false);
1215         if (context->supported == true) {
1216         AUDIO_INFO_LOG("mic block detection supported");
1217         } else {
1218         AUDIO_ERR_LOG("mic block detection is not supported");
1219         }
1220     };
1221     auto complete = [env, context](napi_value &output) {
1222         NapiParamUtils::SetValueBoolean(env, context->supported, output);
1223     };
1224     return NapiAsyncWork::Enqueue(env, context, "IsMicBlockDetectionSupported", executor, complete);
1225 }
1226 #endif
1227 }  // namespace AudioStandard
1228 }  // namespace OHOS
1229