• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 
16 #include "audio_routing_manager_napi.h"
17 
18 #include "audio_common_napi.h"
19 #include "audio_micstatechange_callback_napi.h"
20 #include "audio_errors.h"
21 #include "audio_log.h"
22 #include "hilog/log.h"
23 #include "napi_base_context.h"
24 
25 using namespace std;
26 using OHOS::HiviewDFX::HiLog;
27 using OHOS::HiviewDFX::HiLogLabel;
28 
29 namespace OHOS {
30 namespace AudioStandard {
31 static __thread napi_ref g_routingManagerConstructor = nullptr;
32 
33 namespace {
34     const int ARGS_ONE = 1;
35     const int ARGS_TWO = 2;
36     const int ARGS_THREE = 3;
37     const int SIZE = 100;
38     const int PARAM0 = 0;
39     const int PARAM1 = 1;
40     const int PARAM2 = 2;
41     const int PARAM3 = 3;
42 
43     constexpr HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AudioRoutingManagerNapi"};
44 }
45 
46 struct AudioRoutingManagerAsyncContext {
47     napi_env env;
48     napi_async_work work;
49     napi_deferred deferred;
50     napi_ref callbackRef = nullptr;
51     int32_t deviceFlag;
52     int32_t status = SUCCESS;
53     int32_t deviceType;
54     bool isActive;
55     bool isTrue;
56     bool bArgTransFlag = true;
57     AudioRoutingManagerNapi *objectInfo;
58     sptr<AudioRendererFilter> audioRendererFilter;
59     sptr<AudioCapturerFilter> audioCapturerFilter;
60     vector<sptr<AudioDeviceDescriptor>> deviceDescriptors;
61     vector<sptr<AudioDeviceDescriptor>> outDeviceDescriptors;
62 };
63 
AudioRoutingManagerNapi()64 AudioRoutingManagerNapi::AudioRoutingManagerNapi()
65     : audioMngr_(nullptr), env_(nullptr) {}
66 
67 AudioRoutingManagerNapi::~AudioRoutingManagerNapi() = default;
68 
Destructor(napi_env env,void * nativeObject,void * finalize_hint)69 void AudioRoutingManagerNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
70 {
71     if (nativeObject != nullptr) {
72         auto obj = static_cast<AudioRoutingManagerNapi *>(nativeObject);
73         delete obj;
74         obj = nullptr;
75     }
76 }
77 
Init(napi_env env,napi_value exports)78 napi_value AudioRoutingManagerNapi::Init(napi_env env, napi_value exports)
79 {
80     AUDIO_INFO_LOG("AudioRoutingManagerNapi::Init");
81     napi_status status;
82     napi_value constructor;
83     napi_value result = nullptr;
84     const int32_t refCount = 1;
85     napi_get_undefined(env, &result);
86 
87     napi_property_descriptor audio_routing_manager_properties[] = {
88         DECLARE_NAPI_FUNCTION("getDevices", GetDevices),
89         DECLARE_NAPI_FUNCTION("on", AudioRoutingManagerNapi::On),
90         DECLARE_NAPI_FUNCTION("off", AudioRoutingManagerNapi::Off),
91         DECLARE_NAPI_FUNCTION("selectOutputDevice", SelectOutputDevice),
92         DECLARE_NAPI_FUNCTION("selectOutputDeviceByFilter", SelectOutputDeviceByFilter),
93         DECLARE_NAPI_FUNCTION("selectInputDevice", SelectInputDevice),
94         DECLARE_NAPI_FUNCTION("selectInputDeviceByFilter", SelectInputDeviceByFilter),
95         DECLARE_NAPI_FUNCTION("setCommunicationDevice", SetCommunicationDevice),
96         DECLARE_NAPI_FUNCTION("isCommunicationDeviceActive", IsCommunicationDeviceActive),
97         DECLARE_NAPI_FUNCTION("getActiveOutputDeviceDescriptors", GetActiveOutputDeviceDescriptors),
98     };
99 
100     status = napi_define_class(env, AUDIO_ROUTING_MANAGER_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct, nullptr,
101         sizeof(audio_routing_manager_properties) / sizeof(audio_routing_manager_properties[PARAM0]),
102         audio_routing_manager_properties, &constructor);
103     if (status != napi_ok) {
104         return result;
105     }
106     status = napi_create_reference(env, constructor, refCount, &g_routingManagerConstructor);
107     if (status == napi_ok) {
108         status = napi_set_named_property(env, exports, AUDIO_ROUTING_MANAGER_NAPI_CLASS_NAME.c_str(), constructor);
109         if (status == napi_ok) {
110             return exports;
111         }
112     }
113 
114     HiLog::Error(LABEL, "Failure in AudioRoutingManagerNapi::Init()");
115     return result;
116 }
117 
CreateRoutingManagerWrapper(napi_env env)118 napi_value AudioRoutingManagerNapi::CreateRoutingManagerWrapper(napi_env env)
119 {
120     napi_status status;
121     napi_value result = nullptr;
122     napi_value constructor;
123 
124     status = napi_get_reference_value(env, g_routingManagerConstructor, &constructor);
125     if (status == napi_ok) {
126         status = napi_new_instance(env, constructor, 0, nullptr, &result);
127         if (status == napi_ok) {
128             return result;
129         }
130     }
131     HiLog::Error(LABEL, "Failed in AudioRoutingManagerNapi::CreateRoutingManagerWrapper!");
132     napi_get_undefined(env, &result);
133 
134     return result;
135 }
136 
Construct(napi_env env,napi_callback_info info)137 napi_value AudioRoutingManagerNapi::Construct(napi_env env, napi_callback_info info)
138 {
139     AUDIO_INFO_LOG("AudioRoutingManagerNapi::Construct");
140     napi_status status;
141     napi_value result = nullptr;
142     napi_get_undefined(env, &result);
143 
144     size_t argc = ARGS_TWO;
145     napi_value argv[ARGS_TWO] = {0};
146     napi_value thisVar = nullptr;
147     void *data = nullptr;
148     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
149     unique_ptr<AudioRoutingManagerNapi> audioRoutingManagerNapi = make_unique<AudioRoutingManagerNapi>();
150     CHECK_AND_RETURN_RET_LOG(audioRoutingManagerNapi != nullptr, result, "No memory");
151 
152     audioRoutingManagerNapi->audioMngr_ = AudioSystemManager::GetInstance();
153 
154     audioRoutingManagerNapi->audioRoutingMngr_ = AudioRoutingManager::GetInstance();
155 
156     audioRoutingManagerNapi->env_ = env;
157 
158     status = napi_wrap(env, thisVar, static_cast<void*>(audioRoutingManagerNapi.get()),
159         AudioRoutingManagerNapi::Destructor, nullptr, nullptr);
160     if (status == napi_ok) {
161         audioRoutingManagerNapi.release();
162         return thisVar;
163     }
164 
165     HiLog::Error(LABEL, "Failed in AudioRoutingManager::Construct()!");
166     return result;
167 }
168 
CommonCallbackRoutine(napi_env env,AudioRoutingManagerAsyncContext * & asyncContext,const napi_value & valueParam)169 static void CommonCallbackRoutine(napi_env env, AudioRoutingManagerAsyncContext *&asyncContext,
170     const napi_value &valueParam)
171 {
172     napi_value result[ARGS_TWO] = {0};
173     napi_value retVal;
174 
175     if (!asyncContext->status) {
176         napi_get_undefined(env, &result[PARAM0]);
177         result[PARAM1] = valueParam;
178     } else {
179         napi_value message = nullptr;
180         std::string messageValue = AudioCommonNapi::getMessageByCode(asyncContext->status);
181         napi_create_string_utf8(env, messageValue.c_str(), NAPI_AUTO_LENGTH, &message);
182 
183         napi_value code = nullptr;
184         napi_create_string_utf8(env, (std::to_string(asyncContext->status)).c_str(), NAPI_AUTO_LENGTH, &code);
185 
186         napi_create_error(env, code, message, &result[PARAM0]);
187         napi_get_undefined(env, &result[PARAM1]);
188     }
189 
190     if (asyncContext->deferred) {
191         if (!asyncContext->status) {
192             napi_resolve_deferred(env, asyncContext->deferred, result[PARAM1]);
193         } else {
194             napi_reject_deferred(env, asyncContext->deferred, result[PARAM0]);
195         }
196     } else {
197         napi_value callback = nullptr;
198         napi_get_reference_value(env, asyncContext->callbackRef, &callback);
199         napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
200         napi_delete_reference(env, asyncContext->callbackRef);
201     }
202     napi_delete_async_work(env, asyncContext->work);
203 
204     delete asyncContext;
205     asyncContext = nullptr;
206 }
207 
SetFunctionAsyncCallbackComplete(napi_env env,napi_status status,void * data)208 static void SetFunctionAsyncCallbackComplete(napi_env env, napi_status status, void *data)
209 {
210     auto asyncContext = static_cast<AudioRoutingManagerAsyncContext*>(data);
211     napi_value valueParam = nullptr;
212 
213     if (asyncContext != nullptr) {
214         if (!asyncContext->status) {
215             napi_get_undefined(env, &valueParam);
216         }
217         CommonCallbackRoutine(env, asyncContext, valueParam);
218     } else {
219         HiLog::Error(LABEL, "ERROR: AudioManagerAsyncContext* is Null!");
220     }
221 }
222 
IsTrueAsyncCallbackComplete(napi_env env,napi_status status,void * data)223 static void IsTrueAsyncCallbackComplete(napi_env env, napi_status status, void *data)
224 {
225     auto asyncContext = static_cast<AudioRoutingManagerAsyncContext*>(data);
226     napi_value valueParam = nullptr;
227 
228     if (asyncContext != nullptr) {
229         if (!asyncContext->status) {
230             napi_get_boolean(env, asyncContext->isTrue, &valueParam);
231         }
232         CommonCallbackRoutine(env, asyncContext, valueParam);
233     } else {
234         HiLog::Error(LABEL, "ERROR: AudioManagerAsyncContext* is Null!");
235     }
236 }
237 
ParseAudioRendererInfo(napi_env env,napi_value root,AudioRendererInfo * rendererInfo)238 static void ParseAudioRendererInfo(napi_env env, napi_value root, AudioRendererInfo *rendererInfo)
239 {
240     napi_value tempValue = nullptr;
241     int32_t intValue = {0};
242 
243     if (napi_get_named_property(env, root, "contentType", &tempValue) == napi_ok) {
244         napi_get_value_int32(env, tempValue, &intValue);
245         rendererInfo->contentType = static_cast<ContentType>(intValue);
246     }
247 
248     if (napi_get_named_property(env, root, "streamUsage", &tempValue) == napi_ok) {
249         napi_get_value_int32(env, tempValue, &intValue);
250         rendererInfo->streamUsage = static_cast<StreamUsage>(intValue);
251     }
252 
253     if (napi_get_named_property(env, root, "rendererFlags", &tempValue) == napi_ok) {
254         napi_get_value_int32(env, tempValue, &(rendererInfo->rendererFlags));
255     }
256 }
257 
258 
ParseAudioRendererFilter(napi_env env,napi_value root,sptr<AudioRendererFilter> & audioRendererFilter,bool & argTransFlag)259 static void ParseAudioRendererFilter(napi_env env, napi_value root,
260     sptr<AudioRendererFilter> &audioRendererFilter, bool &argTransFlag)
261 {
262     napi_value tempValue = nullptr;
263     int32_t intValue = {0};
264     argTransFlag = true;
265     bool hasUid = true;
266     napi_has_named_property(env, root, "uid", &hasUid);
267 
268     if (!hasUid) {
269         argTransFlag = false;
270         return;
271     }
272     audioRendererFilter = new(std::nothrow) AudioRendererFilter();
273 
274     if (napi_get_named_property(env, root, "uid", &tempValue) == napi_ok) {
275         napi_get_value_int32(env, tempValue, &intValue);
276         audioRendererFilter->uid = intValue;
277     }
278 
279     if (napi_get_named_property(env, root, "rendererInfo", &tempValue) == napi_ok) {
280         ParseAudioRendererInfo(env, tempValue, &(audioRendererFilter->rendererInfo));
281     }
282 
283     if (napi_get_named_property(env, root, "rendererId", &tempValue) == napi_ok) {
284         napi_get_value_int32(env, tempValue, &intValue);
285         audioRendererFilter->streamId = intValue;
286     }
287 }
288 
ParseAudioDeviceDescriptor(napi_env env,napi_value root,sptr<AudioDeviceDescriptor> & selectedAudioDevice,bool & argTransFlag)289 static void ParseAudioDeviceDescriptor(napi_env env, napi_value root,
290     sptr<AudioDeviceDescriptor> &selectedAudioDevice, bool &argTransFlag)
291 {
292     napi_value tempValue = nullptr;
293     int32_t intValue = {0};
294     char buffer[SIZE];
295     size_t res = 0;
296     argTransFlag = true;
297     bool hasDeviceRole = true;
298     bool hasNetworkId  = true;
299     napi_has_named_property(env, root, "deviceRole", &hasDeviceRole);
300     napi_has_named_property(env, root, "networkId", &hasNetworkId);
301 
302     if ((!hasDeviceRole) || (!hasNetworkId)) {
303         argTransFlag = false;
304         return;
305     }
306 
307     if (napi_get_named_property(env, root, "deviceRole", &tempValue) == napi_ok) {
308         napi_get_value_int32(env, tempValue, &intValue);
309         selectedAudioDevice->deviceRole_ = static_cast<DeviceRole>(intValue);
310     }
311 
312     if (napi_get_named_property(env, root, "deviceType", &tempValue) == napi_ok) {
313         napi_get_value_int32(env, tempValue, &intValue);
314         selectedAudioDevice->deviceType_ = static_cast<DeviceType>(intValue);
315     }
316 
317     if (napi_get_named_property(env, root, "networkId", &tempValue) == napi_ok) {
318         napi_get_value_string_utf8(env, tempValue, buffer, SIZE, &res);
319         selectedAudioDevice->networkId_ = std::string(buffer);
320     }
321 
322     if (napi_get_named_property(env, root, "interruptGroupId", &tempValue) == napi_ok) {
323         napi_get_value_int32(env, tempValue, &intValue);
324         selectedAudioDevice->interruptGroupId_ = intValue;
325     }
326 
327     if (napi_get_named_property(env, root, "volumeGroupId", &tempValue) == napi_ok) {
328         napi_get_value_int32(env, tempValue, &intValue);
329         selectedAudioDevice->volumeGroupId_ = intValue;
330     }
331 }
332 
ParseAudioDeviceDescriptorVector(napi_env env,napi_value root,vector<sptr<AudioDeviceDescriptor>> & deviceDescriptorsVector,bool & argTransFlag)333 static void ParseAudioDeviceDescriptorVector(napi_env env, napi_value root,
334     vector<sptr<AudioDeviceDescriptor>> &deviceDescriptorsVector, bool &argTransFlag)
335 {
336     uint32_t arrayLen = 0;
337     napi_get_array_length(env, root, &arrayLen);
338     if (arrayLen == 0) {
339         deviceDescriptorsVector = {};
340         AUDIO_INFO_LOG("Error: AudioDeviceDescriptor vector is NULL!");
341     }
342 
343     for (size_t i = 0; i < arrayLen; i++) {
344         napi_value element;
345         napi_get_element(env, root, i, &element);
346         sptr<AudioDeviceDescriptor> selectedAudioDevice = new(std::nothrow) AudioDeviceDescriptor();
347         ParseAudioDeviceDescriptor(env, element, selectedAudioDevice, argTransFlag);
348         if (!argTransFlag) {
349             return;
350         }
351         deviceDescriptorsVector.push_back(selectedAudioDevice);
352     }
353 }
354 
355 
SelectOutputDeviceAsyncCallbackComplete(napi_env env,napi_status status,void * data)356 static void SelectOutputDeviceAsyncCallbackComplete(napi_env env, napi_status status, void *data)
357 {
358     auto asyncContext = static_cast<AudioRoutingManagerAsyncContext*>(data);
359     napi_value valueParam = nullptr;
360 
361     if (asyncContext != nullptr) {
362         if (!asyncContext->status) {
363             napi_get_undefined(env, &valueParam);
364         }
365         CommonCallbackRoutine(env, asyncContext, valueParam);
366     } else {
367         HiLog::Error(LABEL, "ERROR: AudioRoutingManagerAsyncContext* is Null!");
368     }
369 }
370 
SetValueInt32(const napi_env & env,const std::string & fieldStr,const int intValue,napi_value & result)371 static void SetValueInt32(const napi_env& env, const std::string& fieldStr, const int intValue, napi_value& result)
372 {
373     napi_value value = nullptr;
374     napi_create_int32(env, intValue, &value);
375     napi_set_named_property(env, result, fieldStr.c_str(), value);
376 }
377 
SetValueString(const napi_env & env,const std::string & fieldStr,const std::string stringValue,napi_value & result)378 static void SetValueString(const napi_env& env, const std::string& fieldStr, const std::string stringValue,
379     napi_value& result)
380 {
381     napi_value value = nullptr;
382     napi_create_string_utf8(env, stringValue.c_str(), NAPI_AUTO_LENGTH, &value);
383     napi_set_named_property(env, result, fieldStr.c_str(), value);
384 }
385 
SetDevicesInfo(vector<sptr<AudioDeviceDescriptor>> deviceDescriptors,napi_env env,napi_value * result,napi_value valueParam)386 static void SetDevicesInfo(vector<sptr<AudioDeviceDescriptor>> deviceDescriptors, napi_env env, napi_value* result,
387     napi_value valueParam)
388 {
389     size_t size = deviceDescriptors.size();
390     HiLog::Info(LABEL, "number of devices = %{public}zu", size);
391 
392     napi_create_array_with_length(env, size, &result[PARAM1]);
393     for (size_t i = 0; i < size; i++) {
394         if (deviceDescriptors[i] != nullptr) {
395             (void)napi_create_object(env, &valueParam);
396             SetValueInt32(env, "deviceRole", static_cast<int32_t>(
397                 deviceDescriptors[i]->deviceRole_), valueParam);
398             SetValueInt32(env, "deviceType", static_cast<int32_t>(
399                 deviceDescriptors[i]->deviceType_), valueParam);
400             SetValueInt32(env, "id", static_cast<int32_t>(
401                 deviceDescriptors[i]->deviceId_), valueParam);
402             SetValueString(env, "name", deviceDescriptors[i]->deviceName_, valueParam);
403             SetValueString(env, "address", deviceDescriptors[i]->macAddress_, valueParam);
404             SetValueString(env, "networkId", static_cast<std::string>(
405                 deviceDescriptors[i]->networkId_), valueParam);
406             SetValueInt32(env, "interruptGroupId", static_cast<int32_t>(
407                 deviceDescriptors[i]->interruptGroupId_), valueParam);
408             SetValueInt32(env, "volumeGroupId", static_cast<int32_t>(
409                 deviceDescriptors[i]->volumeGroupId_), valueParam);
410 
411             napi_value value = nullptr;
412             napi_value sampleRates;
413             napi_create_array_with_length(env, 1, &sampleRates);
414             napi_create_int32(env, deviceDescriptors[i]->audioStreamInfo_.samplingRate, &value);
415             napi_set_element(env, sampleRates, 0, value);
416             napi_set_named_property(env, valueParam, "sampleRates", sampleRates);
417 
418             napi_value channelCounts;
419             napi_create_array_with_length(env, 1, &channelCounts);
420             napi_create_int32(env, deviceDescriptors[i]->audioStreamInfo_.channels, &value);
421             napi_set_element(env, channelCounts, 0, value);
422             napi_set_named_property(env, valueParam, "channelCounts", channelCounts);
423 
424             napi_value channelMasks;
425             napi_create_array_with_length(env, 1, &channelMasks);
426             napi_create_int32(env, deviceDescriptors[i]->channelMasks_, &value);
427             napi_set_element(env, channelMasks, 0, value);
428             napi_set_named_property(env, valueParam, "channelMasks", channelMasks);
429             napi_set_element(env, result[PARAM1], i, valueParam);
430         }
431     }
432 }
433 
GetDevicesAsyncCallbackComplete(napi_env env,napi_status status,void * data)434 static void GetDevicesAsyncCallbackComplete(napi_env env, napi_status status, void* data)
435 {
436     auto asyncContext = static_cast<AudioRoutingManagerAsyncContext*>(data);
437     if (asyncContext == nullptr) {
438         HiLog::Error(LABEL, "ERROR: AudioRoutingManagerAsyncContext* is Null!");
439         return;
440     }
441     napi_value result[ARGS_TWO] = {0};
442     napi_value valueParam = nullptr;
443     SetDevicesInfo(asyncContext->deviceDescriptors, env, result, valueParam);
444 
445     napi_get_undefined(env, &result[PARAM0]);
446     if (!asyncContext->status) {
447         napi_get_undefined(env, &valueParam);
448     }
449     CommonCallbackRoutine(env, asyncContext, result[PARAM1]);
450 }
451 
GetDevices(napi_env env,napi_callback_info info)452 napi_value AudioRoutingManagerNapi::GetDevices(napi_env env, napi_callback_info info)
453 {
454     const int32_t refCount = 1;
455     napi_value result = nullptr;
456 
457     size_t argc = ARGS_TWO;
458     napi_value argv[ARGS_TWO] = { 0 };
459     napi_value thisVar = nullptr;
460     void* data;
461     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
462 
463     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
464 
465     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
466     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
467         CheckParams(argc, env, argv, asyncContext, refCount, result);
468 
469         napi_value resource = nullptr;
470         napi_create_string_utf8(env, "GetDevices", NAPI_AUTO_LENGTH, &resource);
471 
472         status = napi_create_async_work(
473             env, nullptr, resource, [](napi_env env, void *data) {
474                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
475                 if (context->status == SUCCESS) {
476                     context->deviceDescriptors = context->objectInfo->audioMngr_->GetDevices(
477                         static_cast<DeviceFlag>(context->deviceFlag));
478                     context->status = 0;
479                 }
480             }, GetDevicesAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
481         if (status != napi_ok) {
482             result = nullptr;
483         } else {
484             status = napi_queue_async_work(env, asyncContext->work);
485             if (status == napi_ok) {
486                 asyncContext.release();
487             } else {
488                 result = nullptr;
489             }
490         }
491     }
492 
493     return result;
494 }
495 
CheckParams(size_t argc,napi_env env,napi_value * argv,std::unique_ptr<AudioRoutingManagerAsyncContext> & asyncContext,const int32_t refCount,napi_value & result)496 void AudioRoutingManagerNapi::CheckParams(size_t argc, napi_env env, napi_value* argv,
497     std::unique_ptr<AudioRoutingManagerAsyncContext>& asyncContext, const int32_t refCount, napi_value& result)
498 {
499     if (argc < ARGS_ONE) {
500             asyncContext->status = NAPI_ERR_INVALID_PARAM;
501     }
502     for (size_t i = PARAM0; i < argc; i++) {
503         napi_valuetype valueType = napi_undefined;
504         napi_typeof(env, argv[i], &valueType);
505 
506         if (i == PARAM0 && valueType == napi_number) {
507             napi_get_value_int32(env, argv[i], &asyncContext->deviceFlag);
508             HiLog::Info(LABEL, " GetDevices deviceFlag = %{public}d", asyncContext->deviceFlag);
509             if (!AudioCommonNapi::IsLegalInputArgumentDeviceFlag(asyncContext->deviceFlag)) {
510                 asyncContext->status = asyncContext->status ==
511                     NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED;
512             }
513         } else if (i == PARAM1) {
514             if (valueType == napi_function) {
515                 napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
516             }
517             break;
518         } else {
519             asyncContext->status = NAPI_ERR_INVALID_PARAM;
520             HiLog::Error(LABEL, "ERROR: type mismatch");
521         }
522     }
523 
524     if (asyncContext->callbackRef == nullptr) {
525         napi_create_promise(env, &asyncContext->deferred, &result);
526     } else {
527         napi_get_undefined(env, &result);
528     }
529 }
530 
SelectOutputDevice(napi_env env,napi_callback_info info)531 napi_value AudioRoutingManagerNapi::SelectOutputDevice(napi_env env, napi_callback_info info)
532 {
533     napi_status status;
534     const int32_t refCount = 1;
535     napi_value result = nullptr;
536     size_t argc = ARGS_TWO;
537     napi_value argv[ARGS_TWO] = {0};
538     napi_value thisVar = nullptr;
539     void *data = nullptr;
540     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
541 
542     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
543 
544     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
545     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
546         if (argc < ARGS_ONE) {
547             asyncContext->status = NAPI_ERR_INVALID_PARAM;
548         }
549         for (size_t i = PARAM0; i < argc; i++) {
550             napi_valuetype valueType = napi_undefined;
551             napi_typeof(env, argv[i], &valueType);
552 
553             if (i == PARAM0 && valueType == napi_object) {
554                 ParseAudioDeviceDescriptorVector(env, argv[i], asyncContext->deviceDescriptors,
555                     asyncContext->bArgTransFlag);
556             } else if (i == PARAM1) {
557                 if (valueType == napi_function) {
558                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
559                 }
560                 break;
561             } else {
562                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
563             }
564         }
565 
566         if (asyncContext->callbackRef == nullptr) {
567             napi_create_promise(env, &asyncContext->deferred, &result);
568         } else {
569             napi_get_undefined(env, &result);
570         }
571 
572         napi_value resource = nullptr;
573         napi_create_string_utf8(env, "SelectOutputDevice", NAPI_AUTO_LENGTH, &resource);
574 
575         status = napi_create_async_work(
576             env, nullptr, resource,
577             [](napi_env env, void *data) {
578                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
579                 if (context->bArgTransFlag) {
580                     context->status = context->objectInfo->audioMngr_->SelectOutputDevice(context->deviceDescriptors);
581                 } else {
582                     context->status = context->status ==
583                         NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED;
584                 }
585             },
586             SelectOutputDeviceAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
587         if (status != napi_ok) {
588             result = nullptr;
589         } else {
590             status = napi_queue_async_work(env, asyncContext->work);
591             if (status == napi_ok) {
592                 asyncContext.release();
593             } else {
594                 result = nullptr;
595             }
596         }
597     }
598     return result;
599 }
600 
GetActiveOutputDeviceAsyncCallbackComplete(napi_env env,napi_status status,void * data)601 static void GetActiveOutputDeviceAsyncCallbackComplete(napi_env env, napi_status status, void* data)
602 {
603     auto asyncContext = static_cast<AudioRoutingManagerAsyncContext*>(data);
604     napi_value result[ARGS_TWO] = {0};
605     napi_value valueParam = nullptr;
606     if (asyncContext == nullptr) {
607         HiLog::Error(LABEL, "ERROR: AudioRoutingManagerAsyncContext* is Null!");
608         return;
609     }
610     SetDevicesInfo(asyncContext->outDeviceDescriptors, env, result, valueParam);
611 
612     napi_get_undefined(env, &result[PARAM0]);
613     if (!asyncContext->status) {
614         napi_get_undefined(env, &valueParam);
615     }
616     CommonCallbackRoutine(env, asyncContext, result[PARAM1]);
617 }
618 
GetActiveOutputDeviceDescriptors(napi_env env,napi_callback_info info)619 napi_value AudioRoutingManagerNapi::GetActiveOutputDeviceDescriptors(napi_env env, napi_callback_info info)
620 {
621     napi_status status;
622     const int32_t refCount = 1;
623     napi_value result = nullptr;
624     size_t argc = ARGS_ONE;
625     napi_value argv[ARGS_ONE] = {0};
626     napi_value thisVar = nullptr;
627     void *data = nullptr;
628     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
629 
630     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
631 
632     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
633     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
634         napi_valuetype valueType = napi_undefined;
635         napi_typeof(env, argv[PARAM0], &valueType);
636 
637         if (argc == PARAM1 && valueType == napi_function) {
638                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
639         }
640 
641         if (asyncContext->callbackRef == nullptr) {
642             napi_create_promise(env, &asyncContext->deferred, &result);
643         } else {
644             napi_get_undefined(env, &result);
645         }
646 
647         napi_value resource = nullptr;
648         napi_create_string_utf8(env, "GetActiveOutputDeviceDescriptors", NAPI_AUTO_LENGTH, &resource);
649 
650         status = napi_create_async_work(
651             env, nullptr, resource,
652             [](napi_env env, void *data) {
653                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
654                 if (context->status == SUCCESS) {
655                     context->outDeviceDescriptors = context->objectInfo->audioMngr_->GetActiveOutputDeviceDescriptors();
656                     context->status = SUCCESS;
657                 }
658             },
659             GetActiveOutputDeviceAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
660         if (status != napi_ok) {
661             result = nullptr;
662         } else {
663             status = napi_queue_async_work(env, asyncContext->work);
664             if (status == napi_ok) {
665                 asyncContext.release();
666             } else {
667                 result = nullptr;
668             }
669         }
670     }
671     return result;
672 }
SelectOutputDeviceByFilter(napi_env env,napi_callback_info info)673 napi_value AudioRoutingManagerNapi::SelectOutputDeviceByFilter(napi_env env, napi_callback_info info)
674 {
675     napi_status status;
676     const int32_t refCount = 1;
677     napi_value result = nullptr;
678     size_t argc = ARGS_THREE;
679     napi_value argv[ARGS_THREE] = {0};
680     napi_value thisVar = nullptr;
681     void *data = nullptr;
682     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
683 
684     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
685 
686     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
687     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
688         if (argc < ARGS_TWO) {
689             asyncContext->status = NAPI_ERR_INVALID_PARAM;
690         }
691         for (size_t i = PARAM0; i < argc; i++) {
692             napi_valuetype valueType = napi_undefined;
693             napi_typeof(env, argv[i], &valueType);
694 
695             if (i == PARAM0 && valueType == napi_object) {
696                 ParseAudioRendererFilter(env, argv[i], asyncContext->audioRendererFilter, asyncContext->bArgTransFlag);
697             } else if (i == PARAM1 && valueType == napi_object) {
698                 ParseAudioDeviceDescriptorVector(env, argv[i], asyncContext->deviceDescriptors,
699                     asyncContext->bArgTransFlag);
700             } else if (i == PARAM2) {
701                 if (valueType == napi_function) {
702                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
703                 }
704                 break;
705             } else {
706                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
707             }
708         }
709 
710         if (asyncContext->callbackRef == nullptr) {
711             napi_create_promise(env, &asyncContext->deferred, &result);
712         } else {
713             napi_get_undefined(env, &result);
714         }
715 
716         napi_value resource = nullptr;
717         napi_create_string_utf8(env, "SelectOutputDeviceByFilter", NAPI_AUTO_LENGTH, &resource);
718 
719         status = napi_create_async_work(
720             env, nullptr, resource,
721             [](napi_env env, void *data) {
722                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
723                 if (context->bArgTransFlag) {
724                     context->status = context->objectInfo->audioMngr_->SelectOutputDevice(
725                         context->audioRendererFilter, context->deviceDescriptors);
726                 } else {
727                     context->status = context->status ==
728                         NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED;
729                 }
730             },
731             SelectOutputDeviceAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
732         if (status != napi_ok) {
733             result = nullptr;
734         } else {
735             status = napi_queue_async_work(env, asyncContext->work);
736             if (status == napi_ok) {
737                 asyncContext.release();
738             } else {
739                 result = nullptr;
740             }
741         }
742     }
743 
744     return result;
745 }
746 
ParseAudioCapturerFilter(napi_env env,napi_value root,sptr<AudioCapturerFilter> & audioCapturerFilter)747 static void ParseAudioCapturerFilter(napi_env env, napi_value root, sptr<AudioCapturerFilter> &audioCapturerFilter)
748 {
749     napi_value tempValue = nullptr;
750     int32_t intValue = {0};
751 
752     audioCapturerFilter = new(std::nothrow) AudioCapturerFilter();
753     if (napi_get_named_property(env, root, "uid", &tempValue) == napi_ok) {
754         napi_get_value_int32(env, tempValue, &intValue);
755         audioCapturerFilter->uid = intValue;
756     }
757 }
758 
SelectInputDeviceAsyncCallbackComplete(napi_env env,napi_status status,void * data)759 static void SelectInputDeviceAsyncCallbackComplete(napi_env env, napi_status status, void *data)
760 {
761     auto asyncContext = static_cast<AudioRoutingManagerAsyncContext*>(data);
762     napi_value valueParam = nullptr;
763 
764     if (asyncContext != nullptr) {
765         if (!asyncContext->status) {
766             napi_get_undefined(env, &valueParam);
767         }
768         CommonCallbackRoutine(env, asyncContext, valueParam);
769     } else {
770         HiLog::Error(LABEL, "ERROR: AudioRoutingManagerAsyncContext* is Null!");
771     }
772 }
773 
SelectInputDevice(napi_env env,napi_callback_info info)774 napi_value AudioRoutingManagerNapi::SelectInputDevice(napi_env env, napi_callback_info info)
775 {
776     napi_status status;
777     const int32_t refCount = 1;
778     napi_value result = nullptr;
779     size_t argc = ARGS_TWO;
780     napi_value argv[ARGS_TWO] = {0};
781     napi_value thisVar = nullptr;
782     void *data = nullptr;
783     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
784 
785     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
786 
787     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
788     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
789         if (argc < ARGS_ONE) {
790             asyncContext->status = NAPI_ERR_INVALID_PARAM;
791         }
792         for (size_t i = PARAM0; i < argc; i++) {
793             napi_valuetype valueType = napi_undefined;
794             napi_typeof(env, argv[i], &valueType);
795             if (i == PARAM0 && valueType == napi_object) {
796                 ParseAudioDeviceDescriptorVector(env, argv[i], asyncContext->deviceDescriptors,
797                     asyncContext->bArgTransFlag);
798             } else if (i == PARAM1) {
799                 if (valueType == napi_function) {
800                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
801                 }
802                 break;
803             } else {
804                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
805             }
806 
807             if (!asyncContext->bArgTransFlag) {
808                 break;
809             }
810         }
811 
812         if (asyncContext->callbackRef == nullptr) {
813             napi_create_promise(env, &asyncContext->deferred, &result);
814         } else {
815             napi_get_undefined(env, &result);
816         }
817 
818         napi_value resource = nullptr;
819         napi_create_string_utf8(env, "SelectInputDevice", NAPI_AUTO_LENGTH, &resource);
820 
821         status = napi_create_async_work(
822             env, nullptr, resource,
823             [](napi_env env, void *data) {
824                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
825                 if (context->bArgTransFlag) {
826                     context->status = context->objectInfo->audioMngr_->SelectInputDevice(context->deviceDescriptors);
827                 } else {
828                     context->status = ERR_INVALID_PARAM;
829                 }
830             },
831             SelectInputDeviceAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
832         if (status != napi_ok) {
833             result = nullptr;
834         } else {
835             status = napi_queue_async_work(env, asyncContext->work);
836             if (status == napi_ok) {
837                 asyncContext.release();
838             } else {
839                 result = nullptr;
840             }
841         }
842     }
843 
844     return result;
845 }
846 
SelectInputDeviceByFilter(napi_env env,napi_callback_info info)847 napi_value AudioRoutingManagerNapi::SelectInputDeviceByFilter(napi_env env, napi_callback_info info)
848 {
849     napi_status status;
850     const int32_t refCount = 1;
851     napi_value result = nullptr;
852 
853     size_t argc = ARGS_THREE;
854     napi_value argv[ARGS_TWO] = {0};
855     napi_value thisVar = nullptr;
856     void *data = nullptr;
857     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
858     NAPI_ASSERT(env, argc >= ARGS_THREE, "requires 2 parameters minimum");
859 
860     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
861 
862     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
863     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
864         if (argc < ARGS_TWO) {
865             asyncContext->status = NAPI_ERR_INVALID_PARAM;
866         }
867         for (size_t i = PARAM0; i < argc; i++) {
868             napi_valuetype valueType = napi_undefined;
869             napi_typeof(env, argv[i], &valueType);
870             if (i == PARAM0 && valueType == napi_object) {
871                 ParseAudioCapturerFilter(env, argv[i], asyncContext->audioCapturerFilter);
872             } else if (i == PARAM1 && valueType == napi_object) {
873                 ParseAudioDeviceDescriptorVector(env, argv[i], asyncContext->deviceDescriptors,
874                     asyncContext->bArgTransFlag);
875             } else if (i == PARAM2) {
876                 if (valueType == napi_function) {
877                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
878                 }
879                 break;
880             } else {
881                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
882             }
883 
884             if (!asyncContext->bArgTransFlag) {
885                 break;
886             }
887         }
888 
889         if (asyncContext->callbackRef == nullptr) {
890             napi_create_promise(env, &asyncContext->deferred, &result);
891         } else {
892             napi_get_undefined(env, &result);
893         }
894 
895         napi_value resource = nullptr;
896         napi_create_string_utf8(env, "SelectInputDeviceByFilter", NAPI_AUTO_LENGTH, &resource);
897 
898         status = napi_create_async_work(
899             env, nullptr, resource,
900             [](napi_env env, void *data) {
901                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
902                 if (context->bArgTransFlag) {
903                     context->status = context->objectInfo->audioMngr_->SelectInputDevice(
904                         context->audioCapturerFilter, context->deviceDescriptors);
905                 } else {
906                     context->status = context->status ==
907                         NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED;
908                 }
909             },
910             SelectInputDeviceAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
911         if (status != napi_ok) {
912             result = nullptr;
913         } else {
914             status = napi_queue_async_work(env, asyncContext->work);
915             if (status == napi_ok) {
916                 asyncContext.release();
917             } else {
918                 result = nullptr;
919             }
920         }
921     }
922 
923     return result;
924 }
925 
RegisterDeviceChangeCallback(napi_env env,napi_value * args,const std::string & cbName,int32_t flag,AudioRoutingManagerNapi * routingMgrNapi)926 void AudioRoutingManagerNapi::RegisterDeviceChangeCallback(napi_env env, napi_value* args,
927     const std::string& cbName, int32_t flag, AudioRoutingManagerNapi* routingMgrNapi)
928 {
929     if (!routingMgrNapi->deviceChangeCallbackNapi_) {
930         routingMgrNapi->deviceChangeCallbackNapi_= std::make_shared<AudioManagerCallbackNapi>(env);
931         if (!routingMgrNapi->deviceChangeCallbackNapi_) {
932             AUDIO_ERR_LOG("AudioStreamMgrNapi: Memory Allocation Failed !!");
933             return;
934         }
935         DeviceFlag deviceFlag = DeviceFlag(flag);
936 
937         int32_t ret = routingMgrNapi->audioMngr_->SetDeviceChangeCallback(deviceFlag,
938             routingMgrNapi->deviceChangeCallbackNapi_);
939         if (ret) {
940             AUDIO_ERR_LOG("AudioRoutingMgrNapi: Registering Device Change Callback Failed");
941             return;
942         }
943     }
944 
945     std::shared_ptr<AudioManagerCallbackNapi> cb =
946         std::static_pointer_cast<AudioManagerCallbackNapi>(routingMgrNapi->deviceChangeCallbackNapi_);
947     cb->SaveCallbackReference(cbName, args[PARAM2]);
948 
949     AUDIO_INFO_LOG("AudioRoutingManager::On SetDeviceChangeCallback is successful");
950 }
951 
RegisterCallback(napi_env env,napi_value jsThis,napi_value * args,const std::string & cbName,int32_t flag)952 void AudioRoutingManagerNapi::RegisterCallback(napi_env env, napi_value jsThis,
953     napi_value* args, const std::string& cbName, int32_t flag)
954 {
955     AudioRoutingManagerNapi* routingMgrNapi = nullptr;
956     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void**>(&routingMgrNapi));
957     if ((status != napi_ok) || (routingMgrNapi == nullptr) || (routingMgrNapi->audioMngr_ == nullptr)
958         || (routingMgrNapi->audioRoutingMngr_ == nullptr)) {
959         AUDIO_ERR_LOG("AudioRoutingMgrNapi::Failed to retrieve stream mgr napi instance.");
960 
961         return;
962     }
963 
964     if (!cbName.compare(DEVICE_CHANGE_CALLBACK_NAME)) {
965         RegisterDeviceChangeCallback(env, args, cbName, flag, routingMgrNapi);
966     } else {
967         AUDIO_ERR_LOG("AudioRoutingMgrNapi::No such supported");
968         AudioCommonNapi::throwError(env, NAPI_ERR_INVALID_PARAM);
969     }
970 }
971 
On(napi_env env,napi_callback_info info)972 napi_value AudioRoutingManagerNapi::On(napi_env env, napi_callback_info info)
973 {
974     AUDIO_INFO_LOG("audioRoutingManagerNapi: On inter");
975 
976     const size_t requireArgc = PARAM2;
977     const size_t maxArgc = PARAM3;
978     size_t argc = PARAM3;
979 
980     napi_value undefinedResult = nullptr;
981     napi_get_undefined(env, &undefinedResult);
982 
983     napi_value args[requireArgc + 1] = { nullptr, nullptr, nullptr };
984     napi_value jsThis = nullptr;
985     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
986     bool isArgcCountRight = argc == requireArgc || argc == maxArgc;
987     THROW_ERROR_ASSERT(env, status == napi_ok && isArgcCountRight, NAPI_ERR_INPUT_INVALID);
988 
989     napi_valuetype eventType = napi_undefined;
990     napi_typeof(env, args[0], &eventType);
991     THROW_ERROR_ASSERT(env, eventType == napi_string, NAPI_ERR_INPUT_INVALID);
992     std::string callbackName = AudioCommonNapi::GetStringArgument(env, args[0]);
993     AUDIO_INFO_LOG("AaudioRoutingManagerNapi: On callbackName: %{public}s", callbackName.c_str());
994 
995     int32_t deviceFlag;
996 
997     if (argc == requireArgc) {
998         napi_valuetype handler = napi_undefined;
999         napi_typeof(env, args[1], &handler);
1000         THROW_ERROR_ASSERT(env, handler == napi_function, NAPI_ERR_INPUT_INVALID);
1001         deviceFlag = 3; // 3 for ALL_DEVICES_FLAG
1002     }
1003     if (argc == maxArgc) {
1004         napi_valuetype valueType = napi_undefined;
1005         napi_typeof(env, args[PARAM1], &valueType);
1006         if (valueType == napi_number) {
1007             napi_get_value_int32(env, args[PARAM1], &deviceFlag);
1008             AUDIO_INFO_LOG("AudioRoutingMgrNapi:On deviceFlag: %{public}d", deviceFlag);
1009             if (!AudioCommonNapi::IsLegalInputArgumentDeviceFlag(deviceFlag)) {
1010                 THROW_ERROR_ASSERT(env, false, NAPI_ERR_INVALID_PARAM);
1011             }
1012         } else {
1013             THROW_ERROR_ASSERT(env, false, NAPI_ERR_INPUT_INVALID);
1014         }
1015 
1016         napi_valuetype handler = napi_undefined;
1017         napi_typeof(env, args[PARAM2], &handler);
1018         THROW_ERROR_ASSERT(env, handler == napi_function, NAPI_ERR_INPUT_INVALID);
1019     }
1020 
1021     RegisterCallback(env, jsThis, args, callbackName, deviceFlag);
1022 
1023     return undefinedResult;
1024 }
1025 
Off(napi_env env,napi_callback_info info)1026 napi_value AudioRoutingManagerNapi::Off(napi_env env, napi_callback_info info)
1027 {
1028     napi_value undefinedResult = nullptr;
1029     napi_get_undefined(env, &undefinedResult);
1030 
1031     const size_t minArgCount = 1;
1032     size_t argCount = 3;
1033     napi_value args[minArgCount + 2] = {nullptr, nullptr, nullptr};
1034     napi_value jsThis = nullptr;
1035     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
1036     if (status != napi_ok || argCount < minArgCount) {
1037         AUDIO_ERR_LOG("Off fail to napi_get_cb_info/Requires min 1 parameters");
1038         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
1039         return undefinedResult;
1040     }
1041 
1042     napi_valuetype eventType = napi_undefined;
1043     if (napi_typeof(env, args[PARAM0], &eventType) != napi_ok || eventType != napi_string) {
1044         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
1045         return undefinedResult;
1046     }
1047     std::string callbackName = AudioCommonNapi::GetStringArgument(env, args[0]);
1048     AUDIO_INFO_LOG("AudioManagerNapi::Off callbackName: %{public}s", callbackName.c_str());
1049 
1050     AudioRoutingManagerNapi* routingMgrNapi = nullptr;
1051     status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&routingMgrNapi));
1052     NAPI_ASSERT(env, status == napi_ok && routingMgrNapi != nullptr, "Failed to retrieve audio mgr napi instance.");
1053     NAPI_ASSERT(env, routingMgrNapi->audioMngr_ != nullptr, "audio system mgr instance is null.");
1054 
1055     if (!callbackName.compare(DEVICE_CHANGE_CALLBACK_NAME)) {
1056         int32_t ret = routingMgrNapi->audioMngr_->UnsetDeviceChangeCallback();
1057         if (ret) {
1058             AUDIO_ERR_LOG("AudioManagerNapi::Off UnsetDeviceChangeCallback Failed");
1059             return undefinedResult;
1060         }
1061         if (routingMgrNapi->deviceChangeCallbackNapi_ != nullptr) {
1062             routingMgrNapi->deviceChangeCallbackNapi_.reset();
1063             routingMgrNapi->deviceChangeCallbackNapi_ = nullptr;
1064         }
1065         AUDIO_INFO_LOG("AudioManagerNapi::Off UnsetDeviceChangeCallback Success");
1066     } else {
1067         AUDIO_ERR_LOG("AudioRoutingMgrNapi:: off no such supported");
1068         AudioCommonNapi::throwError(env, NAPI_ERR_INVALID_PARAM);
1069     }
1070     return undefinedResult;
1071 }
1072 
SetCommunicationDevice(napi_env env,napi_callback_info info)1073 napi_value AudioRoutingManagerNapi::SetCommunicationDevice(napi_env env, napi_callback_info info)
1074 {
1075     napi_status status;
1076     const int32_t refCount = 1;
1077     napi_value result = nullptr;
1078 
1079     GET_PARAMS(env, info, ARGS_THREE);
1080 
1081     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
1082 
1083     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1084     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1085         if (argc < ARGS_TWO) {
1086             asyncContext->status = NAPI_ERR_INVALID_PARAM;
1087         }
1088         for (size_t i = PARAM0; i < argc; i++) {
1089             napi_valuetype valueType = napi_undefined;
1090             napi_typeof(env, argv[i], &valueType);
1091 
1092             if (i == PARAM0 && valueType == napi_number) {
1093                 napi_get_value_int32(env, argv[i], &asyncContext->deviceType);
1094                 if (!AudioCommonNapi::IsLegalInputArgumentCommunicationDeviceType(asyncContext->deviceType)) {
1095                 asyncContext->status = asyncContext->status ==
1096                     NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED;
1097                 }
1098             } else if (i == PARAM1 && valueType == napi_boolean) {
1099                 napi_get_value_bool(env, argv[i], &asyncContext->isActive);
1100             } else if (i == PARAM2) {
1101                 if (valueType == napi_function) {
1102                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
1103                 }
1104                 break;
1105             } else {
1106                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
1107             }
1108         }
1109 
1110         if (asyncContext->callbackRef == nullptr) {
1111             napi_create_promise(env, &asyncContext->deferred, &result);
1112         } else {
1113             napi_get_undefined(env, &result);
1114         }
1115 
1116         napi_value resource = nullptr;
1117         napi_create_string_utf8(env, "SetCommunicationDeviceActive", NAPI_AUTO_LENGTH, &resource);
1118 
1119         status = napi_create_async_work(
1120             env, nullptr, resource,
1121             [](napi_env env, void *data) {
1122                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
1123                 if (context->status == 0) {
1124                     context->status = context->objectInfo->audioMngr_->SetDeviceActive(
1125                         static_cast<ActiveDeviceType>(context->deviceType), context->isActive);
1126                 }
1127             },
1128             SetFunctionAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1129         if (status != napi_ok) {
1130             result = nullptr;
1131         } else {
1132             status = napi_queue_async_work(env, asyncContext->work);
1133             if (status == napi_ok) {
1134                 asyncContext.release();
1135             } else {
1136                 result = nullptr;
1137             }
1138         }
1139     }
1140 
1141     return result;
1142 }
1143 
IsCommunicationDeviceActive(napi_env env,napi_callback_info info)1144 napi_value AudioRoutingManagerNapi::IsCommunicationDeviceActive(napi_env env, napi_callback_info info)
1145 {
1146     napi_status status;
1147     const int32_t refCount = 1;
1148     napi_value result = nullptr;
1149 
1150     GET_PARAMS(env, info, ARGS_TWO);
1151 
1152     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
1153 
1154     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1155     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1156         if (argc < ARGS_ONE) {
1157             asyncContext->status = NAPI_ERR_INVALID_PARAM;
1158         }
1159         for (size_t i = PARAM0; i < argc; i++) {
1160             napi_valuetype valueType = napi_undefined;
1161             napi_typeof(env, argv[i], &valueType);
1162 
1163             if (i == PARAM0 && valueType == napi_number) {
1164                 napi_get_value_int32(env, argv[i], &asyncContext->deviceType);
1165                 if (!AudioCommonNapi::IsLegalInputArgumentActiveDeviceType(asyncContext->deviceType)) {
1166                     asyncContext->status = asyncContext->status ==
1167                         NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED;
1168                 }
1169             } else if (i == PARAM1) {
1170                 if (valueType == napi_function) {
1171                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
1172                 }
1173                 break;
1174             } else {
1175                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
1176             }
1177         }
1178 
1179         if (asyncContext->callbackRef == nullptr) {
1180             napi_create_promise(env, &asyncContext->deferred, &result);
1181         } else {
1182             napi_get_undefined(env, &result);
1183         }
1184 
1185         napi_value resource = nullptr;
1186         napi_create_string_utf8(env, "IsCommunicationDeviceActive", NAPI_AUTO_LENGTH, &resource);
1187 
1188         status = napi_create_async_work(
1189             env, nullptr, resource,
1190             [](napi_env env, void *data) {
1191                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
1192                 if (context->status == SUCCESS) {
1193                     context->isActive = context->objectInfo->audioMngr_->
1194                         IsDeviceActive(static_cast<ActiveDeviceType>(context->deviceType));
1195                     context->isTrue = context->isActive;
1196                     context->status = 0;
1197                 }
1198             },
1199             IsTrueAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1200         if (status != napi_ok) {
1201             result = nullptr;
1202         } else {
1203             status = napi_queue_async_work(env, asyncContext->work);
1204             if (status == napi_ok) {
1205                 asyncContext.release();
1206             } else {
1207                 result = nullptr;
1208             }
1209         }
1210     }
1211 
1212     return result;
1213 }
1214 
1215 } // namespace AudioStandard
1216 } // namespace OHOS
1217