• 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,
395             "Invalid arguments. The number of parameters should be greater than 2.", 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,
398             "Parameter verification failed. AudioCapturerFilter abnormal.", 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 count.", 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 count.", 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 count.", NAPI_ERR_INVALID_PARAM);
520         context->status = NapiParamUtils::GetValueInt32(env, context->deviceType, argv[PARAM0]);
521         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "Invalid arguments type.",
522             NAPI_ERR_INVALID_PARAM);
523         if (!NapiAudioEnum::IsLegalInputArgumentCommunicationDeviceType(context->deviceType)) {
524             context->SignError(context->errCode == NAPI_ERR_INVALID_PARAM?
525                 NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED);
526         }
527         context->status = NapiParamUtils::GetValueBoolean(env, context->isActive, argv[PARAM1]);
528         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "Invalid arguments type.",
529             NAPI_ERR_INVALID_PARAM);
530     };
531     context->GetCbInfo(env, info, inputParser);
532 
533     auto executor = [context]() {
534         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
535         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
536         ObjectRefMap objectGuard(obj);
537         auto *napiAudioRoutingManager = objectGuard.GetPtr();
538         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
539             "context object state is error.");
540         context->intValue = napiAudioRoutingManager->audioMngr_->SetDeviceActive(
541             static_cast<DeviceType>(context->deviceType), context->isActive);
542         NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS, "SelectInputDevice failed",
543             NAPI_ERR_SYSTEM);
544     };
545 
546     auto complete = [env](napi_value &output) {
547         output = NapiParamUtils::GetUndefinedValue(env);
548     };
549     return NapiAsyncWork::Enqueue(env, context, "SetCommunicationDevice", executor, complete);
550 }
551 
IsCommunicationDeviceActive(napi_env env,napi_callback_info info)552 napi_value NapiAudioRoutingManager::IsCommunicationDeviceActive(napi_env env, napi_callback_info info)
553 {
554     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
555     if (context == nullptr) {
556         AUDIO_ERR_LOG("IsCommunicationDeviceActive failed : no memory");
557         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
558         return NapiParamUtils::GetUndefinedValue(env);
559     }
560 
561     auto inputParser = [env, context](size_t argc, napi_value *argv) {
562         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments",
563             NAPI_ERR_INVALID_PARAM);
564         context->status = NapiParamUtils::GetValueInt32(env, context->deviceType, argv[PARAM0]);
565         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "IsCommunicationDeviceActive failed",
566             NAPI_ERR_INVALID_PARAM);
567         if (!NapiAudioEnum::IsLegalInputArgumentActiveDeviceType(context->deviceType)) {
568             context->SignError(context->errCode == NAPI_ERR_INVALID_PARAM?
569                 NAPI_ERR_INVALID_PARAM: NAPI_ERR_UNSUPPORTED);
570         }
571     };
572     context->GetCbInfo(env, info, inputParser);
573 
574     auto executor = [context]() {
575         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
576         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
577         ObjectRefMap objectGuard(obj);
578         auto *napiAudioRoutingManager = objectGuard.GetPtr();
579         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
580             "context object state is error.");
581         context->isActive = napiAudioRoutingManager->audioMngr_->IsDeviceActive(
582             static_cast<DeviceType>(context->deviceType));
583         context->isTrue = context->isActive;
584     };
585 
586     auto complete = [env, context](napi_value &output) {
587         NapiParamUtils::SetValueBoolean(env, context->isTrue, output);
588     };
589     return NapiAsyncWork::Enqueue(env, context, "IsCommunicationDeviceActive", executor, complete);
590 }
591 
IsCommunicationDeviceActiveSync(napi_env env,napi_callback_info info)592 napi_value NapiAudioRoutingManager::IsCommunicationDeviceActiveSync(napi_env env, napi_callback_info info)
593 {
594     napi_value result = nullptr;
595     size_t argc = ARGS_ONE;
596     napi_value argv[ARGS_ONE] = {};
597     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
598     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env,
599         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argCount invalid");
600 
601     napi_valuetype valueType = napi_undefined;
602     napi_typeof(env, argv[PARAM0], &valueType);
603     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env,
604         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of deviceType must be number"),
605         "valueType invalid");
606 
607     int32_t deviceType;
608     napi_status status = NapiParamUtils::GetValueInt32(env, deviceType, argv[PARAM0]);
609     CHECK_AND_RETURN_RET_LOG(NapiAudioEnum::IsLegalInputArgumentActiveDeviceType(deviceType) && status == napi_ok,
610         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
611         "parameter verification failed: The param of deviceType must be enum CommunicationDeviceType"),
612         "valueType invalid");
613 
614     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
615     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioMngr_ != nullptr, result, "audioMngr_ nullptr");
616     bool isActive = napiAudioRoutingManager->audioMngr_->IsDeviceActive(static_cast<DeviceType>(deviceType));
617 
618     NapiParamUtils::SetValueBoolean(env, isActive, result);
619     return result;
620 }
621 
GetActiveOutputDeviceDescriptors(napi_env env,napi_callback_info info)622 napi_value NapiAudioRoutingManager::GetActiveOutputDeviceDescriptors(napi_env env, napi_callback_info info)
623 {
624     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
625     if (context == nullptr) {
626         AUDIO_ERR_LOG("GetActiveOutputDeviceDescriptors failed : no memory");
627         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
628         return NapiParamUtils::GetUndefinedValue(env);
629     }
630 
631     context->GetCbInfo(env, info);
632 
633     auto executor = [context]() {
634         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
635         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
636         ObjectRefMap objectGuard(obj);
637         auto *napiAudioRoutingManager = objectGuard.GetPtr();
638         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
639             "context object state is error.");
640         context->outDeviceDescriptors = napiAudioRoutingManager->audioMngr_->GetActiveOutputDeviceDescriptors();
641     };
642 
643     auto complete = [env, context](napi_value &output) {
644         NapiParamUtils::SetDeviceDescriptors(env, context->outDeviceDescriptors, output);
645     };
646     return NapiAsyncWork::Enqueue(env, context, "GetActiveOutputDeviceDescriptors", executor, complete);
647 }
648 
GetPreferredOutputDeviceForRendererInfo(napi_env env,napi_callback_info info)649 napi_value NapiAudioRoutingManager::GetPreferredOutputDeviceForRendererInfo(napi_env env, napi_callback_info info)
650 {
651     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
652     if (context == nullptr) {
653         AUDIO_ERR_LOG("GetPreferredOutputDeviceForRendererInfo failed : no memory");
654         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
655         return NapiParamUtils::GetUndefinedValue(env);
656     }
657 
658     auto inputParser = [env, context](size_t argc, napi_value *argv) {
659         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "mandatory parameters are left unspecified",
660             NAPI_ERR_INPUT_INVALID);
661         context->status = NapiParamUtils::GetRendererInfo(env, &(context->rendererInfo), argv[PARAM0]);
662         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
663             "incorrect parameter types: The type of rendererInfo must be interface AudioRendererInfo",
664             NAPI_ERR_INPUT_INVALID);
665     };
666     context->GetCbInfo(env, info, inputParser);
667     if (context->status != napi_ok) {
668         NapiAudioError::ThrowError(env, context->errCode, context->errMessage);
669         return NapiParamUtils::GetUndefinedValue(env);
670     }
671 
672     auto executor = [context]() {
673         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
674         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
675         ObjectRefMap objectGuard(obj);
676         auto *napiAudioRoutingManager = objectGuard.GetPtr();
677         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
678             "context object state is error.");
679         if (context->rendererInfo.streamUsage == StreamUsage::STREAM_USAGE_INVALID) {
680             context->SignError(NAPI_ERR_INVALID_PARAM,
681                 "Parameter verification failed. Your usage in AudioRendererInfo is invalid.");
682         } else {
683             context->intValue = napiAudioRoutingManager->audioRoutingMngr_->GetPreferredOutputDeviceForRendererInfo(
684                 context->rendererInfo, context->outDeviceDescriptors);
685             NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS,
686                 "GetPreferredOutputDeviceForRendererInfo failed", NAPI_ERR_SYSTEM);
687         }
688     };
689 
690     auto complete = [env, context](napi_value &output) {
691         NapiParamUtils::SetDeviceDescriptors(env, context->outDeviceDescriptors, output);
692     };
693     return NapiAsyncWork::Enqueue(env, context, "GetPreferredOutputDeviceForRendererInfo", executor, complete);
694 }
695 
GetPreferOutputDeviceForRendererInfo(napi_env env,napi_callback_info info)696 napi_value NapiAudioRoutingManager::GetPreferOutputDeviceForRendererInfo(napi_env env, napi_callback_info info)
697 {
698     // for api compatibility, leave some time for applications to adapt to new one
699     return GetPreferredOutputDeviceForRendererInfo(env, info);
700 }
701 
GetPreferredOutputDeviceForRendererInfoSync(napi_env env,napi_callback_info info)702 napi_value NapiAudioRoutingManager::GetPreferredOutputDeviceForRendererInfoSync(napi_env env, napi_callback_info info)
703 {
704     AUDIO_INFO_LOG("GetPreferredOutputDeviceForRendererInfoSync");
705     napi_value result = nullptr;
706     size_t argc = ARGS_ONE;
707     napi_value argv[ARGS_ONE] = {};
708     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
709     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env,
710         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argCount invalid");
711 
712     napi_valuetype valueType = napi_undefined;
713     napi_typeof(env, argv[PARAM0], &valueType);
714     CHECK_AND_RETURN_RET_LOG(valueType == napi_object, NapiAudioError::ThrowErrorAndReturn(env,
715         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of rendererInfo must be object"),
716         "valueType invalid");
717 
718     AudioRendererInfo rendererInfo;
719     if (NapiParamUtils::GetRendererInfo(env, &rendererInfo, argv[PARAM0]) != napi_ok) {
720         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
721             "incorrect parameter types: The type of rendererInfo must be interface AudioRendererInfo");
722         return result;
723     } else if (rendererInfo.streamUsage == StreamUsage::STREAM_USAGE_INVALID) {
724         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
725             "Parameter verification failed. Your usage in AudioRendererInfo is invalid.");
726         return result;
727     }
728 
729     vector<std::shared_ptr<AudioDeviceDescriptor>> outDeviceDescriptors;
730     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
731     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioRoutingMngr_ != nullptr, result,
732         "audioRoutingMngr_ nullptr");
733     napiAudioRoutingManager->audioRoutingMngr_->GetPreferredOutputDeviceForRendererInfo(
734         rendererInfo, outDeviceDescriptors);
735 
736     NapiParamUtils::SetDeviceDescriptors(env, outDeviceDescriptors, result);
737 
738     return result;
739 }
740 
741 
GetPreferredOutputDeviceByFilter(napi_env env,napi_callback_info info)742 napi_value NapiAudioRoutingManager::GetPreferredOutputDeviceByFilter(napi_env env, napi_callback_info info)
743 {
744     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
745     if (context == nullptr) {
746         AUDIO_ERR_LOG("GetPreferredOutputDeviceByFilter failed : no memory");
747         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
748         return NapiParamUtils::GetUndefinedValue(env);
749     }
750 
751     auto inputParser = [env, context](size_t argc, napi_value *argv) {
752         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "Invalid arguments count.", NAPI_ERR_INVALID_PARAM);
753         context->status = NapiParamUtils::GetAudioRendererFilter(env, context->audioRendererFilter,
754             context->bArgTransFlag, argv[PARAM0]);
755         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
756             "Parameter verification failed. Your usage in AudioRendererFilter is invalid.", NAPI_ERR_INVALID_PARAM);
757     };
758     context->GetCbInfo(env, info, inputParser);
759 
760     auto executor = [context]() {
761         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
762         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
763         ObjectRefMap objectGuard(obj);
764         auto *napiAudioRoutingManager = objectGuard.GetPtr();
765         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
766             "context object state is error.");
767         context->deviceDescriptors = napiAudioRoutingManager->audioMngr_->GetOutputDevice(context->audioRendererFilter);
768     };
769     auto complete = [env, context](napi_value &output) {
770         NapiParamUtils::SetDeviceDescriptors(env, context->deviceDescriptors, output);
771     };
772     return NapiAsyncWork::Enqueue(env, context, "GetPreferredOutputDeviceByFilter", executor, complete);
773 }
774 
GetPreferredInputDeviceForCapturerInfo(napi_env env,napi_callback_info info)775 napi_value NapiAudioRoutingManager::GetPreferredInputDeviceForCapturerInfo(napi_env env, napi_callback_info info)
776 {
777     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
778     if (context == nullptr) {
779         AUDIO_ERR_LOG("GetPreferredInputDeviceForCapturerInfo failed : no memory");
780         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
781         return NapiParamUtils::GetUndefinedValue(env);
782     }
783 
784     auto inputParser = [env, context](size_t argc, napi_value *argv) {
785         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "mandatory parameters are left unspecified",
786             NAPI_ERR_INPUT_INVALID);
787         context->status = NapiParamUtils::GetAudioCapturerInfo(env, &context->captureInfo, argv[PARAM0]);
788         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
789             "incorrect parameter types: The type of capturerInfo must be interface AudioCapturerInfo",
790             NAPI_ERR_INPUT_INVALID);
791     };
792     context->GetCbInfo(env, info, inputParser);
793 
794     if (context->status != napi_ok) {
795         NapiAudioError::ThrowError(env, context->errCode, context->errMessage);
796         return NapiParamUtils::GetUndefinedValue(env);
797     }
798 
799     auto executor = [context]() {
800         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
801         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
802         ObjectRefMap objectGuard(obj);
803         auto *napiAudioRoutingManager = objectGuard.GetPtr();
804         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
805             "context object state is error.");
806         if (context->captureInfo.sourceType == SourceType::SOURCE_TYPE_INVALID) {
807             context->SignError(NAPI_ERR_INVALID_PARAM,
808                 "Parameter verification failed. You source in AudioCapturerInfo is invalid.");
809         } else {
810             context->intValue = napiAudioRoutingManager->audioRoutingMngr_->GetPreferredInputDeviceForCapturerInfo(
811                 context->captureInfo, context->inputDeviceDescriptors);
812             NAPI_CHECK_ARGS_RETURN_VOID(context, context->intValue == SUCCESS,
813                 "GetPreferredInputDeviceForCapturerInfo failed", NAPI_ERR_SYSTEM);
814         }
815     };
816 
817     auto complete = [env, context](napi_value &output) {
818         NapiParamUtils::SetDeviceDescriptors(env, context->inputDeviceDescriptors, output);
819     };
820     return NapiAsyncWork::Enqueue(env, context, "GetPreferredInputDeviceForCapturerInfo", executor, complete);
821 }
822 
GetPreferredInputDeviceForCapturerInfoSync(napi_env env,napi_callback_info info)823 napi_value NapiAudioRoutingManager::GetPreferredInputDeviceForCapturerInfoSync(napi_env env, napi_callback_info info)
824 {
825     napi_value result = nullptr;
826     size_t argc = ARGS_ONE;
827     napi_value argv[ARGS_ONE] = {};
828     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
829     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env,
830         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argCount invalid");
831 
832     napi_valuetype valueType = napi_undefined;
833     napi_typeof(env, argv[PARAM0], &valueType);
834     CHECK_AND_RETURN_RET_LOG(valueType == napi_object,
835         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
836         "incorrect parameter types: The type of capturerInfo must be object"), "valueType invalid");
837 
838     AudioCapturerInfo capturerInfo;
839     napi_status status = NapiParamUtils::GetAudioCapturerInfo(env, &capturerInfo, argv[PARAM0]);
840     CHECK_AND_RETURN_RET_LOG((capturerInfo.sourceType != SourceType::SOURCE_TYPE_INVALID) && (status == napi_ok),
841         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
842         "Parameter verification failed. AudioCapturerInfo abnormal."), "sourceType invalid");
843 
844     vector<std::shared_ptr<AudioDeviceDescriptor>> outDeviceDescriptors;
845     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
846     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioRoutingMngr_ != nullptr, result,
847         "audioRoutingMngr_ nullptr");
848     napiAudioRoutingManager->audioRoutingMngr_->GetPreferredInputDeviceForCapturerInfo(
849         capturerInfo, outDeviceDescriptors);
850 
851     NapiParamUtils::SetDeviceDescriptors(env, outDeviceDescriptors, result);
852 
853     return result;
854 }
855 
GetPreferredInputDeviceByFilter(napi_env env,napi_callback_info info)856 napi_value NapiAudioRoutingManager::GetPreferredInputDeviceByFilter(napi_env env, napi_callback_info info)
857 {
858     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
859     if (context == nullptr) {
860         AUDIO_ERR_LOG("GetPreferredInputDeviceByFilter failed : no memory");
861         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY);
862         return NapiParamUtils::GetUndefinedValue(env);
863     }
864 
865     auto inputParser = [env, context](size_t argc, napi_value *argv) {
866         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "Invalid arguments count.", NAPI_ERR_INVALID_PARAM);
867         context->status = NapiParamUtils::GetAudioCapturerFilter(env, context->audioCapturerFilter, argv[PARAM0]);
868         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
869             "Parameter verification failed. AudioCapturerFilter abnormal.", NAPI_ERR_INVALID_PARAM);
870     };
871     context->GetCbInfo(env, info, inputParser);
872 
873     auto executor = [context]() {
874         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
875         auto obj = reinterpret_cast<NapiAudioRoutingManager*>(context->native);
876         ObjectRefMap objectGuard(obj);
877         auto *napiAudioRoutingManager = objectGuard.GetPtr();
878         CHECK_AND_RETURN_LOG(CheckAudioRoutingManagerStatus(napiAudioRoutingManager, context),
879             "context object state is error.");
880         context->deviceDescriptors = napiAudioRoutingManager->audioMngr_->GetInputDevice(context->audioCapturerFilter);
881     };
882     auto complete = [env, context](napi_value &output) {
883         NapiParamUtils::SetDeviceDescriptors(env, context->deviceDescriptors, output);
884     };
885     return NapiAsyncWork::Enqueue(env, context, "GetPreferredInputDeviceByFilter", executor, complete);
886 }
887 
GetAvailableMicrophones(napi_env env,napi_callback_info info)888 napi_value NapiAudioRoutingManager::GetAvailableMicrophones(napi_env env, napi_callback_info info)
889 {
890     AUDIO_INFO_LOG("GetAvailableMicrophones");
891     napi_value result = nullptr;
892     size_t argc = PARAM0;
893     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, nullptr);
894     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env,
895         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argCount invalid");
896     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
897     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioRoutingMngr_ != nullptr, result,
898         "audioRoutingMngr_ is nullptr");
899 
900     vector<sptr<MicrophoneDescriptor>> micDescs =
901         napiAudioRoutingManager->audioRoutingMngr_->GetAvailableMicrophones();
902 
903     NapiParamUtils::SetMicrophoneDescriptors(env, micDescs, result);
904 
905     return result;
906 }
907 
GetAvailableDevices(napi_env env,napi_callback_info info)908 napi_value NapiAudioRoutingManager::GetAvailableDevices(napi_env env, napi_callback_info info)
909 {
910     napi_value result = nullptr;
911     size_t argc = ARGS_ONE;
912     napi_value argv[ARGS_ONE] = {};
913     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
914     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env,
915         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"), "argcCount invalid");
916 
917     napi_valuetype valueType = napi_undefined;
918     napi_status status = napi_typeof(env, argv[PARAM0], &valueType);
919     CHECK_AND_RETURN_RET_LOG(status == napi_ok && valueType == napi_number, NapiAudioError::ThrowErrorAndReturn(env,
920         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of deviceUsage must be number"),
921         "valueType invalid");
922 
923     int32_t intValue = 0;
924     status = napi_get_value_int32(env, argv[PARAM0], &intValue);
925     CHECK_AND_RETURN_RET_LOG(status == napi_ok && NapiAudioEnum::IsLegalDeviceUsage(intValue),
926         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
927         "parameter verification failed: The param of deviceUsage must be enum DeviceUsage"), "invalid deviceusage");
928 
929     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
930     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioRoutingMngr_ != nullptr, result,
931         "audioRoutingMngr_ is nullptr");
932     AudioDeviceUsage usage = static_cast<AudioDeviceUsage>(intValue);
933 
934     vector<std::shared_ptr<AudioDeviceDescriptor>> availableDescs =
935         napiAudioRoutingManager->audioRoutingMngr_->GetAvailableDevices(usage);
936 
937     vector<std::shared_ptr<AudioDeviceDescriptor>> availableSptrDescs;
938     for (const auto &availableDesc : availableDescs) {
939         std::shared_ptr<AudioDeviceDescriptor> dec = std::make_shared<AudioDeviceDescriptor>(*availableDesc);
940         CHECK_AND_BREAK_LOG(dec != nullptr, "dec mallac failed,no memery.");
941         availableSptrDescs.push_back(dec);
942     }
943     NapiParamUtils::SetDeviceDescriptors(env, availableSptrDescs, result);
944     return result;
945 }
946 
GetExcludedDevices(napi_env env,napi_callback_info info)947 napi_value NapiAudioRoutingManager::GetExcludedDevices(napi_env env, napi_callback_info info)
948 {
949     napi_value result = nullptr;
950     size_t argc = ARGS_ONE;
951     napi_value argv[ARGS_ONE] = {};
952     auto *napiAudioRoutingManager = GetParamWithSync(env, info, argc, argv);
953     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager != nullptr, result, "napiAudioRoutingManager is nullptr");
954     CHECK_AND_RETURN_RET_LOG(napiAudioRoutingManager->audioMngr_ != nullptr, result,
955         "audioMngr_ is nullptr");
956     CHECK_AND_RETURN_RET_LOG(argc == ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
957         "mandatory parameters are left unspecified"), "argCount invalid");
958 
959     AudioDeviceUsage audioDevUsage;
960     napi_status status = NapiParamUtils::GetAudioDeviceUsage(env, audioDevUsage, argv[PARAM0]);
961     CHECK_AND_RETURN_RET_LOG(status == napi_ok, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
962         "parameter verification failed: The param of deviceUsage must be enum DeviceUsage"),
963         "exclude output devices failed");
964     vector<shared_ptr<AudioDeviceDescriptor>> excludedDevices =
965         napiAudioRoutingManager->audioMngr_->GetExcludedDevices(audioDevUsage);
966     NapiParamUtils::SetDeviceDescriptors(env, excludedDevices, result);
967     return result;
968 }
969 
RegisterCallback(napi_env env,napi_value jsThis,size_t argc,napi_value * args,const std::string & cbName)970 napi_value NapiAudioRoutingManager::RegisterCallback(napi_env env, napi_value jsThis, size_t argc,
971     napi_value *args, const std::string &cbName)
972 {
973     napi_value undefinedResult = nullptr;
974     NapiAudioRoutingManager *napiRoutingMgr = nullptr;
975     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void**>(&napiRoutingMgr));
976     if ((status != napi_ok) || (napiRoutingMgr == nullptr) || (napiRoutingMgr->audioMngr_ == nullptr) ||
977         (napiRoutingMgr->audioRoutingMngr_ == nullptr)) {
978         AUDIO_ERR_LOG("NapiAudioRoutingManager::Failed to retrieve stream mgr napi instance.");
979         return undefinedResult;
980     }
981 
982     if (!cbName.compare(DEVICE_CHANGE_CALLBACK_NAME)) {
983         RegisterDeviceChangeCallback(env, argc, args, cbName, napiRoutingMgr);
984     } else if (!cbName.compare(PREFERRED_OUTPUT_DEVICE_CALLBACK_NAME) ||
985         !cbName.compare(PREFER_OUTPUT_DEVICE_CALLBACK_NAME)) {
986         RegisterPreferredOutputDeviceChangeCallback(env, argc, args, cbName, napiRoutingMgr);
987     } else if (!cbName.compare(PREFERRED_INPUT_DEVICE_CALLBACK_NAME)) {
988         RegisterPreferredInputDeviceChangeCallback(env, argc, args, cbName, napiRoutingMgr);
989     } else if (!cbName.compare(AVAILABLE_DEVICE_CHANGE_CALLBACK_NAME)) {
990         RegisterAvaiableDeviceChangeCallback(env, argc, args, cbName, napiRoutingMgr);
991     } else if (!cbName.compare(MICROPHONE_BLOCKED_CALLBACK_NAME)) {
992         RegisterMicrophoneBlockedCallback(env, argc, args, cbName, napiRoutingMgr);
993     } else {
994         AUDIO_ERR_LOG("NapiAudioRoutingManager::No such supported");
995         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
996             "parameter verification failed: The param of type is not supported");
997     }
998     return undefinedResult;
999 }
1000 
RegisterDeviceChangeCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,NapiAudioRoutingManager * napiRoutingMgr)1001 void NapiAudioRoutingManager::RegisterDeviceChangeCallback(napi_env env, size_t argc, napi_value *args,
1002     const std::string &cbName, NapiAudioRoutingManager *napiRoutingMgr)
1003 {
1004     int32_t flag = ARGS_THREE;
1005     napi_valuetype valueType = napi_undefined;
1006     napi_typeof(env, args[PARAM1], &valueType);
1007     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowError(env,
1008         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of deviceFlag must be number"),
1009         "invalid valueType");
1010     if (valueType == napi_number) {
1011         NapiParamUtils::GetValueInt32(env, flag, args[PARAM1]);
1012         AUDIO_INFO_LOG("RegisterDeviceChangeCallback:On deviceFlag: %{public}d", flag);
1013         if (!NapiAudioEnum::IsLegalInputArgumentDeviceFlag(flag)) {
1014             NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
1015                 "parameter verification failed: The param of deviceFlag must be enum DeviceFlag");
1016         }
1017     }
1018 
1019     napi_valuetype handler = napi_undefined;
1020     napi_typeof(env, args[PARAM2], &handler);
1021 
1022     if (handler != napi_function) {
1023         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1024             "incorrect parameter types: The type of callback must be function");
1025     }
1026     DeviceFlag deviceFlag = DeviceFlag(flag);
1027     if (!napiRoutingMgr->deviceChangeCallbackNapi_) {
1028         napiRoutingMgr->deviceChangeCallbackNapi_ = std::make_shared<NapiAudioManagerCallback>(env);
1029     }
1030     CHECK_AND_RETURN_LOG(napiRoutingMgr->deviceChangeCallbackNapi_,
1031         "RegisterDeviceChangeCallback: Memory Allocation Failed !");
1032 
1033     int32_t ret = napiRoutingMgr->audioMngr_->SetDeviceChangeCallback(deviceFlag,
1034         napiRoutingMgr->deviceChangeCallbackNapi_);
1035     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
1036         "RegisterDeviceChangeCallback: Registering Device Change Callback Failed %{public}d", ret);
1037 
1038     std::shared_ptr<NapiAudioManagerCallback> cb =
1039         std::static_pointer_cast<NapiAudioManagerCallback>(napiRoutingMgr->deviceChangeCallbackNapi_);
1040     cb->SaveRoutingManagerDeviceChangeCbRef(deviceFlag, args[PARAM2]);
1041     if (!cb->GetDevChgTsfnFlag()) {
1042         cb->CreateDevChgTsfn(env);
1043     }
1044 }
1045 
GetNapiPrefOutputDeviceChangeCb(napi_value args,NapiAudioRoutingManager * napiRoutingMgr)1046 std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> NapiAudioRoutingManager::GetNapiPrefOutputDeviceChangeCb(
1047     napi_value args, NapiAudioRoutingManager *napiRoutingMgr)
1048 {
1049     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredOutputDeviceMutex_);
1050     std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb = nullptr;
1051     for (auto &iter : napiRoutingMgr->preferredOutputDeviceCallbacks_) {
1052         if (iter->ContainSameJsCallback(args)) {
1053             cb = iter;
1054         }
1055     }
1056     return cb;
1057 }
1058 
AddPreferredOutputDeviceChangeCallback(NapiAudioRoutingManager * napiRoutingMgr,std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb)1059 void NapiAudioRoutingManager::AddPreferredOutputDeviceChangeCallback(NapiAudioRoutingManager *napiRoutingMgr,
1060     std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb)
1061 {
1062     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredOutputDeviceMutex_);
1063     napiRoutingMgr->preferredOutputDeviceCallbacks_.push_back(cb);
1064 }
1065 
RegisterPreferredOutputDeviceChangeCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,NapiAudioRoutingManager * napiRoutingMgr)1066 void NapiAudioRoutingManager::RegisterPreferredOutputDeviceChangeCallback(napi_env env, size_t argc, napi_value *args,
1067     const std::string &cbName, NapiAudioRoutingManager *napiRoutingMgr)
1068 {
1069     CHECK_AND_RETURN_RET_LOG(argc == ARGS_THREE, NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1070         "incorrect number of parameters: expected at least 3 parameters"), "argc invalid");
1071 
1072     CHECK_AND_RETURN_RET_LOG(NapiParamUtils::CheckArgType(env, args[PARAM1], napi_object),
1073         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1074         "incorrect parameter types: The type of rendererInfo must be object"), "rendererInfo invalid");
1075 
1076     CHECK_AND_RETURN_RET_LOG(NapiParamUtils::CheckArgType(env, args[PARAM2], napi_function),
1077         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1078         "incorrect parameter types: The type of callback must be function"), "callback invalid");
1079 
1080     CHECK_AND_RETURN_LOG(GetNapiPrefOutputDeviceChangeCb(args[PARAM2], napiRoutingMgr) == nullptr,
1081         "Do not allow duplicate registration of the same callback");
1082 
1083     AudioRendererInfo rendererInfo;
1084     NapiParamUtils::GetRendererInfo(env, &rendererInfo, args[PARAM1]);
1085     CHECK_AND_RETURN_RET_LOG(rendererInfo.streamUsage != StreamUsage::STREAM_USAGE_INVALID,
1086         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
1087         "Parameter verification failed. Your usage in AudioRendererInfo is invalid."), "invalid streamUsage");
1088     std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb =
1089         std::make_shared<NapiAudioPreferredOutputDeviceChangeCallback>(env);
1090     CHECK_AND_RETURN_LOG(cb != nullptr, "Memory allocation failed!!");
1091 
1092     cb->SaveCallbackReference(args[PARAM2]);
1093     cb->CreatePreferredOutTsfn(env);
1094 
1095     int32_t ret = napiRoutingMgr->audioRoutingMngr_->SetPreferredOutputDeviceChangeCallback(
1096         rendererInfo, cb);
1097     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
1098         "Registering Preferred Output Device Change Callback Failed %{public}d", ret);
1099 
1100     AddPreferredOutputDeviceChangeCallback(napiRoutingMgr, cb);
1101 }
1102 
GetNapiPrefInputDeviceChangeCb(napi_value args,NapiAudioRoutingManager * napiRoutingMgr)1103 std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> NapiAudioRoutingManager::GetNapiPrefInputDeviceChangeCb(
1104     napi_value args, NapiAudioRoutingManager *napiRoutingMgr)
1105 {
1106     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredInputDeviceMutex_);
1107     std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb = nullptr;
1108     for (auto &iter : napiRoutingMgr->preferredInputDeviceCallbacks_) {
1109         if (iter->ContainSameJsCallback(args)) {
1110             cb = iter;
1111         }
1112     }
1113     return cb;
1114 }
1115 
AddPreferredInputDeviceChangeCallback(NapiAudioRoutingManager * napiRoutingMgr,std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb)1116 void NapiAudioRoutingManager::AddPreferredInputDeviceChangeCallback(NapiAudioRoutingManager *napiRoutingMgr,
1117     std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb)
1118 {
1119     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredInputDeviceMutex_);
1120     napiRoutingMgr->preferredInputDeviceCallbacks_.push_back(cb);
1121 }
1122 
RegisterPreferredInputDeviceChangeCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,NapiAudioRoutingManager * napiRoutingMgr)1123 void NapiAudioRoutingManager::RegisterPreferredInputDeviceChangeCallback(napi_env env, size_t argc, napi_value *args,
1124     const std::string &cbName, NapiAudioRoutingManager *napiRoutingMgr)
1125 {
1126     CHECK_AND_RETURN_RET_LOG(argc >= ARGS_THREE, NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1127         "mandatory parameters are left unspecified"), "argCount invalid");
1128 
1129     CHECK_AND_RETURN_RET_LOG(NapiParamUtils::CheckArgType(env, args[PARAM1], napi_object),
1130         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1131         "incorrect parameter types: The type of capturerInfo must be object"), "capturerInfo invalid");
1132 
1133     CHECK_AND_RETURN_RET_LOG(NapiParamUtils::CheckArgType(env, args[PARAM2], napi_function),
1134         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1135         "incorrect parameter types: The type of callback must be function"), "callback invalid");
1136 
1137     CHECK_AND_RETURN_LOG(GetNapiPrefInputDeviceChangeCb(args[PARAM2], napiRoutingMgr) == nullptr,
1138         "Do not allow duplicate registration of the same callback");
1139 
1140     AudioCapturerInfo captureInfo;
1141     NapiParamUtils::GetAudioCapturerInfo(env, &captureInfo, args[PARAM1]);
1142 
1143     CHECK_AND_RETURN_RET_LOG(captureInfo.sourceType != SourceType::SOURCE_TYPE_INVALID,
1144         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
1145         "Parameter verification failed. Your source in AudioCapturerInfo is invalid."), "invalid sourceType");
1146 
1147     std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb =
1148         std::make_shared<NapiAudioPreferredInputDeviceChangeCallback>(env);
1149     CHECK_AND_RETURN_LOG(cb != nullptr, "Memory allocation failed!!");
1150 
1151     cb->SaveCallbackReference(args[PARAM2]);
1152     cb->CreatePreferredInTsfn(env);
1153 
1154     int32_t ret = napiRoutingMgr->audioRoutingMngr_->SetPreferredInputDeviceChangeCallback(
1155         captureInfo, cb);
1156     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
1157         "Registering Preferred Input Device Change Callback Failed %{public}d", ret);
1158 
1159     AddPreferredInputDeviceChangeCallback(napiRoutingMgr, cb);
1160 }
1161 
RegisterAvaiableDeviceChangeCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,NapiAudioRoutingManager * napiRoutingMgr)1162 void NapiAudioRoutingManager::RegisterAvaiableDeviceChangeCallback(napi_env env, size_t argc, napi_value *args,
1163     const std::string &cbName, NapiAudioRoutingManager *napiRoutingMgr)
1164 {
1165     int32_t flag = 0;
1166     napi_valuetype valueType = napi_undefined;
1167     napi_typeof(env, args[PARAM1], &valueType);
1168     CHECK_AND_RETURN_RET_LOG(valueType == napi_number, NapiAudioError::ThrowError(env,
1169         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of deviceUsage must be number"),
1170         "invalid Type");
1171 
1172     NapiParamUtils::GetValueInt32(env, flag, args[PARAM1]);
1173     AUDIO_INFO_LOG("RegisterDeviceChangeCallback:On deviceFlag: %{public}d", flag);
1174     if (!NapiAudioEnum::IsLegalDeviceUsage(flag)) {
1175         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
1176             "parameter verification failed: The param of deviceUsage must be enum DeviceUsage");
1177     }
1178 
1179     napi_valuetype handler = napi_undefined;
1180     napi_typeof(env, args[PARAM2], &handler);
1181     if (handler != napi_function) {
1182         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1183             "incorrect parameter types: The type of callback must be function");
1184     }
1185     AudioDeviceUsage usage = static_cast<AudioDeviceUsage>(flag);
1186     if (!napiRoutingMgr->availableDeviceChangeCallbackNapi_) {
1187         napiRoutingMgr->availableDeviceChangeCallbackNapi_ =
1188             std::make_shared<NapiAudioRountingAvailableDeviceChangeCallback>(env);
1189     }
1190     CHECK_AND_RETURN_LOG(napiRoutingMgr->availableDeviceChangeCallbackNapi_ != nullptr,
1191         "RegisterDeviceChangeCallback: Memory Allocation Failed !");
1192 
1193     int32_t ret = napiRoutingMgr->audioMngr_->SetAvailableDeviceChangeCallback(usage,
1194         napiRoutingMgr->availableDeviceChangeCallbackNapi_);
1195     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
1196         "RegisterDeviceChangeCallback: Registering Device Change Callback Failed %{public}d", ret);
1197 
1198     std::shared_ptr<NapiAudioRountingAvailableDeviceChangeCallback> cb =
1199         std::static_pointer_cast<NapiAudioRountingAvailableDeviceChangeCallback>(
1200         napiRoutingMgr->availableDeviceChangeCallbackNapi_);
1201     cb->SaveRoutingAvailbleDeviceChangeCbRef(usage, args[PARAM2]);
1202     if (!cb->GetRouDevChgTsfnFlag()) {
1203         cb->CreateRouDevChgTsfn(env);
1204     }
1205 }
1206 
RegisterMicrophoneBlockedCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,NapiAudioRoutingManager * napiRoutingMgr)1207 void NapiAudioRoutingManager::RegisterMicrophoneBlockedCallback(napi_env env, size_t argc, napi_value *args,
1208     const std::string &cbName, NapiAudioRoutingManager *napiRoutingMgr)
1209 {
1210     napi_valuetype valueType = napi_undefined;
1211     napi_typeof(env, args[PARAM1], &valueType);
1212     if (valueType != napi_function) {
1213         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
1214             "parameter verification failed: The param of deviceFlag must be enum DeviceFlag");
1215     }
1216     if (!napiRoutingMgr->microphoneBlockedCallbackNapi_) {
1217         napiRoutingMgr->microphoneBlockedCallbackNapi_ = std::make_shared<NapiAudioManagerCallback>(env);
1218     }
1219     int32_t ret = napiRoutingMgr->audioMngr_->SetMicrophoneBlockedCallback(
1220         napiRoutingMgr->microphoneBlockedCallbackNapi_);
1221     CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
1222         "Registering micro phone blocked Callback Failed %{public}d", ret);
1223     std::shared_ptr<NapiAudioManagerCallback> cb =
1224         std::static_pointer_cast<NapiAudioManagerCallback>(napiRoutingMgr->microphoneBlockedCallbackNapi_);
1225     cb->SaveMicrophoneBlockedCallbackReference(args[PARAM1]);
1226     if (!cb->GetMicBlockedTsfnFlag()) {
1227         cb->CreateMicBlockedTsfn(env);
1228     }
1229 }
1230 
On(napi_env env,napi_callback_info info)1231 napi_value NapiAudioRoutingManager::On(napi_env env, napi_callback_info info)
1232 {
1233     const size_t requireArgc = ARGS_TWO;
1234     const size_t maxArgc = ARGS_THREE;
1235     size_t argc = ARGS_THREE;
1236 
1237     napi_value undefinedResult = nullptr;
1238     napi_get_undefined(env, &undefinedResult);
1239 
1240     napi_value args[requireArgc + PARAM1] = { nullptr, nullptr, nullptr };
1241     napi_value jsThis = nullptr;
1242     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
1243     bool isArgcCountRight = argc == requireArgc || argc == maxArgc;
1244     CHECK_AND_RETURN_RET_LOG(status == napi_ok && isArgcCountRight, NapiAudioError::ThrowErrorAndReturn(env,
1245         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"),
1246         "status or isArgcCountRight error");
1247 
1248     napi_valuetype eventType = napi_undefined;
1249     napi_typeof(env, args[PARAM0], &eventType);
1250     CHECK_AND_RETURN_RET_LOG(eventType == napi_string, NapiAudioError::ThrowErrorAndReturn(env,
1251         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of eventType must be string"),
1252         "eventType is invalid");
1253     std::string callbackName = NapiParamUtils::GetStringArgument(env, args[PARAM0]);
1254     AUDIO_INFO_LOG("On callbackName: %{public}s", callbackName.c_str());
1255 
1256     if (argc == requireArgc) {
1257         napi_valuetype handler = napi_undefined;
1258         napi_typeof(env, args[PARAM1], &handler);
1259         CHECK_AND_RETURN_RET_LOG(handler == napi_function, NapiAudioError::ThrowErrorAndReturn(env,
1260             NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of callback must be function"),
1261             "handler is invalid");
1262     }
1263 
1264     return RegisterCallback(env, jsThis, argc, args, callbackName);
1265 }
1266 
UnregisterCallback(napi_env env,napi_value jsThis,const std::string & callbackName,napi_value callback)1267 napi_value NapiAudioRoutingManager::UnregisterCallback(napi_env env, napi_value jsThis,
1268     const std::string &callbackName, napi_value callback)
1269 {
1270     napi_value undefinedResult = nullptr;
1271     napi_get_undefined(env, &undefinedResult);
1272     NapiAudioRoutingManager *napiRoutingMgr = nullptr;
1273     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiRoutingMgr));
1274     CHECK_AND_RETURN_RET_LOG(status == napi_ok && napiRoutingMgr != nullptr, undefinedResult,
1275         "Failed to retrieve audio mgr napi instance.");
1276     CHECK_AND_RETURN_RET_LOG(napiRoutingMgr->audioMngr_ != nullptr, undefinedResult,
1277         "audio system mgr instance is null.");
1278     if (!callbackName.compare(DEVICE_CHANGE_CALLBACK_NAME)) {
1279         UnregisterDeviceChangeCallback(env, callback, napiRoutingMgr);
1280     } else if (!callbackName.compare(PREFERRED_OUTPUT_DEVICE_CALLBACK_NAME) ||
1281         !callbackName.compare(PREFER_OUTPUT_DEVICE_CALLBACK_NAME)) {
1282         UnregisterPreferredOutputDeviceChangeCallback(env, callback, napiRoutingMgr);
1283     } else if (!callbackName.compare(PREFERRED_INPUT_DEVICE_CALLBACK_NAME)) {
1284         UnregisterPreferredInputDeviceChangeCallback(env, callback, napiRoutingMgr);
1285     } else if (!callbackName.compare(AVAILABLE_DEVICE_CHANGE_CALLBACK_NAME)) {
1286         UnregisterAvailableDeviceChangeCallback(env, callback, napiRoutingMgr);
1287     } else if (!callbackName.compare(MICROPHONE_BLOCKED_CALLBACK_NAME)) {
1288         UnregisterMicrophoneBlockedCallback(env, callback, napiRoutingMgr);
1289     } else {
1290         AUDIO_ERR_LOG("off no such supported");
1291         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
1292             "parameter verification failed: The param of type is not supported");
1293     }
1294 
1295     return undefinedResult;
1296 }
1297 
UnregisterDeviceChangeCallback(napi_env env,napi_value callback,NapiAudioRoutingManager * napiRoutingMgr)1298 void NapiAudioRoutingManager::UnregisterDeviceChangeCallback(napi_env env, napi_value callback,
1299     NapiAudioRoutingManager *napiRoutingMgr)
1300 {
1301     if (napiRoutingMgr->deviceChangeCallbackNapi_ != nullptr) {
1302         std::shared_ptr<NapiAudioManagerCallback> cb =
1303             std::static_pointer_cast<NapiAudioManagerCallback>(
1304             napiRoutingMgr->deviceChangeCallbackNapi_);
1305         if (callback != nullptr) {
1306             cb->RemoveRoutingManagerDeviceChangeCbRef(env, callback);
1307         }
1308         if (callback == nullptr || cb->GetRoutingManagerDeviceChangeCbListSize() == 0) {
1309             int32_t ret = napiRoutingMgr->audioMngr_->UnsetDeviceChangeCallback(DeviceFlag::ALL_L_D_DEVICES_FLAG,
1310                 napiRoutingMgr->deviceChangeCallbackNapi_);
1311             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetDeviceChangeCallback Failed");
1312             napiRoutingMgr->deviceChangeCallbackNapi_.reset();
1313             napiRoutingMgr->deviceChangeCallbackNapi_ = nullptr;
1314 
1315             cb->RemoveAllRoutingManagerDeviceChangeCb();
1316         }
1317     } else {
1318         AUDIO_ERR_LOG("UnregisterDeviceChangeCallback: deviceChangeCallbackNapi_ is null");
1319     }
1320 }
1321 
RemovePreferredOutputDeviceChangeCallback(NapiAudioRoutingManager * napiRoutingMgr,std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb)1322 void NapiAudioRoutingManager::RemovePreferredOutputDeviceChangeCallback(NapiAudioRoutingManager *napiRoutingMgr,
1323     std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb)
1324 {
1325     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredOutputDeviceMutex_);
1326     napiRoutingMgr->preferredOutputDeviceCallbacks_.remove(cb);
1327 }
1328 
RemoveAllPrefOutputDeviceChangeCallback(napi_env env,NapiAudioRoutingManager * napiRoutingMgr)1329 void NapiAudioRoutingManager::RemoveAllPrefOutputDeviceChangeCallback(napi_env env,
1330     NapiAudioRoutingManager *napiRoutingMgr)
1331 {
1332     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredOutputDeviceMutex_);
1333     for (auto &iter : napiRoutingMgr->preferredOutputDeviceCallbacks_) {
1334         int32_t ret = napiRoutingMgr->audioRoutingMngr_->UnsetPreferredOutputDeviceChangeCallback(iter);
1335         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
1336             "Unset one of preferred output device change callback failed!");
1337     }
1338     napiRoutingMgr->preferredOutputDeviceCallbacks_.clear();
1339 }
1340 
UnregisterPreferredOutputDeviceChangeCallback(napi_env env,napi_value callback,NapiAudioRoutingManager * napiRoutingMgr)1341 void NapiAudioRoutingManager::UnregisterPreferredOutputDeviceChangeCallback(napi_env env, napi_value callback,
1342     NapiAudioRoutingManager *napiRoutingMgr)
1343 {
1344     if (callback != nullptr) {
1345         std::shared_ptr<NapiAudioPreferredOutputDeviceChangeCallback> cb =
1346             GetNapiPrefOutputDeviceChangeCb(callback, napiRoutingMgr);
1347         CHECK_AND_RETURN_LOG(cb != nullptr, "NapiPreferredOutputDeviceCallback is nullptr");
1348         int32_t ret = napiRoutingMgr->audioRoutingMngr_->UnsetPreferredOutputDeviceChangeCallback(cb);
1349         CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetPreferredOutputDeviceChangeCallback Failed");
1350 
1351         RemovePreferredOutputDeviceChangeCallback(napiRoutingMgr, cb);
1352         return;
1353     }
1354 
1355     RemoveAllPrefOutputDeviceChangeCallback(env, napiRoutingMgr);
1356 }
1357 
RemovePreferredInputDeviceChangeCallback(NapiAudioRoutingManager * napiRoutingMgr,std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb)1358 void NapiAudioRoutingManager::RemovePreferredInputDeviceChangeCallback(NapiAudioRoutingManager *napiRoutingMgr,
1359     std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb)
1360 {
1361     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredInputDeviceMutex_);
1362     napiRoutingMgr->preferredInputDeviceCallbacks_.remove(cb);
1363 }
1364 
RemoveAllPrefInputDeviceChangeCallback(napi_env env,NapiAudioRoutingManager * napiRoutingMgr)1365 void NapiAudioRoutingManager::RemoveAllPrefInputDeviceChangeCallback(napi_env env,
1366     NapiAudioRoutingManager *napiRoutingMgr)
1367 {
1368     std::lock_guard<std::mutex> lock(napiRoutingMgr->preferredInputDeviceMutex_);
1369     for (auto &iter : napiRoutingMgr->preferredInputDeviceCallbacks_) {
1370         int32_t ret = napiRoutingMgr->audioRoutingMngr_->UnsetPreferredInputDeviceChangeCallback(iter);
1371         CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, NapiAudioError::ThrowError(env, ret),
1372             "Unset one of preferred input device change callback failed!");
1373     }
1374     napiRoutingMgr->preferredInputDeviceCallbacks_.clear();
1375 }
1376 
UnregisterPreferredInputDeviceChangeCallback(napi_env env,napi_value callback,NapiAudioRoutingManager * napiRoutingMgr)1377 void NapiAudioRoutingManager::UnregisterPreferredInputDeviceChangeCallback(napi_env env, napi_value callback,
1378     NapiAudioRoutingManager *napiRoutingMgr)
1379 {
1380     if (callback != nullptr) {
1381         std::shared_ptr<NapiAudioPreferredInputDeviceChangeCallback> cb =
1382             GetNapiPrefInputDeviceChangeCb(callback, napiRoutingMgr);
1383         CHECK_AND_RETURN_LOG(cb != nullptr, "NapiPreferredInputDeviceCallback is nullptr");
1384         int32_t ret = napiRoutingMgr->audioRoutingMngr_->UnsetPreferredInputDeviceChangeCallback(cb);
1385         CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetPreferredInputDeviceChangeCallback Failed");
1386 
1387         RemovePreferredInputDeviceChangeCallback(napiRoutingMgr, cb);
1388         return;
1389     }
1390 
1391     RemoveAllPrefInputDeviceChangeCallback(env, napiRoutingMgr);
1392 }
1393 
UnregisterAvailableDeviceChangeCallback(napi_env env,napi_value callback,NapiAudioRoutingManager * napiRoutingMgr)1394 void NapiAudioRoutingManager::UnregisterAvailableDeviceChangeCallback(napi_env env, napi_value callback,
1395     NapiAudioRoutingManager *napiRoutingMgr)
1396 {
1397     if (napiRoutingMgr->availableDeviceChangeCallbackNapi_ != nullptr) {
1398         std::shared_ptr<NapiAudioRountingAvailableDeviceChangeCallback> cb =
1399             std::static_pointer_cast<NapiAudioRountingAvailableDeviceChangeCallback>(
1400             napiRoutingMgr->availableDeviceChangeCallbackNapi_);
1401         if (callback == nullptr || cb->GetRoutingAvailbleDeviceChangeCbListSize() == 0) {
1402             int32_t ret = napiRoutingMgr->audioMngr_->UnsetAvailableDeviceChangeCallback(D_ALL_DEVICES);
1403             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetAvailableDeviceChangeCallback Failed");
1404 
1405             napiRoutingMgr->availableDeviceChangeCallbackNapi_.reset();
1406             napiRoutingMgr->availableDeviceChangeCallbackNapi_ = nullptr;
1407             cb->RemoveAllRoutinAvailbleDeviceChangeCb();
1408             return;
1409         }
1410         cb->RemoveRoutingAvailbleDeviceChangeCbRef(env, callback);
1411     } else {
1412         AUDIO_ERR_LOG("UnregisterAvailableDeviceChangeCallback: availableDeviceChangeCallbackNapi_ is null");
1413     }
1414 }
1415 
UnregisterMicrophoneBlockedCallback(napi_env env,napi_value callback,NapiAudioRoutingManager * napiRoutingMgr)1416 void NapiAudioRoutingManager::UnregisterMicrophoneBlockedCallback(napi_env env, napi_value callback,
1417     NapiAudioRoutingManager *napiRoutingMgr)
1418 {
1419     if (napiRoutingMgr->microphoneBlockedCallbackNapi_ != nullptr) {
1420         std::shared_ptr<NapiAudioManagerCallback> cb =
1421             std::static_pointer_cast<NapiAudioManagerCallback>(
1422             napiRoutingMgr->microphoneBlockedCallbackNapi_);
1423         if (callback == nullptr || cb->GetMicrophoneBlockedCbListSize() == 0) {
1424             int32_t ret = napiRoutingMgr->audioMngr_->UnsetMicrophoneBlockedCallback(
1425                 napiRoutingMgr->microphoneBlockedCallbackNapi_);
1426             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetMicrophoneBlockedCallback Failed");
1427             napiRoutingMgr->microphoneBlockedCallbackNapi_.reset();
1428             napiRoutingMgr->microphoneBlockedCallbackNapi_ = nullptr;
1429             cb->RemoveAllMicrophoneBlockedCallback();
1430             return;
1431         }
1432         cb->RemoveMicrophoneBlockedCallbackReference(env, callback);
1433     } else {
1434         AUDIO_ERR_LOG("microphoneBlockedCallbackNapi_ is null");
1435     }
1436 }
1437 
Off(napi_env env,napi_callback_info info)1438 napi_value NapiAudioRoutingManager::Off(napi_env env, napi_callback_info info)
1439 {
1440     napi_value undefinedResult = nullptr;
1441     napi_get_undefined(env, &undefinedResult);
1442 
1443     const size_t minArgCount = ARGS_ONE;
1444     size_t argCount = ARGS_TWO;
1445     napi_value args[minArgCount + PARAM1] = {nullptr, nullptr};
1446     napi_value jsThis = nullptr;
1447     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
1448     if (status != napi_ok || argCount < minArgCount) {
1449         AUDIO_ERR_LOG("Off fail to napi_get_cb_info/Requires min 1 parameters");
1450         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1451             "mandatory parameters are left unspecified");
1452         return undefinedResult;
1453     }
1454 
1455     napi_valuetype eventType = napi_undefined;
1456     if (napi_typeof(env, args[PARAM0], &eventType) != napi_ok || eventType != napi_string) {
1457         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1458             "incorrect parameter types: The type of eventType must be string");
1459         return undefinedResult;
1460     }
1461 
1462     napi_valuetype secondArgsType = napi_undefined;
1463     if (argCount > minArgCount &&
1464         (napi_typeof(env, args[PARAM1], &secondArgsType) != napi_ok || secondArgsType != napi_function)) {
1465         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID,
1466             "incorrect parameter types: The type of callback must be function");
1467         return undefinedResult;
1468     }
1469     std::string callbackName = NapiParamUtils::GetStringArgument(env, args[PARAM0]);
1470 
1471     if (argCount == minArgCount) {
1472         args[PARAM1] = nullptr;
1473     }
1474     AUDIO_INFO_LOG("Off callbackName: %{public}s", callbackName.c_str());
1475 
1476     return UnregisterCallback(env, jsThis, callbackName, args[PARAM1]);
1477 }
1478 
GetMicrophoneBlockedCbListSize()1479 int32_t NapiAudioManagerCallback::GetMicrophoneBlockedCbListSize()
1480 {
1481     std::lock_guard<std::mutex> lock(mutex_);
1482     return microphoneBlockedCbList_.size();
1483 }
1484 
1485 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
IsMicBlockDetectionSupported(napi_env env,napi_callback_info info)1486 napi_value NapiAudioRoutingManager::IsMicBlockDetectionSupported(napi_env env, napi_callback_info info)
1487 {
1488     auto context = std::make_shared<AudioRoutingManagerAsyncContext>();
1489     context->GetCbInfo(env, info);
1490     auto executor = [context]() {
1491         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
1492         context->supported = OHOS::system::GetBoolParameter("const.multimedia.audio.mic_block_detection", false);
1493         if (context->supported == true) {
1494         AUDIO_INFO_LOG("mic block detection supported");
1495         } else {
1496         AUDIO_ERR_LOG("mic block detection is not supported");
1497         }
1498     };
1499     auto complete = [env, context](napi_value &output) {
1500         NapiParamUtils::SetValueBoolean(env, context->supported, output);
1501     };
1502     return NapiAsyncWork::Enqueue(env, context, "IsMicBlockDetectionSupported", executor, complete);
1503 }
1504 #endif
1505 }  // namespace AudioStandard
1506 }  // namespace OHOS
1507