• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 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         AUDIO_WARNING_LOG("Native object is null");
47         return;
48     }
49     auto obj = static_cast<NapiAudioRoutingManager *>(nativeObject);
50     ObjectRefMap<NapiAudioRoutingManager>::DecreaseRef(obj);
51     AUDIO_INFO_LOG("Decrease obj count");
52 }
53 
Construct(napi_env env,napi_callback_info info)54 napi_value NapiAudioRoutingManager::Construct(napi_env env, napi_callback_info info)
55 {
56     napi_status status;
57     napi_value result = nullptr;
58     napi_get_undefined(env, &result);
59 
60     size_t argc = ARGS_TWO;
61     napi_value argv[ARGS_TWO] = {0};
62     napi_value thisVar = nullptr;
63     void *data = nullptr;
64     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
65     unique_ptr<NapiAudioRoutingManager> napiAudioRoutingManager = make_unique<NapiAudioRoutingManager>();
66     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "No memory");
67 
68     napiAudioRoutingManager->audioMngr_ = AudioSystemManager::GetInstance();
69     napiAudioRoutingManager->audioRoutingMngr_ = AudioRoutingManager::GetInstance();
70     napiAudioRoutingManager->env_ = env;
71     ObjectRefMap<NapiAudioRoutingManager>::Insert(napiAudioRoutingManager.get());
72 
73     status = napi_wrap(env, thisVar, static_cast<void*>(napiAudioRoutingManager.get()),
74         NapiAudioRoutingManager::Destructor, nullptr, nullptr);
75     if (status != napi_ok) {
76         ObjectRefMap<NapiAudioRoutingManager>::Erase(napiAudioRoutingManager.get());
77         return result;
78     }
79     napiAudioRoutingManager.release();
80     return thisVar;
81 }
82 
Init(napi_env env,napi_value exports)83 napi_value NapiAudioRoutingManager::Init(napi_env env, napi_value exports)
84 {
85     napi_status status;
86     napi_value constructor;
87     napi_value result = nullptr;
88     const int32_t refCount = ARGS_ONE;
89     napi_get_undefined(env, &result);
90 
91     napi_property_descriptor audio_routing_manager_properties[] = {
92         DECLARE_NAPI_FUNCTION("getDevices", GetDevices),
93         DECLARE_NAPI_FUNCTION("getDevicesSync", GetDevicesSync),
94         DECLARE_NAPI_FUNCTION("selectOutputDevice", SelectOutputDevice),
95         DECLARE_NAPI_FUNCTION("selectOutputDeviceByFilter", SelectOutputDeviceByFilter),
96         DECLARE_NAPI_FUNCTION("selectInputDevice", SelectInputDevice),
97         DECLARE_NAPI_FUNCTION("selectInputDeviceByFilter", SelectInputDeviceByFilter),
98         DECLARE_NAPI_FUNCTION("excludeOutputDevices", ExcludeOutputDevices),
99         DECLARE_NAPI_FUNCTION("unexcludeOutputDevices", UnexcludeOutputDevices),
100         DECLARE_NAPI_FUNCTION("setCommunicationDevice", SetCommunicationDevice),
101         DECLARE_NAPI_FUNCTION("isCommunicationDeviceActive", IsCommunicationDeviceActive),
102         DECLARE_NAPI_FUNCTION("isCommunicationDeviceActiveSync", IsCommunicationDeviceActiveSync),
103         DECLARE_NAPI_FUNCTION("getActiveOutputDeviceDescriptors", GetActiveOutputDeviceDescriptors),
104         DECLARE_NAPI_FUNCTION("getPreferredOutputDeviceForRendererInfo", GetPreferredOutputDeviceForRendererInfo),
105         DECLARE_NAPI_FUNCTION("getPreferOutputDeviceForRendererInfo", GetPreferOutputDeviceForRendererInfo),
106         DECLARE_NAPI_FUNCTION("getPreferredOutputDeviceForRendererInfoSync",
107             GetPreferredOutputDeviceForRendererInfoSync),
108         DECLARE_NAPI_FUNCTION("getPreferredOutputDeviceByFilter", GetPreferredOutputDeviceByFilter),
109         DECLARE_NAPI_FUNCTION("getPreferredInputDeviceForCapturerInfo", GetPreferredInputDeviceForCapturerInfo),
110         DECLARE_NAPI_FUNCTION("getPreferredInputDeviceForCapturerInfoSync", GetPreferredInputDeviceForCapturerInfoSync),
111         DECLARE_NAPI_FUNCTION("getPreferredInputDeviceByFilter", GetPreferredInputDeviceByFilter),
112         DECLARE_NAPI_FUNCTION("getAvailableMicrophones", GetAvailableMicrophones),
113         DECLARE_NAPI_FUNCTION("getAvailableDevices", GetAvailableDevices),
114         DECLARE_NAPI_FUNCTION("getExcludedDevices", GetExcludedDevices),
115         DECLARE_NAPI_FUNCTION("on", On),
116         DECLARE_NAPI_FUNCTION("off", Off),
117 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
118         DECLARE_NAPI_FUNCTION("isMicBlockDetectionSupported", IsMicBlockDetectionSupported),
119 #endif
120     };
121 
122     status = napi_define_class(env, NAPI_AUDIO_ROUTING_MANAGER_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct,
123         nullptr, sizeof(audio_routing_manager_properties) / sizeof(audio_routing_manager_properties[PARAM0]),
124         audio_routing_manager_properties, &constructor);
125     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_define_class fail");
126 
127     status = napi_create_reference(env, constructor, refCount, &g_routingManagerConstructor);
128     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_create_reference fail");
129     status = napi_set_named_property(env, exports, NAPI_AUDIO_ROUTING_MANAGER_CLASS_NAME.c_str(), constructor);
130     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_set_named_property fail");
131     return exports;
132 }
133 
CheckContextStatus(std::shared_ptr<AudioRoutingManagerAsyncContext> context)134 bool NapiAudioRoutingManager::CheckContextStatus(std::shared_ptr<AudioRoutingManagerAsyncContext> context)
135 {
136     CHECK_AND_RETURN_RET_LOG(context != nullptr, false, "context object is nullptr.");
137     if (context->native == nullptr) {
138         context->SignError(NAPI_ERR_SYSTEM);
139         AUDIO_ERR_LOG("context object state is error.");
140         return false;
141     }
142     return true;
143 }
144 
CheckAudioRoutingManagerStatus(NapiAudioRoutingManager * napi,std::shared_ptr<AudioRoutingManagerAsyncContext> context)145 bool NapiAudioRoutingManager::CheckAudioRoutingManagerStatus(NapiAudioRoutingManager *napi,
146     std::shared_ptr<AudioRoutingManagerAsyncContext> context)
147 {
148     CHECK_AND_RETURN_RET_LOG(napi != nullptr, false, "napi object is nullptr.");
149     if ((napi->audioMngr_ == nullptr) || (napi->audioRoutingMngr_ == nullptr)) {
150         context->SignError(NAPI_ERR_SYSTEM);
151         AUDIO_ERR_LOG("audioMngr_ is nullptr");
152         return false;
153     }
154 
155     return true;
156 }
157 
GetParamWithSync(const napi_env & env,napi_callback_info info,size_t & argc,napi_value * args)158 NapiAudioRoutingManager* NapiAudioRoutingManager::GetParamWithSync(const napi_env &env, napi_callback_info info,
159     size_t &argc, napi_value *args)
160 {
161     napi_status status;
162     NapiAudioRoutingManager *napiAudioRoutingManager = nullptr;
163     napi_value jsThis = nullptr;
164     status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
165     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr,
166         "GetParamWithSync fail to napi_get_cb_info");
167 
168     status = napi_unwrap(env, jsThis, (void **)&napiAudioRoutingManager);
169     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "napi_unwrap failed");
170     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr && napiAudioRoutingManager->audioMngr_  !=
171         nullptr, napiAudioRoutingManager, "GetParamWithSync fail to napi_unwrap");
172     return napiAudioRoutingManager;
173 }
174 
CreateRoutingManagerWrapper(napi_env env)175 napi_value NapiAudioRoutingManager::CreateRoutingManagerWrapper(napi_env env)
176 {
177     napi_status status;
178     napi_value result = nullptr;
179     napi_value constructor;
180 
181     status = napi_get_reference_value(env, g_routingManagerConstructor, &constructor);
182     if (status != napi_ok) {
183         AUDIO_ERR_LOG("Failed in CreateRoutingManagerWrapper, %{public}d", status);
184         goto fail;
185     }
186     status = napi_new_instance(env, constructor, PARAM0, nullptr, &result);
187     if (status != napi_ok) {
188         AUDIO_ERR_LOG("napi_new_instance failed, status:%{public}d", status);
189         goto fail;
190     }
191     return result;
192 
193 fail:
194     napi_get_undefined(env, &result);
195     return result;
196 }
197 
GetDevices(napi_env env,napi_callback_info info)198 napi_value NapiAudioRoutingManager::GetDevices(napi_env env, napi_callback_info info)
199 {
200     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
201     if (context == nullptr) {
202         AUDIO_ERR_LOG("GetDevices failed : no memory");
203         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
204         return NapiParamUtils::GetUndefinedValue(env);
205     }
206 
207     auto inputParser = [env, context](size_t argc, napi_value *argv) {
208         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments",
209             NAPI_ERR_INVALID_PARAM);
210         context->status = NapiParamUtils::GetValueInt32(env, context->deviceFlag, argv[PARAM0]);
211         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "get deviceFlag failed",
212             NAPI_ERR_INVALID_PARAM);
213         if (!NapiAudioEnum::IsLegalInputArgumentDeviceFlag(context->deviceFlag)) {
214             context->SignError(context->errCode ==
215                 NAPI_ERR_INVALID_PARAM?
216                 NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED);
217         }
218     };
219     context->GetCbInfo(env, info, inputParser);
220 
221     auto executor = [context]() {
222         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
223         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
224         ObjectRefMap objectGuard(obj);
225         auto *napiAudioRoutingManager = objectGuard.GetPtr();
226         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
227             "context object state is error.");
228         context->deviceDescriptors = napiAudioRoutingManager->audioMngr_->GetDevices(
229             static_cast<DeviceFlag>(context->deviceFlag));
230     };
231     auto complete = [env, context](napi_value &output) {
232         NapiParamUtils::SetDeviceDescriptors(env, context->deviceDescriptors, output);
233     };
234     return NapiAsyncWork::Enqueue(env, context, "GetDevices", executor, complete);
235 }
236 
GetDevicesSync(napi_env env,napi_callback_info info)237 napi_value NapiAudioRoutingManager::GetDevicesSync(napi_env env, napi_callback_info info)
238 {
239     napi_value result = nullptr;
240     size_t argc = ARGS_ONE;
241     napi_value argv[ARGS_ONE] = {};
242     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
243     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env,
244         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argCount invalid");
245 
246     napi_valuetype valueType = napi_undefined;
247     napi_typeof(env, argv[PARAM0], &valueType);
248     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env,
249         NAPI_ERR_INPUT_INVALID,
250         "incorrect parameter types: The type of deviceFlag must be number"), "valueType invalid");
251 
252     int32_t deviceFlag;
253     napi_status status = NapiParamUtils::GetValueInt32(env, deviceFlag, argv[PARAM0]);
254     CHECK_AND_RETURN_RET_LOG(NapiAudioEnum::IsLegalInputArgumentDeviceFlag(deviceFlag) && (status == napi_ok),
255         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
256         "parameter verification failed: The param of deviceFlag must be enum DeviceFlag"), "deviceFlag invalid");
257 
258     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
259     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioMngr_ != nullptr, result, "audioMngr_ nullptr");
260     vector<std::shared_ptr<AudioDeviceDescriptor>> deviceDescriptors = napiAudioRoutingManager->audioMngr_->GetDevices(
261         static_cast<DeviceFlag>(deviceFlag));
262 
263     NapiParamUtils::SetDeviceDescriptors(env, deviceDescriptors, result);
264 
265     return result;
266 }
267 
SelectOutputDevice(napi_env env,napi_callback_info info)268 napi_value NapiAudioRoutingManager::SelectOutputDevice(napi_env env, napi_callback_info info)
269 {
270     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
271     if (context == nullptr) {
272         AUDIO_ERR_LOG("SelectOutputDevice failed : no memory");
273         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
274         return NapiParamUtils::GetUndefinedValue(env);
275     }
276 
277     auto inputParser = [env, context](size_t argc, napi_value *argv) {
278         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments",
279             NAPI_ERR_INVALID_PARAM);
280         NapiParamUtils::GetAudioDeviceDescriptorVector(env, context->deviceDescriptors,
281             context->bArgTransFlag, argv[PARAM0]);
282         NAPI_CHECK_ARGS_RETURN_VOID(context, context->bArgTransFlag, "select output device failed",
283             NAPI_ERR_UNSUPPORTED);
284     };
285     context->GetCbInfo(env, info, inputParser);
286 
287     auto executor = [context]() {
288         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
289         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
290         ObjectRefMap objectGuard(obj);
291         auto *napiAudioRoutingManager = objectGuard.GetPtr();
292         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
293             "context object state is error.");
294         context->intValue = napiAudioRoutingManager->audioMngr_->SelectOutputDevice(context->deviceDescriptors);
295         NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS, "SelectOutputDevice failed",
296             NAPI_ERR_SYSTEM);
297     };
298 
299     auto complete = [env](napi_value &output) {
300         output = NapiParamUtils::GetUndefinedValue(env);
301     };
302     return NapiAsyncWork::Enqueue(env, context, "SelectOutputDevice", executor, complete);
303 }
304 
SelectOutputDeviceByFilter(napi_env env,napi_callback_info info)305 napi_value NapiAudioRoutingManager::SelectOutputDeviceByFilter(napi_env env, napi_callback_info info)
306 {
307     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
308     if (context == nullptr) {
309         AUDIO_ERR_LOG("SelectOutputDeviceByFilter failed : no memory");
310         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
311         return NapiParamUtils::GetUndefinedValue(env);
312     }
313 
314     auto inputParser = [env, context](size_t argc, napi_value *argv) {
315         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_TWO, "invalid arguments",
316             NAPI_ERR_INVALID_PARAM);
317         NapiParamUtils::GetAudioRendererFilter(env, context->audioRendererFilter,
318             context->bArgTransFlag, argv[PARAM0]);
319         NapiParamUtils::GetAudioDeviceDescriptorVector(env, context->deviceDescriptors,
320             context->bArgTransFlag, argv[PARAM1]);
321     };
322     context->GetCbInfo(env, info, inputParser);
323 
324     auto executor = [context]() {
325         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
326         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
327         ObjectRefMap objectGuard(obj);
328         auto *napiAudioRoutingManager = objectGuard.GetPtr();
329         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
330             "context object state is error.");
331         if (!context->bArgTransFlag) {
332             context->SignError(NAPI_ERR_UNSUPPORTED);
333         }
334         context->intValue = napiAudioRoutingManager->audioMngr_->SelectOutputDevice(context->audioRendererFilter,
335             context->deviceDescriptors);
336         NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS, "SelectOutputDeviceByFilter failed",
337             NAPI_ERR_SYSTEM);
338     };
339 
340     auto complete = [env](napi_value &output) {
341         output = NapiParamUtils::GetUndefinedValue(env);
342     };
343     return NapiAsyncWork::Enqueue(env, context, "SelectOutputDeviceByFilter", executor, complete);
344 }
345 
SelectInputDevice(napi_env env,napi_callback_info info)346 napi_value NapiAudioRoutingManager::SelectInputDevice(napi_env env, napi_callback_info info)
347 {
348     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
349     if (context == nullptr) {
350         AUDIO_ERR_LOG("SelectInputDevice failed : no memory");
351         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
352         return NapiParamUtils::GetUndefinedValue(env);
353     }
354 
355     auto inputParser = [env, context](size_t argc, napi_value *argv) {
356         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments",
357             NAPI_ERR_INVALID_PARAM);
358         NapiParamUtils::GetAudioDeviceDescriptorVector(env, context->deviceDescriptors,
359             context->bArgTransFlag, argv[PARAM0]);
360     };
361     context->GetCbInfo(env, info, inputParser);
362 
363     auto executor = [context]() {
364         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
365         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
366         ObjectRefMap objectGuard(obj);
367         auto *napiAudioRoutingManager = objectGuard.GetPtr();
368         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
369             "context object state is error.");
370         if (!context->bArgTransFlag) {
371             context->SignError(NAPI_ERR_INVALID_PARAM);
372         }
373         context->intValue = napiAudioRoutingManager->audioMngr_->SelectInputDevice(context->deviceDescriptors);
374         NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS, "SelectInputDevice failed",
375             NAPI_ERR_SYSTEM);
376     };
377 
378     auto complete = [env](napi_value &output) {
379         output = NapiParamUtils::GetUndefinedValue(env);
380     };
381     return NapiAsyncWork::Enqueue(env, context, "SelectInputDevice", executor, complete);
382 }
383 
SelectInputDeviceByFilter(napi_env env,napi_callback_info info)384 napi_value NapiAudioRoutingManager::SelectInputDeviceByFilter(napi_env env, napi_callback_info info)
385 {
386     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
387     if (context == nullptr) {
388         AUDIO_ERR_LOG("SelectInputDeviceByFilter failed : no memory");
389         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
390         return NapiParamUtils::GetUndefinedValue(env);
391     }
392 
393     auto inputParser = [env, context](size_t argc, napi_value *argv) {
394         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_TWO, "invalid arguments",
395             NAPI_ERR_INVALID_PARAM);
396         context->status = NapiParamUtils::GetAudioCapturerFilter(env, context->audioCapturerFilter, argv[PARAM0]);
397         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "select input device by filter failed",
398             NAPI_ERR_INVALID_PARAM);
399         NapiParamUtils::GetAudioDeviceDescriptorVector(env, context->deviceDescriptors,
400             context->bArgTransFlag, argv[PARAM1]);
401     };
402     context->GetCbInfo(env, info, inputParser);
403 
404     auto executor = [context]() {
405         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
406         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
407         ObjectRefMap objectGuard(obj);
408         auto *napiAudioRoutingManager = objectGuard.GetPtr();
409         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
410             "context object state is error.");
411         if (!context->bArgTransFlag) {
412             context->SignError(NAPI_ERR_UNSUPPORTED);
413         }
414         context->intValue = napiAudioRoutingManager->audioMngr_->SelectInputDevice(context->audioCapturerFilter,
415             context->deviceDescriptors);
416         NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS, "SelectInputDevice failed",
417             NAPI_ERR_SYSTEM);
418     };
419 
420     auto complete = [env](napi_value &output) {
421         output = NapiParamUtils::GetUndefinedValue(env);
422     };
423     return NapiAsyncWork::Enqueue(env, context, "SelectInputDeviceByFilter", executor, complete);
424 }
425 
ExcludeOutputDevices(napi_env env,napi_callback_info info)426 napi_value NapiAudioRoutingManager::ExcludeOutputDevices(napi_env env, napi_callback_info info)
427 {
428     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
429     if (context == nullptr) {
430         AUDIO_ERR_LOG("ExcludeOutputDevices failed : no memory");
431         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
432         return NapiParamUtils::GetUndefinedValue(env);
433     }
434 
435     auto inputParser = [env, context](size_t argc, napi_value *argv) {
436         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_TWO, "invalid arguments", NAPI_ERR_INVALID_PARAM);
437         context->status = NapiParamUtils::GetAudioDeviceUsage(env, context->audioDevUsage, argv[PARAM0]);
438         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "exclude output devices failed",
439             NAPI_ERR_UNSUPPORTED);
440         NapiParamUtils::GetAudioDeviceDescriptorVector(env, context->deviceDescriptors,
441             context->bArgTransFlag, argv[PARAM1]);
442     };
443     context->GetCbInfo(env, info, inputParser);
444 
445     auto executor = [context]() {
446         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
447         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
448         ObjectRefMap objectGuard(obj);
449         auto *napiAudioRoutingManager = objectGuard.GetPtr();
450         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
451             "context object state is error.");
452         context->intValue = napiAudioRoutingManager->audioMngr_->ExcludeOutputDevices(context->audioDevUsage,
453             context->deviceDescriptors);
454         NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS, "ExcludeOutputDevices failed",
455             NAPI_ERR_SYSTEM);
456     };
457 
458     auto complete = [env](napi_value &output) {
459         output = NapiParamUtils::GetUndefinedValue(env);
460     };
461     return NapiAsyncWork::Enqueue(env, context, "ExcludeOutputDevices", executor, complete);
462 }
463 
UnexcludeOutputDevices(napi_env env,napi_callback_info info)464 napi_value NapiAudioRoutingManager::UnexcludeOutputDevices(napi_env env, napi_callback_info info)
465 {
466     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
467     if (context == nullptr) {
468         AUDIO_ERR_LOG("UnexcludeOutputDevices failed : no memory");
469         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
470         return NapiParamUtils::GetUndefinedValue(env);
471     }
472 
473     auto inputParser = [env, context](size_t argc, napi_value *argv) {
474         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments", NAPI_ERR_INVALID_PARAM);
475         context->status = NapiParamUtils::GetAudioDeviceUsage(env, context->audioDevUsage, argv[PARAM0]);
476         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "unexclude output devices failed",
477             NAPI_ERR_UNSUPPORTED);
478         context->argSize = argc;
479         if (argc == ARGS_TWO) {
480             NapiParamUtils::GetAudioDeviceDescriptorVector(env, context->deviceDescriptors,
481                 context->bArgTransFlag, argv[PARAM1]);
482         }
483     };
484     context->GetCbInfo(env, info, inputParser);
485 
486     auto executor = [context]() {
487         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
488         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
489         ObjectRefMap objectGuard(obj);
490         auto *napiAudioRoutingManager = objectGuard.GetPtr();
491         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
492             "context object state is error.");
493         if (context->argSize == ARGS_ONE) {
494             context->intValue = napiAudioRoutingManager->audioMngr_->UnexcludeOutputDevices(context->audioDevUsage);
495         } else {
496             context->intValue = napiAudioRoutingManager->audioMngr_->UnexcludeOutputDevices(context->audioDevUsage,
497                 context->deviceDescriptors);
498         }
499         NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS, "UnexcludeOutputDevices failed",
500             NAPI_ERR_SYSTEM);
501     };
502 
503     auto complete = [env](napi_value &output) {
504         output = NapiParamUtils::GetUndefinedValue(env);
505     };
506     return NapiAsyncWork::Enqueue(env, context, "UnexcludeOutputDevices", executor, complete);
507 }
508 
SetCommunicationDevice(napi_env env,napi_callback_info info)509 napi_value NapiAudioRoutingManager::SetCommunicationDevice(napi_env env, napi_callback_info info)
510 {
511     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
512     if (context == nullptr) {
513         AUDIO_ERR_LOG("SetCommunicationDevice failed : no memory");
514         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
515         return NapiParamUtils::GetUndefinedValue(env);
516     }
517 
518     auto inputParser = [env, context](size_t argc, napi_value *argv) {
519         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_TWO, "invalid arguments",
520             NAPI_ERR_INVALID_PARAM);
521         context->status = NapiParamUtils::GetValueInt32(env, context->deviceType, argv[PARAM0]);
522         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "set communication device failed",
523             NAPI_ERR_INVALID_PARAM);
524         if (!NapiAudioEnum::IsLegalInputArgumentCommunicationDeviceType(context->deviceType)) {
525             context->SignError(context->errCode == NAPI_ERR_INVALID_PARAM?
526                 NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED);
527         }
528         context->status = NapiParamUtils::GetValueBoolean(env, context->isActive, argv[PARAM1]);
529         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "set communication device failed",
530             NAPI_ERR_INVALID_PARAM);
531     };
532     context->GetCbInfo(env, info, inputParser);
533 
534     auto executor = [context]() {
535         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
536         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
537         ObjectRefMap objectGuard(obj);
538         auto *napiAudioRoutingManager = objectGuard.GetPtr();
539         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
540             "context object state is error.");
541         context->intValue = napiAudioRoutingManager->audioMngr_->SetDeviceActive(
542             static_cast<DeviceType>(context->deviceType), context->isActive);
543         NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS, "SelectInputDevice failed",
544             NAPI_ERR_SYSTEM);
545     };
546 
547     auto complete = [env](napi_value &output) {
548         output = NapiParamUtils::GetUndefinedValue(env);
549     };
550     return NapiAsyncWork::Enqueue(env, context, "SetCommunicationDevice", executor, complete);
551 }
552 
IsCommunicationDeviceActive(napi_env env,napi_callback_info info)553 napi_value NapiAudioRoutingManager::IsCommunicationDeviceActive(napi_env env, napi_callback_info info)
554 {
555     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
556     if (context == nullptr) {
557         AUDIO_ERR_LOG("IsCommunicationDeviceActive failed : no memory");
558         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
559         return NapiParamUtils::GetUndefinedValue(env);
560     }
561 
562     auto inputParser = [env, context](size_t argc, napi_value *argv) {
563         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments",
564             NAPI_ERR_INVALID_PARAM);
565         context->status = NapiParamUtils::GetValueInt32(env, context->deviceType, argv[PARAM0]);
566         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "IsCommunicationDeviceActive failed",
567             NAPI_ERR_INVALID_PARAM);
568         if (!NapiAudioEnum::IsLegalInputArgumentActiveDeviceType(context->deviceType)) {
569             context->SignError(context->errCode == NAPI_ERR_INVALID_PARAM?
570                 NAPI_ERR_INVALID_PARAM: NAPI_ERR_UNSUPPORTED);
571         }
572     };
573     context->GetCbInfo(env, info, inputParser);
574 
575     auto executor = [context]() {
576         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
577         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
578         ObjectRefMap objectGuard(obj);
579         auto *napiAudioRoutingManager = objectGuard.GetPtr();
580         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
581             "context object state is error.");
582         context->isActive = napiAudioRoutingManager->audioMngr_->IsDeviceActive(
583             static_cast<DeviceType>(context->deviceType));
584         context->isTrue = context->isActive;
585     };
586 
587     auto complete = [env, context](napi_value &output) {
588         NapiParamUtils::SetValueBoolean(env, context->isTrue, output);
589     };
590     return NapiAsyncWork::Enqueue(env, context, "IsCommunicationDeviceActive", executor, complete);
591 }
592 
IsCommunicationDeviceActiveSync(napi_env env,napi_callback_info info)593 napi_value NapiAudioRoutingManager::IsCommunicationDeviceActiveSync(napi_env env, napi_callback_info info)
594 {
595     napi_value result = nullptr;
596     size_t argc = ARGS_ONE;
597     napi_value argv[ARGS_ONE] = {};
598     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
599     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env,
600         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argCount invalid");
601 
602     napi_valuetype valueType = napi_undefined;
603     napi_typeof(env, argv[PARAM0], &valueType);
604     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env,
605         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of deviceType must be number"),
606         "valueType invalid");
607 
608     int32_t deviceType;
609     napi_status status = NapiParamUtils::GetValueInt32(env, deviceType, argv[PARAM0]);
610     CHECK_AND_RETURN_RET_LOG(NapiAudioEnum::IsLegalInputArgumentActiveDeviceType(deviceType) && status == napi_ok,
611         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
612         "parameter verification failed: The param of deviceType must be enum CommunicationDeviceType"),
613         "valueType invalid");
614 
615     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
616     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioMngr_ != nullptr, result, "audioMngr_ nullptr");
617     bool isActive = napiAudioRoutingManager->audioMngr_->IsDeviceActive(static_cast<DeviceType>(deviceType));
618 
619     NapiParamUtils::SetValueBoolean(env, isActive, result);
620     return result;
621 }
622 
GetActiveOutputDeviceDescriptors(napi_env env,napi_callback_info info)623 napi_value NapiAudioRoutingManager::GetActiveOutputDeviceDescriptors(napi_env env, napi_callback_info info)
624 {
625     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
626     if (context == nullptr) {
627         AUDIO_ERR_LOG("GetActiveOutputDeviceDescriptors failed : no memory");
628         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
629         return NapiParamUtils::GetUndefinedValue(env);
630     }
631 
632     context->GetCbInfo(env, info);
633 
634     auto executor = [context]() {
635         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
636         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
637         ObjectRefMap objectGuard(obj);
638         auto *napiAudioRoutingManager = objectGuard.GetPtr();
639         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
640             "context object state is error.");
641         context->outDeviceDescriptors = napiAudioRoutingManager->audioMngr_->GetActiveOutputDeviceDescriptors();
642     };
643 
644     auto complete = [env, context](napi_value &output) {
645         NapiParamUtils::SetDeviceDescriptors(env, context->outDeviceDescriptors, output);
646     };
647     return NapiAsyncWork::Enqueue(env, context, "GetActiveOutputDeviceDescriptors", executor, complete);
648 }
649 
GetPreferredOutputDeviceForRendererInfo(napi_env env,napi_callback_info info)650 napi_value NapiAudioRoutingManager::GetPreferredOutputDeviceForRendererInfo(napi_env env, napi_callback_info info)
651 {
652     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
653     if (context == nullptr) {
654         AUDIO_ERR_LOG("GetPreferredOutputDeviceForRendererInfo failed : no memory");
655         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
656         return NapiParamUtils::GetUndefinedValue(env);
657     }
658 
659     auto inputParser = [env, context](size_t argc, napi_value *argv) {
660         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "mandatory parameters are left unspecified",
661             NAPI_ERR_INPUT_INVALID);
662         context->status = NapiParamUtils::GetRendererInfo(env, &(context->rendererInfo), argv[PARAM0]);
663         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
664             "incorrect parameter types: The type of rendererInfo must be interface AudioRendererInfo",
665             NAPI_ERR_INPUT_INVALID);
666     };
667     context->GetCbInfo(env, info, inputParser);
668     if (context->status != napi_ok) {
669         NapiAudioError::ThrowError(env, context->errCode, context->errMessage);
670         return NapiParamUtils::GetUndefinedValue(env);
671     }
672 
673     auto executor = [context]() {
674         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
675         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
676         ObjectRefMap objectGuard(obj);
677         auto *napiAudioRoutingManager = objectGuard.GetPtr();
678         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
679             "context object state is error.");
680         if (context->rendererInfo.streamUsage == StreamUsage::STREAM_USAGE_INVALID) {
681             context->SignError(NAPI_ERR_INVALID_PARAM,
682                 "parameter verification failed: The param of usage invalid");
683         } else {
684             context->intValue = napiAudioRoutingManager->audioRoutingMngr_->GetPreferredOutputDeviceForRendererInfo(
685                 context->rendererInfo, context->outDeviceDescriptors);
686             NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS,
687                 "GetPreferredOutputDeviceForRendererInfo failed", NAPI_ERR_SYSTEM);
688         }
689     };
690 
691     auto complete = [env, context](napi_value &output) {
692         NapiParamUtils::SetDeviceDescriptors(env, context->outDeviceDescriptors, output);
693     };
694     return NapiAsyncWork::Enqueue(env, context, "GetPreferredOutputDeviceForRendererInfo", executor, complete);
695 }
696 
GetPreferOutputDeviceForRendererInfo(napi_env env,napi_callback_info info)697 napi_value NapiAudioRoutingManager::GetPreferOutputDeviceForRendererInfo(napi_env env, napi_callback_info info)
698 {
699     // for api compatibility, leave some time for applications to adapt to new one
700     return GetPreferredOutputDeviceForRendererInfo(env, info);
701 }
702 
GetPreferredOutputDeviceForRendererInfoSync(napi_env env,napi_callback_info info)703 napi_value NapiAudioRoutingManager::GetPreferredOutputDeviceForRendererInfoSync(napi_env env, napi_callback_info info)
704 {
705     AUDIO_INFO_LOG("GetPreferredOutputDeviceForRendererInfoSync");
706     napi_value result = nullptr;
707     size_t argc = ARGS_ONE;
708     napi_value argv[ARGS_ONE] = {};
709     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
710     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env,
711         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argCount invalid");
712 
713     napi_valuetype valueType = napi_undefined;
714     napi_typeof(env, argv[PARAM0], &valueType);
715     CHECK_AND_RETURN_RET_LOG(valueType == napi_object, NapiAudioError::ThrowErrorAndReturn(env,
716         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of rendererInfo must be object"),
717         "valueType invalid");
718 
719     AudioRendererInfo rendererInfo;
720     if (NapiParamUtils::GetRendererInfo(env, &rendererInfo, argv[PARAM0]) != napi_ok) {
721         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
722             "incorrect parameter types: The type of rendererInfo must be interface AudioRendererInfo");
723         return result;
724     } else if (rendererInfo.streamUsage == StreamUsage::STREAM_USAGE_INVALID) {
725         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
726             "parameter verification failed: The param of usage invalid");
727         return result;
728     }
729 
730     vector<std::shared_ptr<AudioDeviceDescriptor>> outDeviceDescriptors;
731     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
732     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioRoutingMngr_ != nullptr, result,
733         "audioRoutingMngr_ nullptr");
734     napiAudioRoutingManager->audioRoutingMngr_->GetPreferredOutputDeviceForRendererInfo(
735         rendererInfo, outDeviceDescriptors);
736 
737     NapiParamUtils::SetDeviceDescriptors(env, outDeviceDescriptors, result);
738 
739     return result;
740 }
741 
742 
GetPreferredOutputDeviceByFilter(napi_env env,napi_callback_info info)743 napi_value NapiAudioRoutingManager::GetPreferredOutputDeviceByFilter(napi_env env, napi_callback_info info)
744 {
745     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
746     if (context == nullptr) {
747         AUDIO_ERR_LOG("GetPreferredOutputDeviceByFilter failed : no memory");
748         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
749         return NapiParamUtils::GetUndefinedValue(env);
750     }
751 
752     auto inputParser = [env, context](size_t argc, napi_value *argv) {
753         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments",
754             NAPI_ERR_INVALID_PARAM);
755         context->status = NapiParamUtils::GetAudioRendererFilter(env, context->audioRendererFilter,
756             context->bArgTransFlag, argv[PARAM0]);
757         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "get AudioRendererFilter failed",
758             NAPI_ERR_INVALID_PARAM);
759     };
760     context->GetCbInfo(env, info, inputParser);
761 
762     auto executor = [context]() {
763         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
764         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
765         ObjectRefMap objectGuard(obj);
766         auto *napiAudioRoutingManager = objectGuard.GetPtr();
767         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
768             "context object state is error.");
769         context->deviceDescriptors = napiAudioRoutingManager->audioMngr_->GetOutputDevice(context->audioRendererFilter);
770     };
771     auto complete = [env, context](napi_value &output) {
772         NapiParamUtils::SetDeviceDescriptors(env, context->deviceDescriptors, output);
773     };
774     return NapiAsyncWork::Enqueue(env, context, "GetPreferredOutputDeviceByFilter", executor, complete);
775 }
776 
GetPreferredInputDeviceForCapturerInfo(napi_env env,napi_callback_info info)777 napi_value NapiAudioRoutingManager::GetPreferredInputDeviceForCapturerInfo(napi_env env, napi_callback_info info)
778 {
779     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
780     if (context == nullptr) {
781         AUDIO_ERR_LOG("GetPreferredInputDeviceForCapturerInfo failed : no memory");
782         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
783         return NapiParamUtils::GetUndefinedValue(env);
784     }
785 
786     auto inputParser = [env, context](size_t argc, napi_value *argv) {
787         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "mandatory parameters are left unspecified",
788             NAPI_ERR_INPUT_INVALID);
789         context->status = NapiParamUtils::GetAudioCapturerInfo(env, &context->captureInfo, argv[PARAM0]);
790         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
791             "incorrect parameter types: The type of capturerInfo must be interface AudioCapturerInfo",
792             NAPI_ERR_INPUT_INVALID);
793     };
794     context->GetCbInfo(env, info, inputParser);
795 
796     if (context->status != napi_ok) {
797         NapiAudioError::ThrowError(env, context->errCode, context->errMessage);
798         return NapiParamUtils::GetUndefinedValue(env);
799     }
800 
801     auto executor = [context]() {
802         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
803         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
804         ObjectRefMap objectGuard(obj);
805         auto *napiAudioRoutingManager = objectGuard.GetPtr();
806         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
807             "context object state is error.");
808         if (context->captureInfo.sourceType == SourceType::SOURCE_TYPE_INVALID) {
809             context->SignError(NAPI_ERR_INVALID_PARAM,
810                 "parameter verification failed: The param of sourceType invalid");
811         } else {
812             context->intValue = napiAudioRoutingManager->audioRoutingMngr_->GetPreferredInputDeviceForCapturerInfo(
813                 context->captureInfo, context->inputDeviceDescriptors);
814             NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS,
815                 "GetPreferredInputDeviceForCapturerInfo failed", NAPI_ERR_SYSTEM);
816         }
817     };
818 
819     auto complete = [env, context](napi_value &output) {
820         NapiParamUtils::SetDeviceDescriptors(env, context->inputDeviceDescriptors, output);
821     };
822     return NapiAsyncWork::Enqueue(env, context, "GetPreferredInputDeviceForCapturerInfo", executor, complete);
823 }
824 
GetPreferredInputDeviceForCapturerInfoSync(napi_env env,napi_callback_info info)825 napi_value NapiAudioRoutingManager::GetPreferredInputDeviceForCapturerInfoSync(napi_env env, napi_callback_info info)
826 {
827     napi_value result = nullptr;
828     size_t argc = ARGS_ONE;
829     napi_value argv[ARGS_ONE] = {};
830     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
831     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env,
832         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argCount invalid");
833 
834     napi_valuetype valueType = napi_undefined;
835     napi_typeof(env, argv[PARAM0], &valueType);
836     CHECK_AND_RETURN_RET_LOG(valueType == napi_object,
837         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
838         "incorrect parameter types: The type of capturerInfo must be object"), "valueType invalid");
839 
840     AudioCapturerInfo capturerInfo;
841     napi_status status = NapiParamUtils::GetAudioCapturerInfo(env, &capturerInfo, argv[PARAM0]);
842     CHECK_AND_RETURN_RET_LOG((capturerInfo.sourceType != SourceType::SOURCE_TYPE_INVALID) && (status == napi_ok),
843         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
844         "parameter verification failed: The param of capturerInfo must be interface AudioCapturerInfo"),
845         "sourceType invalid");
846 
847     vector<std::shared_ptr<AudioDeviceDescriptor>> outDeviceDescriptors;
848     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
849     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioRoutingMngr_ != nullptr, result,
850         "audioRoutingMngr_ nullptr");
851     napiAudioRoutingManager->audioRoutingMngr_->GetPreferredInputDeviceForCapturerInfo(
852         capturerInfo, outDeviceDescriptors);
853 
854     NapiParamUtils::SetDeviceDescriptors(env, outDeviceDescriptors, result);
855 
856     return result;
857 }
858 
GetPreferredInputDeviceByFilter(napi_env env,napi_callback_info info)859 napi_value NapiAudioRoutingManager::GetPreferredInputDeviceByFilter(napi_env env, napi_callback_info info)
860 {
861     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
862     if (context == nullptr) {
863         AUDIO_ERR_LOG("GetPreferredInputDeviceByFilter failed : no memory");
864         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
865         return NapiParamUtils::GetUndefinedValue(env);
866     }
867 
868     auto inputParser = [env, context](size_t argc, napi_value *argv) {
869         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments",
870             NAPI_ERR_INVALID_PARAM);
871         context->status = NapiParamUtils::GetAudioCapturerFilter(env, context->audioCapturerFilter, argv[PARAM0]);
872         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "get GetAudioCapturerFilter failed",
873             NAPI_ERR_INVALID_PARAM);
874     };
875     context->GetCbInfo(env, info, inputParser);
876 
877     auto executor = [context]() {
878         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
879         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
880         ObjectRefMap objectGuard(obj);
881         auto *napiAudioRoutingManager = objectGuard.GetPtr();
882         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
883             "context object state is error.");
884         context->deviceDescriptors = napiAudioRoutingManager->audioMngr_->GetInputDevice(context->audioCapturerFilter);
885     };
886     auto complete = [env, context](napi_value &output) {
887         NapiParamUtils::SetDeviceDescriptors(env, context->deviceDescriptors, output);
888     };
889     return NapiAsyncWork::Enqueue(env, context, "GetPreferredInputDeviceByFilter", executor, complete);
890 }
891 
GetAvailableMicrophones(napi_env env,napi_callback_info info)892 napi_value NapiAudioRoutingManager::GetAvailableMicrophones(napi_env env, napi_callback_info info)
893 {
894     AUDIO_INFO_LOG("GetAvailableMicrophones");
895     napi_value result = nullptr;
896     size_t argc = PARAM0;
897     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, nullptr);
898     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env,
899         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argCount invalid");
900     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
901     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioRoutingMngr_ != nullptr, result,
902         "audioRoutingMngr_ is nullptr");
903 
904     vector<sptr<MicrophoneDescriptor>> micDescs =
905         napiAudioRoutingManager->audioRoutingMngr_->GetAvailableMicrophones();
906 
907     NapiParamUtils::SetMicrophoneDescriptors(env, micDescs, result);
908 
909     return result;
910 }
911 
GetAvailableDevices(napi_env env,napi_callback_info info)912 napi_value NapiAudioRoutingManager::GetAvailableDevices(napi_env env, napi_callback_info info)
913 {
914     napi_value result = nullptr;
915     size_t argc = ARGS_ONE;
916     napi_value argv[ARGS_ONE] = {};
917     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
918     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env,
919         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argcCount invalid");
920 
921     napi_valuetype valueType = napi_undefined;
922     napi_status status = napi_typeof(env, argv[PARAM0], &valueType);
923     CHECK_AND_RETURN_RET_LOG(status == napi_ok && valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env,
924         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of deviceUsage must be number"),
925         "valueType invalid");
926 
927     int32_t intValue = 0;
928     status = napi_get_value_int32(env, argv[PARAM0], &intValue);
929     CHECK_AND_RETURN_RET_LOG(status == napi_ok && NapiAudioEnum::IsLegalDeviceUsage(intValue),
930         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
931         "parameter verification failed: The param of deviceUsage must be enum DeviceUsage"), "invalid deviceusage");
932 
933     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
934     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioRoutingMngr_ != nullptr, result,
935         "audioRoutingMngr_ is nullptr");
936     AudioDeviceUsage usage = static_cast<AudioDeviceUsage>(intValue);
937 
938     vector<std::shared_ptr<AudioDeviceDescriptor>> availableDescs =
939         napiAudioRoutingManager->audioRoutingMngr_->GetAvailableDevices(usage);
940 
941     vector<std::shared_ptr<AudioDeviceDescriptor>> availableSptrDescs;
942     for (const auto &availableDesc : availableDescs) {
943         std::shared_ptr<AudioDeviceDescriptor> dec = std::make_shared<AudioDeviceDescriptor>(*availableDesc);
944         CHECK_AND_BREAK_LOG(dec != nullptr, "dec mallac failed,no memery.");
945         availableSptrDescs.push_back(dec);
946     }
947     NapiParamUtils::SetDeviceDescriptors(env, availableSptrDescs, result);
948     return result;
949 }
950 
GetExcludedDevices(napi_env env,napi_callback_info info)951 napi_value NapiAudioRoutingManager::GetExcludedDevices(napi_env env, napi_callback_info info)
952 {
953     napi_value result = nullptr;
954     size_t argc = ARGS_ONE;
955     napi_value argv[ARGS_ONE] = {};
956     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
957     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
958     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioMngr_ != nullptr, result,
959         "audioMngr_ is nullptr");
960     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
961         "mandatory parameters are left unspecified"), "argCount invalid");
962 
963     AudioDeviceUsage audioDevUsage;
964     napi_status status = NapiParamUtils::GetAudioDeviceUsage(env, audioDevUsage, argv[PARAM0]);
965     CHECK_AND_RETURN_RET_LOG(status == napi_ok, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
966         "parameter verification failed: The param of deviceUsage must be enum DeviceUsage"),
967         "exclude output devices failed");
968     vector<shared_ptr<AudioDeviceDescriptor>> excludedDevices =
969         napiAudioRoutingManager->audioMngr_->GetExcludedDevices(audioDevUsage);
970     NapiParamUtils::SetDeviceDescriptors(env, excludedDevices, result);
971     return result;
972 }
973 
RegisterCallback(napi_env env,napi_value jsThis,size_t argc,napi_value * args,const std::string & cbName)974 napi_value NapiAudioRoutingManager::RegisterCallback(napi_env env, napi_value jsThis, size_t argc,
975     napi_value *args, const std::string &cbName)
976 {
977     napi_value undefinedResult = nullptr;
978     NapiAudioRoutingManager *napiRoutingMgr = nullptr;
979     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void**>(&napiRoutingMgr));
980     if ((status != napi_ok) || (napiRoutingMgr == nullptr) || (napiRoutingMgr->audioMngr_ == nullptr) ||
981         (napiRoutingMgr->audioRoutingMngr_ == nullptr)) {
982         AUDIO_ERR_LOG("NapiAudioRoutingManager::Failed to retrieve stream mgr napi instance.");
983         return undefinedResult;
984     }
985 
986     if (!cbName.compare(DEVICE_CHANGE_CALLBACK_NAME)) {
987         RegisterDeviceChangeCallback(env, argc, args, cbName, napiRoutingMgr);
988     } else if (!cbName.compare(PREFERRED_OUTPUT_DEVICE_CALLBACK_NAME) ||
989         !cbName.compare(PREFER_OUTPUT_DEVICE_CALLBACK_NAME)) {
990         RegisterPreferredOutputDeviceChangeCallback(env, argc, args, cbName, napiRoutingMgr);
991     } else if (!cbName.compare(PREFERRED_INPUT_DEVICE_CALLBACK_NAME)) {
992         RegisterPreferredInputDeviceChangeCallback(env, argc, args, cbName, napiRoutingMgr);
993     } else if (!cbName.compare(AVAILABLE_DEVICE_CHANGE_CALLBACK_NAME)) {
994         RegisterAvaiableDeviceChangeCallback(env, argc, args, cbName, napiRoutingMgr);
995     } else if (!cbName.compare(MICROPHONE_BLOCKED_CALLBACK_NAME)) {
996         RegisterMicrophoneBlockedCallback(env, argc, args, cbName, napiRoutingMgr);
997     } else {
998         AUDIO_ERR_LOG("NapiAudioRoutingManager::No such supported");
999         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
1000             "parameter verification failed: The param of type is not supported");
1001     }
1002     return undefinedResult;
1003 }
1004 
RegisterDeviceChangeCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,NapiAudioRoutingManager * napiRoutingMgr)1005 void NapiAudioRoutingManager::RegisterDeviceChangeCallback(napi_env env, size_t argc, napi_value *args,
1006     const std::string &cbName, NapiAudioRoutingManager *napiRoutingMgr)
1007 {
1008     int32_t flag = ARGS_THREE;
1009     napi_valuetype valueType = napi_undefined;
1010     napi_typeof(env, args[PARAM1], &valueType);
1011     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowError(env,
1012         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of deviceFlag must be number"),
1013         "invalid valueType");
1014     if (valueType == napi_number) {
1015         NapiParamUtils::GetValueInt32(env, flag, args[PARAM1]);
1016         AUDIO_INFO_LOG("RegisterDeviceChangeCallback:On deviceFlag: %{public}d", flag);
1017         if (!NapiAudioEnum::IsLegalInputArgumentDeviceFlag(flag)) {
1018             NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
1019                 "parameter verification failed: The param of deviceFlag must be enum DeviceFlag");
1020         }
1021     }
1022 
1023     napi_valuetype handler = napi_undefined;
1024     napi_typeof(env, args[PARAM2], &handler);
1025 
1026     if (handler != napi_function) {
1027         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1028             "incorrect parameter types: The type of callback must be function");
1029     }
1030     DeviceFlag deviceFlag = DeviceFlag(flag);
1031     if (!napiRoutingMgr->deviceChangeCallbackNapi_) {
1032         napiRoutingMgr->deviceChangeCallbackNapi_ = std::make_shared<NapiAudioManagerCallback>(env);
1033     }
1034     CHECK_AND_RETURN_LOG(napiRoutingMgr->deviceChangeCallbackNapi_,
1035         "RegisterDeviceChangeCallback: Memory Allocation Failed !");
1036 
1037     int32_t ret = napiRoutingMgr->audioMngr_->SetDeviceChangeCallback(deviceFlag,
1038         napiRoutingMgr->deviceChangeCallbackNapi_);
1039     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
1040         "RegisterDeviceChangeCallback: Registering Device Change Callback Failed %{public}d", ret);
1041 
1042     std::shared_ptr<NapiAudioManagerCallback> cb =
1043         std::static_pointer_cast<NapiAudioManagerCallback>(napiRoutingMgr->deviceChangeCallbackNapi_);
1044     cb->SaveRoutingManagerDeviceChangeCbRef(deviceFlag, args[PARAM2]);
1045     if (!cb->GetDevChgTsfnFlag()) {
1046         cb->CreateDevChgTsfn(env);
1047     }
1048 }
1049 
GetNapiPrefOutputDeviceChangeCb(napi_value args,NapiAudioRoutingManager * napiRoutingMgr)1050 std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> NapiAudioRoutingManager::GetNapiPrefOutputDeviceChangeCb(
1051     napi_value args, NapiAudioRoutingManager *napiRoutingMgr)
1052 {
1053     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredOutputDeviceMutex_);
1054     std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb = nullptr;
1055     for (auto &iter : napiRoutingMgr->preferredOutputDeviceCallbacks_) {
1056         if (iter->ContainSameJsCallback(args)) {
1057             cb = iter;
1058         }
1059     }
1060     return cb;
1061 }
1062 
AddPreferredOutputDeviceChangeCallback(NapiAudioRoutingManager * napiRoutingMgr,std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb)1063 void NapiAudioRoutingManager::AddPreferredOutputDeviceChangeCallback(NapiAudioRoutingManager *napiRoutingMgr,
1064     std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb)
1065 {
1066     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredOutputDeviceMutex_);
1067     napiRoutingMgr->preferredOutputDeviceCallbacks_.push_back(cb);
1068 }
1069 
RegisterPreferredOutputDeviceChangeCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,NapiAudioRoutingManager * napiRoutingMgr)1070 void NapiAudioRoutingManager::RegisterPreferredOutputDeviceChangeCallback(napi_env env, size_t argc, napi_value *args,
1071     const std::string &cbName, NapiAudioRoutingManager *napiRoutingMgr)
1072 {
1073     CHECK_AND_RETURN_RET_LOG(argc == ARGS_THREE, NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1074         "incorrect number of parameters: expected at least 3 parameters"), "argc invalid");
1075 
1076     CHECK_AND_RETURN_RET_LOG(NapiParamUtils::CheckArgType(env, args[PARAM1], napi_object),
1077         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1078         "incorrect parameter types: The type of rendererInfo must be object"), "rendererInfo invalid");
1079 
1080     CHECK_AND_RETURN_RET_LOG(NapiParamUtils::CheckArgType(env, args[PARAM2], napi_function),
1081         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1082         "incorrect parameter types: The type of callback must be function"), "callback invalid");
1083 
1084     CHECK_AND_RETURN_LOG(GetNapiPrefOutputDeviceChangeCb(args[PARAM2], napiRoutingMgr) == nullptr,
1085         "Do not allow duplicate registration of the same callback");
1086 
1087     AudioRendererInfo rendererInfo;
1088     NapiParamUtils::GetRendererInfo(env, &rendererInfo, args[PARAM1]);
1089     CHECK_AND_RETURN_RET_LOG(rendererInfo.streamUsage != StreamUsage::STREAM_USAGE_INVALID,
1090         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
1091         "parameter verification failed: The param of streamUsage invalid"), "invalid streamUsage");
1092     std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb =
1093         std::make_shared<NapiAudioPreferredOutputDeviceChangeCallback>(env);
1094     CHECK_AND_RETURN_LOG(cb != nullptr, "Memory allocation failed!!");
1095 
1096     cb->SaveCallbackReference(args[PARAM2]);
1097     cb->CreatePreferredOutTsfn(env);
1098 
1099     int32_t ret = napiRoutingMgr->audioRoutingMngr_->SetPreferredOutputDeviceChangeCallback(
1100         rendererInfo, cb);
1101     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
1102         "Registering Preferred Output Device Change Callback Failed %{public}d", ret);
1103 
1104     AddPreferredOutputDeviceChangeCallback(napiRoutingMgr, cb);
1105 }
1106 
GetNapiPrefInputDeviceChangeCb(napi_value args,NapiAudioRoutingManager * napiRoutingMgr)1107 std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> NapiAudioRoutingManager::GetNapiPrefInputDeviceChangeCb(
1108     napi_value args, NapiAudioRoutingManager *napiRoutingMgr)
1109 {
1110     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredInputDeviceMutex_);
1111     std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb = nullptr;
1112     for (auto &iter : napiRoutingMgr->preferredInputDeviceCallbacks_) {
1113         if (iter->ContainSameJsCallback(args)) {
1114             cb = iter;
1115         }
1116     }
1117     return cb;
1118 }
1119 
AddPreferredInputDeviceChangeCallback(NapiAudioRoutingManager * napiRoutingMgr,std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb)1120 void NapiAudioRoutingManager::AddPreferredInputDeviceChangeCallback(NapiAudioRoutingManager *napiRoutingMgr,
1121     std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb)
1122 {
1123     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredInputDeviceMutex_);
1124     napiRoutingMgr->preferredInputDeviceCallbacks_.push_back(cb);
1125 }
1126 
RegisterPreferredInputDeviceChangeCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,NapiAudioRoutingManager * napiRoutingMgr)1127 void NapiAudioRoutingManager::RegisterPreferredInputDeviceChangeCallback(napi_env env, size_t argc, napi_value *args,
1128     const std::string &cbName, NapiAudioRoutingManager *napiRoutingMgr)
1129 {
1130     CHECK_AND_RETURN_RET_LOG(argc >= ARGS_THREE, NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1131         "mandatory parameters are left unspecified"), "argCount invalid");
1132 
1133     CHECK_AND_RETURN_RET_LOG(NapiParamUtils::CheckArgType(env, args[PARAM1], napi_object),
1134         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1135         "incorrect parameter types: The type of capturerInfo must be object"), "capturerInfo invalid");
1136 
1137     CHECK_AND_RETURN_RET_LOG(NapiParamUtils::CheckArgType(env, args[PARAM2], napi_function),
1138         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1139         "incorrect parameter types: The type of callback must be function"), "callback invalid");
1140 
1141     CHECK_AND_RETURN_LOG(GetNapiPrefInputDeviceChangeCb(args[PARAM2], napiRoutingMgr) == nullptr,
1142         "Do not allow duplicate registration of the same callback");
1143 
1144     AudioCapturerInfo captureInfo;
1145     NapiParamUtils::GetAudioCapturerInfo(env, &captureInfo, args[PARAM1]);
1146 
1147     CHECK_AND_RETURN_RET_LOG(captureInfo.sourceType != SourceType::SOURCE_TYPE_INVALID,
1148         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
1149         "parameter verification failed: The param of sourceType invalid"), "invalid sourceType");
1150 
1151     std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb =
1152         std::make_shared<NapiAudioPreferredInputDeviceChangeCallback>(env);
1153     CHECK_AND_RETURN_LOG(cb != nullptr, "Memory allocation failed!!");
1154 
1155     cb->SaveCallbackReference(args[PARAM2]);
1156     cb->CreatePreferredInTsfn(env);
1157 
1158     int32_t ret = napiRoutingMgr->audioRoutingMngr_->SetPreferredInputDeviceChangeCallback(
1159         captureInfo, cb);
1160     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
1161         "Registering Preferred Input Device Change Callback Failed %{public}d", ret);
1162 
1163     AddPreferredInputDeviceChangeCallback(napiRoutingMgr, cb);
1164 }
1165 
RegisterAvaiableDeviceChangeCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,NapiAudioRoutingManager * napiRoutingMgr)1166 void NapiAudioRoutingManager::RegisterAvaiableDeviceChangeCallback(napi_env env, size_t argc, napi_value *args,
1167     const std::string &cbName, NapiAudioRoutingManager *napiRoutingMgr)
1168 {
1169     int32_t flag = 0;
1170     napi_valuetype valueType = napi_undefined;
1171     napi_typeof(env, args[PARAM1], &valueType);
1172     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowError(env,
1173         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of deviceUsage must be number"),
1174         "invalid Type");
1175 
1176     NapiParamUtils::GetValueInt32(env, flag, args[PARAM1]);
1177     AUDIO_INFO_LOG("RegisterDeviceChangeCallback:On deviceFlag: %{public}d", flag);
1178     if (!NapiAudioEnum::IsLegalDeviceUsage(flag)) {
1179         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
1180             "parameter verification failed: The param of deviceUsage must be enum DeviceUsage");
1181     }
1182 
1183     napi_valuetype handler = napi_undefined;
1184     napi_typeof(env, args[PARAM2], &handler);
1185     if (handler != napi_function) {
1186         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1187             "incorrect parameter types: The type of callback must be function");
1188     }
1189     AudioDeviceUsage usage = static_cast<AudioDeviceUsage>(flag);
1190     if (!napiRoutingMgr->availableDeviceChangeCallbackNapi_) {
1191         napiRoutingMgr->availableDeviceChangeCallbackNapi_ =
1192             std::make_shared<NapiAudioRountingAvailableDeviceChangeCallback>(env);
1193     }
1194     CHECK_AND_RETURN_LOG(napiRoutingMgr->availableDeviceChangeCallbackNapi_ != nullptr,
1195         "RegisterDeviceChangeCallback: Memory Allocation Failed !");
1196 
1197     int32_t ret = napiRoutingMgr->audioMngr_->SetAvailableDeviceChangeCallback(usage,
1198         napiRoutingMgr->availableDeviceChangeCallbackNapi_);
1199     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
1200         "RegisterDeviceChangeCallback: Registering Device Change Callback Failed %{public}d", ret);
1201 
1202     std::shared_ptr<NapiAudioRountingAvailableDeviceChangeCallback> cb =
1203         std::static_pointer_cast<NapiAudioRountingAvailableDeviceChangeCallback>(
1204         napiRoutingMgr->availableDeviceChangeCallbackNapi_);
1205     cb->SaveRoutingAvailbleDeviceChangeCbRef(usage, args[PARAM2]);
1206     if (!cb->GetRouDevChgTsfnFlag()) {
1207         cb->CreateRouDevChgTsfn(env);
1208     }
1209 }
1210 
RegisterMicrophoneBlockedCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,NapiAudioRoutingManager * napiRoutingMgr)1211 void NapiAudioRoutingManager::RegisterMicrophoneBlockedCallback(napi_env env, size_t argc, napi_value *args,
1212     const std::string &cbName, NapiAudioRoutingManager *napiRoutingMgr)
1213 {
1214     napi_valuetype valueType = napi_undefined;
1215     napi_typeof(env, args[PARAM1], &valueType);
1216     if (valueType != napi_function) {
1217         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
1218             "parameter verification failed: The param of deviceFlag must be enum DeviceFlag");
1219     }
1220     if (!napiRoutingMgr->microphoneBlockedCallbackNapi_) {
1221         napiRoutingMgr->microphoneBlockedCallbackNapi_ = std::make_shared<NapiAudioManagerCallback>(env);
1222     }
1223     int32_t ret = napiRoutingMgr->audioMngr_->SetMicrophoneBlockedCallback(
1224         napiRoutingMgr->microphoneBlockedCallbackNapi_);
1225     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
1226         "Registering micro phone blocked Callback Failed %{public}d", ret);
1227     std::shared_ptr<NapiAudioManagerCallback> cb =
1228         std::static_pointer_cast<NapiAudioManagerCallback>(napiRoutingMgr->microphoneBlockedCallbackNapi_);
1229     cb->SaveMicrophoneBlockedCallbackReference(args[PARAM1]);
1230     if (!cb->GetMicBlockedTsfnFlag()) {
1231         cb->CreateMicBlockedTsfn(env);
1232     }
1233 }
1234 
On(napi_env env,napi_callback_info info)1235 napi_value NapiAudioRoutingManager::On(napi_env env, napi_callback_info info)
1236 {
1237     const size_t requireArgc = ARGS_TWO;
1238     const size_t maxArgc = ARGS_THREE;
1239     size_t argc = ARGS_THREE;
1240 
1241     napi_value undefinedResult = nullptr;
1242     napi_get_undefined(env, &undefinedResult);
1243 
1244     napi_value args[requireArgc + PARAM1] = { nullptr, nullptr, nullptr };
1245     napi_value jsThis = nullptr;
1246     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
1247     bool isArgcCountRight = argc == requireArgc || argc == maxArgc;
1248     CHECK_AND_RETURN_RET_LOG(status == napi_ok && isArgcCountRight, NapiAudioError::ThrowErrorAndReturn(env,
1249         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"),
1250         "status or isArgcCountRight error");
1251 
1252     napi_valuetype eventType = napi_undefined;
1253     napi_typeof(env, args[PARAM0], &eventType);
1254     CHECK_AND_RETURN_RET_LOG(eventType == napi_string, NapiAudioError::ThrowErrorAndReturn(env,
1255         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of eventType must be string"),
1256         "eventType is invalid");
1257     std::string callbackName = NapiParamUtils::GetStringArgument(env, args[PARAM0]);
1258     AUDIO_INFO_LOG("On callbackName: %{public}s", callbackName.c_str());
1259 
1260     if (argc == requireArgc) {
1261         napi_valuetype handler = napi_undefined;
1262         napi_typeof(env, args[PARAM1], &handler);
1263         CHECK_AND_RETURN_RET_LOG(handler == napi_function, NapiAudioError::ThrowErrorAndReturn(env,
1264             NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of callback must be function"),
1265             "handler is invalid");
1266     }
1267 
1268     return RegisterCallback(env, jsThis, argc, args, callbackName);
1269 }
1270 
UnregisterCallback(napi_env env,napi_value jsThis,const std::string & callbackName,napi_value callback)1271 napi_value NapiAudioRoutingManager::UnregisterCallback(napi_env env, napi_value jsThis,
1272     const std::string &callbackName, napi_value callback)
1273 {
1274     napi_value undefinedResult = nullptr;
1275     napi_get_undefined(env, &undefinedResult);
1276     NapiAudioRoutingManager *napiRoutingMgr = nullptr;
1277     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiRoutingMgr));
1278     CHECK_AND_RETURN_RET_LOG(status == napi_ok && napiRoutingMgr != nullptr, undefinedResult,
1279         "Failed to retrieve audio mgr napi instance.");
1280     CHECK_AND_RETURN_RET_LOG(napiRoutingMgr->audioMngr_ != nullptr, undefinedResult,
1281         "audio system mgr instance is null.");
1282     if (!callbackName.compare(DEVICE_CHANGE_CALLBACK_NAME)) {
1283         UnregisterDeviceChangeCallback(env, callback, napiRoutingMgr);
1284     } else if (!callbackName.compare(PREFERRED_OUTPUT_DEVICE_CALLBACK_NAME) ||
1285         !callbackName.compare(PREFER_OUTPUT_DEVICE_CALLBACK_NAME)) {
1286         UnregisterPreferredOutputDeviceChangeCallback(env, callback, napiRoutingMgr);
1287     } else if (!callbackName.compare(PREFERRED_INPUT_DEVICE_CALLBACK_NAME)) {
1288         UnregisterPreferredInputDeviceChangeCallback(env, callback, napiRoutingMgr);
1289     } else if (!callbackName.compare(AVAILABLE_DEVICE_CHANGE_CALLBACK_NAME)) {
1290         UnregisterAvailableDeviceChangeCallback(env, callback, napiRoutingMgr);
1291     } else if (!callbackName.compare(MICROPHONE_BLOCKED_CALLBACK_NAME)) {
1292         UnregisterMicrophoneBlockedCallback(env, callback, napiRoutingMgr);
1293     } else {
1294         AUDIO_ERR_LOG("off no such supported");
1295         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
1296             "parameter verification failed: The param of type is not supported");
1297     }
1298 
1299     return undefinedResult;
1300 }
1301 
UnregisterDeviceChangeCallback(napi_env env,napi_value callback,NapiAudioRoutingManager * napiRoutingMgr)1302 void NapiAudioRoutingManager::UnregisterDeviceChangeCallback(napi_env env, napi_value callback,
1303     NapiAudioRoutingManager *napiRoutingMgr)
1304 {
1305     if (napiRoutingMgr->deviceChangeCallbackNapi_ != nullptr) {
1306         std::shared_ptr<NapiAudioManagerCallback> cb =
1307             std::static_pointer_cast<NapiAudioManagerCallback>(
1308             napiRoutingMgr->deviceChangeCallbackNapi_);
1309         if (callback != nullptr) {
1310             cb->RemoveRoutingManagerDeviceChangeCbRef(env, callback);
1311         }
1312         if (callback == nullptr || cb->GetRoutingManagerDeviceChangeCbListSize() == 0) {
1313             int32_t ret = napiRoutingMgr->audioMngr_->UnsetDeviceChangeCallback(DeviceFlag::ALL_L_D_DEVICES_FLAG,
1314                 napiRoutingMgr->deviceChangeCallbackNapi_);
1315             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetDeviceChangeCallback Failed");
1316             napiRoutingMgr->deviceChangeCallbackNapi_.reset();
1317             napiRoutingMgr->deviceChangeCallbackNapi_ = nullptr;
1318 
1319             cb->RemoveAllRoutingManagerDeviceChangeCb();
1320         }
1321     } else {
1322         AUDIO_ERR_LOG("UnregisterDeviceChangeCallback: deviceChangeCallbackNapi_ is null");
1323     }
1324 }
1325 
RemovePreferredOutputDeviceChangeCallback(NapiAudioRoutingManager * napiRoutingMgr,std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb)1326 void NapiAudioRoutingManager::RemovePreferredOutputDeviceChangeCallback(NapiAudioRoutingManager *napiRoutingMgr,
1327     std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb)
1328 {
1329     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredOutputDeviceMutex_);
1330     napiRoutingMgr->preferredOutputDeviceCallbacks_.remove(cb);
1331 }
1332 
RemoveAllPrefOutputDeviceChangeCallback(napi_env env,NapiAudioRoutingManager * napiRoutingMgr)1333 void NapiAudioRoutingManager::RemoveAllPrefOutputDeviceChangeCallback(napi_env env,
1334     NapiAudioRoutingManager *napiRoutingMgr)
1335 {
1336     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredOutputDeviceMutex_);
1337     for (auto &iter : napiRoutingMgr->preferredOutputDeviceCallbacks_) {
1338         int32_t ret = napiRoutingMgr->audioRoutingMngr_->UnsetPreferredOutputDeviceChangeCallback(iter);
1339         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
1340             "Unset one of preferred output device change callback failed!");
1341     }
1342     napiRoutingMgr->preferredOutputDeviceCallbacks_.clear();
1343 }
1344 
UnregisterPreferredOutputDeviceChangeCallback(napi_env env,napi_value callback,NapiAudioRoutingManager * napiRoutingMgr)1345 void NapiAudioRoutingManager::UnregisterPreferredOutputDeviceChangeCallback(napi_env env, napi_value callback,
1346     NapiAudioRoutingManager *napiRoutingMgr)
1347 {
1348     if (callback != nullptr) {
1349         std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb =
1350             GetNapiPrefOutputDeviceChangeCb(callback, napiRoutingMgr);
1351         CHECK_AND_RETURN_LOG(cb != nullptr, "NapiPreferredOutputDeviceCallback is nullptr");
1352         int32_t ret = napiRoutingMgr->audioRoutingMngr_->UnsetPreferredOutputDeviceChangeCallback(cb);
1353         CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetPreferredOutputDeviceChangeCallback Failed");
1354 
1355         RemovePreferredOutputDeviceChangeCallback(napiRoutingMgr, cb);
1356         return;
1357     }
1358 
1359     RemoveAllPrefOutputDeviceChangeCallback(env, napiRoutingMgr);
1360 }
1361 
RemovePreferredInputDeviceChangeCallback(NapiAudioRoutingManager * napiRoutingMgr,std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb)1362 void NapiAudioRoutingManager::RemovePreferredInputDeviceChangeCallback(NapiAudioRoutingManager *napiRoutingMgr,
1363     std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb)
1364 {
1365     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredInputDeviceMutex_);
1366     napiRoutingMgr->preferredInputDeviceCallbacks_.remove(cb);
1367 }
1368 
RemoveAllPrefInputDeviceChangeCallback(napi_env env,NapiAudioRoutingManager * napiRoutingMgr)1369 void NapiAudioRoutingManager::RemoveAllPrefInputDeviceChangeCallback(napi_env env,
1370     NapiAudioRoutingManager *napiRoutingMgr)
1371 {
1372     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredInputDeviceMutex_);
1373     for (auto &iter : napiRoutingMgr->preferredInputDeviceCallbacks_) {
1374         int32_t ret = napiRoutingMgr->audioRoutingMngr_->UnsetPreferredInputDeviceChangeCallback(iter);
1375         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
1376             "Unset one of preferred input device change callback failed!");
1377     }
1378     napiRoutingMgr->preferredInputDeviceCallbacks_.clear();
1379 }
1380 
UnregisterPreferredInputDeviceChangeCallback(napi_env env,napi_value callback,NapiAudioRoutingManager * napiRoutingMgr)1381 void NapiAudioRoutingManager::UnregisterPreferredInputDeviceChangeCallback(napi_env env, napi_value callback,
1382     NapiAudioRoutingManager *napiRoutingMgr)
1383 {
1384     if (callback != nullptr) {
1385         std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb =
1386             GetNapiPrefInputDeviceChangeCb(callback, napiRoutingMgr);
1387         CHECK_AND_RETURN_LOG(cb != nullptr, "NapiPreferredInputDeviceCallback is nullptr");
1388         int32_t ret = napiRoutingMgr->audioRoutingMngr_->UnsetPreferredInputDeviceChangeCallback(cb);
1389         CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetPreferredInputDeviceChangeCallback Failed");
1390 
1391         RemovePreferredInputDeviceChangeCallback(napiRoutingMgr, cb);
1392         return;
1393     }
1394 
1395     RemoveAllPrefInputDeviceChangeCallback(env, napiRoutingMgr);
1396 }
1397 
UnregisterAvailableDeviceChangeCallback(napi_env env,napi_value callback,NapiAudioRoutingManager * napiRoutingMgr)1398 void NapiAudioRoutingManager::UnregisterAvailableDeviceChangeCallback(napi_env env, napi_value callback,
1399     NapiAudioRoutingManager *napiRoutingMgr)
1400 {
1401     if (napiRoutingMgr->availableDeviceChangeCallbackNapi_ != nullptr) {
1402         std::shared_ptr<NapiAudioRountingAvailableDeviceChangeCallback> cb =
1403             std::static_pointer_cast<NapiAudioRountingAvailableDeviceChangeCallback>(
1404             napiRoutingMgr->availableDeviceChangeCallbackNapi_);
1405         if (callback == nullptr || cb->GetRoutingAvailbleDeviceChangeCbListSize() == 0) {
1406             int32_t ret = napiRoutingMgr->audioMngr_->UnsetAvailableDeviceChangeCallback(D_ALL_DEVICES);
1407             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetAvailableDeviceChangeCallback Failed");
1408 
1409             napiRoutingMgr->availableDeviceChangeCallbackNapi_.reset();
1410             napiRoutingMgr->availableDeviceChangeCallbackNapi_ = nullptr;
1411             cb->RemoveAllRoutinAvailbleDeviceChangeCb();
1412             return;
1413         }
1414         cb->RemoveRoutingAvailbleDeviceChangeCbRef(env, callback);
1415     } else {
1416         AUDIO_ERR_LOG("UnregisterAvailableDeviceChangeCallback: availableDeviceChangeCallbackNapi_ is null");
1417     }
1418 }
1419 
UnregisterMicrophoneBlockedCallback(napi_env env,napi_value callback,NapiAudioRoutingManager * napiRoutingMgr)1420 void NapiAudioRoutingManager::UnregisterMicrophoneBlockedCallback(napi_env env, napi_value callback,
1421     NapiAudioRoutingManager *napiRoutingMgr)
1422 {
1423     if (napiRoutingMgr->microphoneBlockedCallbackNapi_ != nullptr) {
1424         std::shared_ptr<NapiAudioManagerCallback> cb =
1425             std::static_pointer_cast<NapiAudioManagerCallback>(
1426             napiRoutingMgr->microphoneBlockedCallbackNapi_);
1427         if (callback == nullptr || cb->GetMicrophoneBlockedCbListSize() == 0) {
1428             int32_t ret = napiRoutingMgr->audioMngr_->UnsetMicrophoneBlockedCallback(
1429                 napiRoutingMgr->microphoneBlockedCallbackNapi_);
1430             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetMicrophoneBlockedCallback Failed");
1431             napiRoutingMgr->microphoneBlockedCallbackNapi_.reset();
1432             napiRoutingMgr->microphoneBlockedCallbackNapi_ = nullptr;
1433             cb->RemoveAllMicrophoneBlockedCallback();
1434             return;
1435         }
1436         cb->RemoveMicrophoneBlockedCallbackReference(env, callback);
1437     } else {
1438         AUDIO_ERR_LOG("microphoneBlockedCallbackNapi_ is null");
1439     }
1440 }
1441 
Off(napi_env env,napi_callback_info info)1442 napi_value NapiAudioRoutingManager::Off(napi_env env, napi_callback_info info)
1443 {
1444     napi_value undefinedResult = nullptr;
1445     napi_get_undefined(env, &undefinedResult);
1446 
1447     const size_t minArgCount = ARGS_ONE;
1448     size_t argCount = ARGS_TWO;
1449     napi_value args[minArgCount + PARAM1] = {nullptr, nullptr};
1450     napi_value jsThis = nullptr;
1451     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
1452     if (status != napi_ok || argCount < minArgCount) {
1453         AUDIO_ERR_LOG("Off fail to napi_get_cb_info/Requires min 1 parameters");
1454         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1455             "mandatory parameters are left unspecified");
1456         return undefinedResult;
1457     }
1458 
1459     napi_valuetype eventType = napi_undefined;
1460     if (napi_typeof(env, args[PARAM0], &eventType) != napi_ok || eventType != napi_string) {
1461         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1462             "incorrect parameter types: The type of eventType must be string");
1463         return undefinedResult;
1464     }
1465 
1466     napi_valuetype secondArgsType = napi_undefined;
1467     if (argCount > minArgCount &&
1468         (napi_typeof(env, args[PARAM1], &secondArgsType) != napi_ok || secondArgsType != napi_function)) {
1469         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1470             "incorrect parameter types: The type of callback must be function");
1471         return undefinedResult;
1472     }
1473     std::string callbackName = NapiParamUtils::GetStringArgument(env, args[PARAM0]);
1474 
1475     if (argCount == minArgCount) {
1476         args[PARAM1] = nullptr;
1477     }
1478     AUDIO_INFO_LOG("Off callbackName: %{public}s", callbackName.c_str());
1479 
1480     return UnregisterCallback(env, jsThis, callbackName, args[PARAM1]);
1481 }
1482 
GetMicrophoneBlockedCbListSize()1483 int32_t NapiAudioManagerCallback::GetMicrophoneBlockedCbListSize()
1484 {
1485     std::lock_guard<std::mutex> lock(mutex_);
1486     return microphoneBlockedCbList_.size();
1487 }
1488 
1489 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
IsMicBlockDetectionSupported(napi_env env,napi_callback_info info)1490 napi_value NapiAudioRoutingManager::IsMicBlockDetectionSupported(napi_env env, napi_callback_info info)
1491 {
1492     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
1493     context->GetCbInfo(env, info);
1494     auto executor = [context]() {
1495         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
1496         context->supported = OHOS::system::GetBoolParameter("const.multimedia.audio.mic_block_detection", false);
1497         if (context->supported == true) {
1498         AUDIO_INFO_LOG("mic block detection supported");
1499         } else {
1500         AUDIO_ERR_LOG("mic block detection is not supported");
1501         }
1502     };
1503     auto complete = [env, context](napi_value &output) {
1504         NapiParamUtils::SetValueBoolean(env, context->supported, output);
1505     };
1506     return NapiAsyncWork::Enqueue(env, context, "IsMicBlockDetectionSupported", executor, complete);
1507 }
1508 #endif
1509 }  // namespace AudioStandard
1510 }  // namespace OHOS
1511