• 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_routing_manager_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     AudioRendererInfo rendererInfo;
59     AudioCapturerInfo captureInfo;
60     sptr<AudioRendererFilter> audioRendererFilter;
61     sptr<AudioCapturerFilter> audioCapturerFilter;
62     vector<sptr<AudioDeviceDescriptor>> deviceDescriptors;
63     vector<sptr<AudioDeviceDescriptor>> outDeviceDescriptors;
64     vector<sptr<AudioDeviceDescriptor>> inputDeviceDescriptors;
65 };
66 
AudioRoutingManagerNapi()67 AudioRoutingManagerNapi::AudioRoutingManagerNapi()
68     : audioMngr_(nullptr), env_(nullptr) {}
69 
70 AudioRoutingManagerNapi::~AudioRoutingManagerNapi() = default;
71 
Destructor(napi_env env,void * nativeObject,void * finalize_hint)72 void AudioRoutingManagerNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
73 {
74     if (nativeObject != nullptr) {
75         auto obj = static_cast<AudioRoutingManagerNapi *>(nativeObject);
76         delete obj;
77         obj = nullptr;
78     }
79 }
80 
Init(napi_env env,napi_value exports)81 napi_value AudioRoutingManagerNapi::Init(napi_env env, napi_value exports)
82 {
83     AUDIO_INFO_LOG("Init");
84     napi_status status;
85     napi_value constructor;
86     napi_value result = nullptr;
87     const int32_t refCount = 1;
88     napi_get_undefined(env, &result);
89 
90     napi_property_descriptor audio_routing_manager_properties[] = {
91         DECLARE_NAPI_FUNCTION("getDevices", GetDevices),
92         DECLARE_NAPI_FUNCTION("getDevicesSync", GetDevicesSync),
93         DECLARE_NAPI_FUNCTION("on", AudioRoutingManagerNapi::On),
94         DECLARE_NAPI_FUNCTION("off", AudioRoutingManagerNapi::Off),
95         DECLARE_NAPI_FUNCTION("selectOutputDevice", SelectOutputDevice),
96         DECLARE_NAPI_FUNCTION("selectOutputDeviceByFilter", SelectOutputDeviceByFilter),
97         DECLARE_NAPI_FUNCTION("selectInputDevice", SelectInputDevice),
98         DECLARE_NAPI_FUNCTION("selectInputDeviceByFilter", SelectInputDeviceByFilter),
99         DECLARE_NAPI_FUNCTION("setCommunicationDevice", SetCommunicationDevice),
100         DECLARE_NAPI_FUNCTION("isCommunicationDeviceActive", IsCommunicationDeviceActive),
101         DECLARE_NAPI_FUNCTION("isCommunicationDeviceActiveSync", IsCommunicationDeviceActiveSync),
102         DECLARE_NAPI_FUNCTION("getActiveOutputDeviceDescriptors", GetActiveOutputDeviceDescriptors),
103         DECLARE_NAPI_FUNCTION("getPreferredOutputDeviceForRendererInfo", GetPreferredOutputDeviceForRendererInfo),
104         DECLARE_NAPI_FUNCTION("getPreferOutputDeviceForRendererInfo", GetPreferOutputDeviceForRendererInfo),
105         DECLARE_NAPI_FUNCTION("getPreferredOutputDeviceForRendererInfoSync",
106             GetPreferredOutputDeviceForRendererInfoSync),
107         DECLARE_NAPI_FUNCTION("getPreferredInputDeviceForCapturerInfo", GetPreferredInputDeviceForCapturerInfo),
108         DECLARE_NAPI_FUNCTION("getPreferredInputDeviceForCapturerInfoSync", GetPreferredInputDeviceForCapturerInfoSync),
109     };
110 
111     status = napi_define_class(env, AUDIO_ROUTING_MANAGER_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct, nullptr,
112         sizeof(audio_routing_manager_properties) / sizeof(audio_routing_manager_properties[PARAM0]),
113         audio_routing_manager_properties, &constructor);
114     if (status != napi_ok) {
115         return result;
116     }
117     status = napi_create_reference(env, constructor, refCount, &g_routingManagerConstructor);
118     if (status == napi_ok) {
119         status = napi_set_named_property(env, exports, AUDIO_ROUTING_MANAGER_NAPI_CLASS_NAME.c_str(), constructor);
120         if (status == napi_ok) {
121             return exports;
122         }
123     }
124 
125     HiLog::Error(LABEL, "Failure in AudioRoutingManagerNapi::Init()");
126     return result;
127 }
128 
CreateRoutingManagerWrapper(napi_env env)129 napi_value AudioRoutingManagerNapi::CreateRoutingManagerWrapper(napi_env env)
130 {
131     napi_status status;
132     napi_value result = nullptr;
133     napi_value constructor;
134 
135     status = napi_get_reference_value(env, g_routingManagerConstructor, &constructor);
136     if (status == napi_ok) {
137         status = napi_new_instance(env, constructor, 0, nullptr, &result);
138         if (status == napi_ok) {
139             return result;
140         }
141     }
142     HiLog::Error(LABEL, "Failed in AudioRoutingManagerNapi::CreateRoutingManagerWrapper!");
143     napi_get_undefined(env, &result);
144 
145     return result;
146 }
147 
Construct(napi_env env,napi_callback_info info)148 napi_value AudioRoutingManagerNapi::Construct(napi_env env, napi_callback_info info)
149 {
150     AUDIO_INFO_LOG("Construct");
151     napi_status status;
152     napi_value result = nullptr;
153     napi_get_undefined(env, &result);
154 
155     size_t argc = ARGS_TWO;
156     napi_value argv[ARGS_TWO] = {0};
157     napi_value thisVar = nullptr;
158     void *data = nullptr;
159     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
160     unique_ptr<AudioRoutingManagerNapi> audioRoutingManagerNapi = make_unique<AudioRoutingManagerNapi>();
161     CHECK_AND_RETURN_RET_LOG(audioRoutingManagerNapi != nullptr, result, "No memory");
162 
163     audioRoutingManagerNapi->audioMngr_ = AudioSystemManager::GetInstance();
164 
165     audioRoutingManagerNapi->audioRoutingMngr_ = AudioRoutingManager::GetInstance();
166 
167     audioRoutingManagerNapi->env_ = env;
168 
169     status = napi_wrap(env, thisVar, static_cast<void*>(audioRoutingManagerNapi.get()),
170         AudioRoutingManagerNapi::Destructor, nullptr, nullptr);
171     if (status == napi_ok) {
172         audioRoutingManagerNapi.release();
173         return thisVar;
174     }
175 
176     HiLog::Error(LABEL, "Failed in AudioRoutingManager::Construct()!");
177     return result;
178 }
179 
CommonCallbackRoutine(napi_env env,AudioRoutingManagerAsyncContext * & asyncContext,const napi_value & valueParam)180 static void CommonCallbackRoutine(napi_env env, AudioRoutingManagerAsyncContext *&asyncContext,
181     const napi_value &valueParam)
182 {
183     napi_value result[ARGS_TWO] = {0};
184     napi_value retVal;
185 
186     if (!asyncContext->status) {
187         napi_get_undefined(env, &result[PARAM0]);
188         result[PARAM1] = valueParam;
189     } else {
190         napi_value message = nullptr;
191         std::string messageValue = AudioCommonNapi::getMessageByCode(asyncContext->status);
192         napi_create_string_utf8(env, messageValue.c_str(), NAPI_AUTO_LENGTH, &message);
193 
194         napi_value code = nullptr;
195         napi_create_string_utf8(env, (std::to_string(asyncContext->status)).c_str(), NAPI_AUTO_LENGTH, &code);
196 
197         napi_create_error(env, code, message, &result[PARAM0]);
198         napi_get_undefined(env, &result[PARAM1]);
199     }
200 
201     if (asyncContext->deferred) {
202         if (!asyncContext->status) {
203             napi_resolve_deferred(env, asyncContext->deferred, result[PARAM1]);
204         } else {
205             napi_reject_deferred(env, asyncContext->deferred, result[PARAM0]);
206         }
207     } else {
208         napi_value callback = nullptr;
209         napi_get_reference_value(env, asyncContext->callbackRef, &callback);
210         napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
211         napi_delete_reference(env, asyncContext->callbackRef);
212     }
213     napi_delete_async_work(env, asyncContext->work);
214 
215     delete asyncContext;
216     asyncContext = nullptr;
217 }
218 
SetFunctionAsyncCallbackComplete(napi_env env,napi_status status,void * data)219 static void SetFunctionAsyncCallbackComplete(napi_env env, napi_status status, void *data)
220 {
221     auto asyncContext = static_cast<AudioRoutingManagerAsyncContext*>(data);
222     napi_value valueParam = nullptr;
223 
224     if (asyncContext != nullptr) {
225         if (!asyncContext->status) {
226             napi_get_undefined(env, &valueParam);
227         }
228         CommonCallbackRoutine(env, asyncContext, valueParam);
229     } else {
230         HiLog::Error(LABEL, "ERROR: AudioManagerAsyncContext* is Null!");
231     }
232 }
233 
IsTrueAsyncCallbackComplete(napi_env env,napi_status status,void * data)234 static void IsTrueAsyncCallbackComplete(napi_env env, napi_status status, void *data)
235 {
236     auto asyncContext = static_cast<AudioRoutingManagerAsyncContext*>(data);
237     napi_value valueParam = nullptr;
238 
239     if (asyncContext != nullptr) {
240         if (!asyncContext->status) {
241             napi_get_boolean(env, asyncContext->isTrue, &valueParam);
242         }
243         CommonCallbackRoutine(env, asyncContext, valueParam);
244     } else {
245         HiLog::Error(LABEL, "ERROR: AudioManagerAsyncContext* is Null!");
246     }
247 }
248 
ParseAudioRendererInfo(napi_env env,napi_value root,AudioRendererInfo * rendererInfo)249 static void ParseAudioRendererInfo(napi_env env, napi_value root, AudioRendererInfo *rendererInfo)
250 {
251     napi_value tempValue = nullptr;
252     int32_t intValue = {0};
253 
254     if (napi_get_named_property(env, root, "content", &tempValue) == napi_ok) {
255         napi_get_value_int32(env, tempValue, &intValue);
256         rendererInfo->contentType = static_cast<ContentType>(intValue);
257     }
258 
259     if (napi_get_named_property(env, root, "usage", &tempValue) == napi_ok) {
260         napi_get_value_int32(env, tempValue, &intValue);
261         rendererInfo->streamUsage = static_cast<StreamUsage>(intValue);
262     }
263 
264     if (napi_get_named_property(env, root, "rendererFlags", &tempValue) == napi_ok) {
265         napi_get_value_int32(env, tempValue, &(rendererInfo->rendererFlags));
266     }
267 }
268 
269 
ParseAudioRendererFilter(napi_env env,napi_value root,sptr<AudioRendererFilter> & audioRendererFilter,bool & argTransFlag)270 static void ParseAudioRendererFilter(napi_env env, napi_value root,
271     sptr<AudioRendererFilter> &audioRendererFilter, bool &argTransFlag)
272 {
273     napi_value tempValue = nullptr;
274     int32_t intValue = {0};
275     argTransFlag = true;
276     audioRendererFilter = new(std::nothrow) AudioRendererFilter();
277 
278     if (napi_get_named_property(env, root, "uid", &tempValue) == napi_ok) {
279         napi_get_value_int32(env, tempValue, &intValue);
280         audioRendererFilter->uid = intValue;
281     }
282 
283     if (napi_get_named_property(env, root, "rendererInfo", &tempValue) == napi_ok) {
284         ParseAudioRendererInfo(env, tempValue, &(audioRendererFilter->rendererInfo));
285     }
286 
287     if (napi_get_named_property(env, root, "rendererId", &tempValue) == napi_ok) {
288         napi_get_value_int32(env, tempValue, &intValue);
289         audioRendererFilter->streamId = intValue;
290     }
291 }
292 
ParseAudioDeviceDescriptor(napi_env env,napi_value root,sptr<AudioDeviceDescriptor> & selectedAudioDevice,bool & argTransFlag)293 static void ParseAudioDeviceDescriptor(napi_env env, napi_value root,
294     sptr<AudioDeviceDescriptor> &selectedAudioDevice, bool &argTransFlag)
295 {
296     napi_value tempValue = nullptr;
297     int32_t intValue = {0};
298     char buffer[SIZE];
299     size_t res = 0;
300     argTransFlag = true;
301     bool hasDeviceRole = true;
302     bool hasNetworkId  = true;
303     napi_has_named_property(env, root, "deviceRole", &hasDeviceRole);
304     napi_has_named_property(env, root, "networkId", &hasNetworkId);
305 
306     if ((!hasDeviceRole) || (!hasNetworkId)) {
307         argTransFlag = false;
308         return;
309     }
310 
311     if (napi_get_named_property(env, root, "deviceRole", &tempValue) == napi_ok) {
312         napi_get_value_int32(env, tempValue, &intValue);
313         selectedAudioDevice->deviceRole_ = static_cast<DeviceRole>(intValue);
314     }
315 
316     if (napi_get_named_property(env, root, "deviceType", &tempValue) == napi_ok) {
317         napi_get_value_int32(env, tempValue, &intValue);
318         selectedAudioDevice->deviceType_ = static_cast<DeviceType>(intValue);
319     }
320 
321     if (napi_get_named_property(env, root, "networkId", &tempValue) == napi_ok) {
322         napi_get_value_string_utf8(env, tempValue, buffer, SIZE, &res);
323         selectedAudioDevice->networkId_ = std::string(buffer);
324     }
325 
326     if (napi_get_named_property(env, root, "displayName", &tempValue) == napi_ok) {
327         napi_get_value_string_utf8(env, tempValue, buffer, SIZE, &res);
328         selectedAudioDevice->displayName_ = std::string(buffer);
329     }
330 
331     if (napi_get_named_property(env, root, "interruptGroupId", &tempValue) == napi_ok) {
332         napi_get_value_int32(env, tempValue, &intValue);
333         selectedAudioDevice->interruptGroupId_ = intValue;
334     }
335 
336     if (napi_get_named_property(env, root, "volumeGroupId", &tempValue) == napi_ok) {
337         napi_get_value_int32(env, tempValue, &intValue);
338         selectedAudioDevice->volumeGroupId_ = intValue;
339     }
340 }
341 
ParseAudioDeviceDescriptorVector(napi_env env,napi_value root,vector<sptr<AudioDeviceDescriptor>> & deviceDescriptorsVector,bool & argTransFlag)342 static void ParseAudioDeviceDescriptorVector(napi_env env, napi_value root,
343     vector<sptr<AudioDeviceDescriptor>> &deviceDescriptorsVector, bool &argTransFlag)
344 {
345     uint32_t arrayLen = 0;
346     napi_get_array_length(env, root, &arrayLen);
347     if (arrayLen == 0) {
348         deviceDescriptorsVector = {};
349         AUDIO_INFO_LOG("Error: AudioDeviceDescriptor vector is NULL!");
350     }
351 
352     for (size_t i = 0; i < arrayLen; i++) {
353         napi_value element;
354         napi_get_element(env, root, i, &element);
355         sptr<AudioDeviceDescriptor> selectedAudioDevice = new(std::nothrow) AudioDeviceDescriptor();
356         ParseAudioDeviceDescriptor(env, element, selectedAudioDevice, argTransFlag);
357         if (!argTransFlag) {
358             return;
359         }
360         deviceDescriptorsVector.push_back(selectedAudioDevice);
361     }
362 }
363 
364 
SelectOutputDeviceAsyncCallbackComplete(napi_env env,napi_status status,void * data)365 static void SelectOutputDeviceAsyncCallbackComplete(napi_env env, napi_status status, void *data)
366 {
367     auto asyncContext = static_cast<AudioRoutingManagerAsyncContext*>(data);
368     napi_value valueParam = nullptr;
369 
370     if (asyncContext != nullptr) {
371         if (!asyncContext->status) {
372             napi_get_undefined(env, &valueParam);
373         }
374         CommonCallbackRoutine(env, asyncContext, valueParam);
375     } else {
376         HiLog::Error(LABEL, "ERROR: AudioRoutingManagerAsyncContext* is Null!");
377     }
378 }
379 
SetValueInt32(const napi_env & env,const std::string & fieldStr,const int intValue,napi_value & result)380 static void SetValueInt32(const napi_env& env, const std::string& fieldStr, const int intValue, napi_value& result)
381 {
382     napi_value value = nullptr;
383     napi_create_int32(env, intValue, &value);
384     napi_set_named_property(env, result, fieldStr.c_str(), value);
385 }
386 
SetValueString(const napi_env & env,const std::string & fieldStr,const std::string stringValue,napi_value & result)387 static void SetValueString(const napi_env& env, const std::string& fieldStr, const std::string stringValue,
388     napi_value& result)
389 {
390     napi_value value = nullptr;
391     napi_create_string_utf8(env, stringValue.c_str(), NAPI_AUTO_LENGTH, &value);
392     napi_set_named_property(env, result, fieldStr.c_str(), value);
393 }
394 
SetDeviceDescriptor(const napi_env & env,napi_value & valueParam,const AudioDeviceDescriptor & deviceInfo)395 static void SetDeviceDescriptor(const napi_env& env, napi_value &valueParam, const AudioDeviceDescriptor &deviceInfo)
396 {
397     SetValueInt32(env, "deviceRole", static_cast<int32_t>(deviceInfo.deviceRole_), valueParam);
398     SetValueInt32(env, "deviceType", static_cast<int32_t>(deviceInfo.deviceType_), valueParam);
399     SetValueInt32(env, "id", static_cast<int32_t>(deviceInfo.deviceId_), valueParam);
400     SetValueString(env, "name", deviceInfo.deviceName_, valueParam);
401     SetValueString(env, "address", deviceInfo.macAddress_, valueParam);
402     SetValueString(env, "networkId", deviceInfo.networkId_, valueParam);
403     SetValueString(env, "displayName", deviceInfo.displayName_, valueParam);
404     SetValueInt32(env, "interruptGroupId", static_cast<int32_t>(deviceInfo.interruptGroupId_), valueParam);
405     SetValueInt32(env, "volumeGroupId", static_cast<int32_t>(deviceInfo.volumeGroupId_), valueParam);
406 
407     napi_value value = nullptr;
408     napi_value sampleRates;
409     napi_create_array_with_length(env, 1, &sampleRates);
410     napi_create_int32(env, deviceInfo.audioStreamInfo_.samplingRate, &value);
411     napi_set_element(env, sampleRates, 0, value);
412     napi_set_named_property(env, valueParam, "sampleRates", sampleRates);
413 
414     napi_value channelCounts;
415     napi_create_array_with_length(env, 1, &channelCounts);
416     napi_create_int32(env, deviceInfo.audioStreamInfo_.channels, &value);
417     napi_set_element(env, channelCounts, 0, value);
418     napi_set_named_property(env, valueParam, "channelCounts", channelCounts);
419 
420     napi_value channelMasks;
421     napi_create_array_with_length(env, 1, &channelMasks);
422     napi_create_int32(env, deviceInfo.channelMasks_, &value);
423     napi_set_element(env, channelMasks, 0, value);
424     napi_set_named_property(env, valueParam, "channelMasks", channelMasks);
425 
426     napi_value encodingTypes;
427     napi_create_array_with_length(env, 1, &encodingTypes);
428     napi_create_int32(env, deviceInfo.audioStreamInfo_.encoding, &value);
429     napi_set_element(env, encodingTypes, 0, value);
430     napi_set_named_property(env, valueParam, "encodingTypes", encodingTypes);
431 }
432 
SetDeviceDescriptors(const napi_env & env,napi_value & result,napi_value & valueParam,const vector<sptr<AudioDeviceDescriptor>> deviceDescriptors)433 static void SetDeviceDescriptors(const napi_env &env, napi_value &result, napi_value &valueParam,
434     const vector<sptr<AudioDeviceDescriptor>> deviceDescriptors)
435 {
436     napi_create_array_with_length(env, deviceDescriptors.size(), &result);
437     for (size_t i = 0; i < deviceDescriptors.size(); i++) {
438         if (deviceDescriptors[i] != nullptr) {
439             (void)napi_create_object(env, &valueParam);
440             SetDeviceDescriptor(env, valueParam, deviceDescriptors[i]);
441             napi_set_element(env, result, i, valueParam);
442         }
443     }
444 }
445 
SetDevicesInfo(vector<sptr<AudioDeviceDescriptor>> deviceDescriptors,napi_env env,napi_value * result,int32_t arrayLength,napi_value valueParam)446 static void SetDevicesInfo(vector<sptr<AudioDeviceDescriptor>> deviceDescriptors, napi_env env, napi_value* result,
447     int32_t arrayLength, napi_value valueParam)
448 {
449     size_t size = deviceDescriptors.size();
450     HiLog::Info(LABEL, "number of devices = %{public}zu", size);
451 
452     if (arrayLength > PARAM1) {
453         SetDeviceDescriptors(env, result[PARAM1], valueParam, deviceDescriptors);
454     } else {
455         HiLog::Error(LABEL, "ERROR: Array access out of bounds, result size is %{public}d", arrayLength);
456         return;
457     }
458 }
459 
GetDevicesAsyncCallbackComplete(napi_env env,napi_status status,void * data)460 static void GetDevicesAsyncCallbackComplete(napi_env env, napi_status status, void* data)
461 {
462     auto asyncContext = static_cast<AudioRoutingManagerAsyncContext*>(data);
463     if (asyncContext == nullptr) {
464         HiLog::Error(LABEL, "ERROR: AudioRoutingManagerAsyncContext* is Null!");
465         return;
466     }
467     napi_value result[ARGS_TWO] = {0};
468     napi_value valueParam = nullptr;
469     SetDevicesInfo(asyncContext->deviceDescriptors, env, result, ARGS_TWO, valueParam);
470 
471     napi_get_undefined(env, &result[PARAM0]);
472     if (!asyncContext->status) {
473         napi_get_undefined(env, &valueParam);
474     }
475     CommonCallbackRoutine(env, asyncContext, result[PARAM1]);
476 }
477 
GetDevices(napi_env env,napi_callback_info info)478 napi_value AudioRoutingManagerNapi::GetDevices(napi_env env, napi_callback_info info)
479 {
480     const int32_t refCount = 1;
481     napi_value result = nullptr;
482 
483     size_t argc = ARGS_TWO;
484     napi_value argv[ARGS_TWO] = { 0 };
485     napi_value thisVar = nullptr;
486     void* data;
487     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
488 
489     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
490 
491     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
492     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
493         CheckParams(argc, env, argv, asyncContext, refCount, result);
494 
495         napi_value resource = nullptr;
496         napi_create_string_utf8(env, "GetDevices", NAPI_AUTO_LENGTH, &resource);
497 
498         status = napi_create_async_work(
499             env, nullptr, resource, [](napi_env env, void *data) {
500                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
501                 if (context->status == SUCCESS) {
502                     context->deviceDescriptors = context->objectInfo->audioMngr_->GetDevices(
503                         static_cast<DeviceFlag>(context->deviceFlag));
504                     context->status = 0;
505                 }
506             }, GetDevicesAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
507         if (status != napi_ok) {
508             result = nullptr;
509         } else {
510             status = napi_queue_async_work(env, asyncContext->work);
511             if (status == napi_ok) {
512                 asyncContext.release();
513             } else {
514                 result = nullptr;
515             }
516         }
517     }
518 
519     return result;
520 }
521 
GetDevicesSync(napi_env env,napi_callback_info info)522 napi_value AudioRoutingManagerNapi::GetDevicesSync(napi_env env, napi_callback_info info)
523 {
524     napi_status status;
525     napi_value result = nullptr;
526     void *native = nullptr;
527 
528     GET_PARAMS(env, info, ARGS_ONE);
529 
530     if (argc < ARGS_ONE) {
531         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
532         return result;
533     }
534 
535     status = napi_unwrap(env, thisVar, &native);
536     auto *audioRoutingManagerNapi = reinterpret_cast<AudioRoutingManagerNapi *>(native);
537     if (status != napi_ok || audioRoutingManagerNapi == nullptr) {
538         AUDIO_ERR_LOG("GetDevicesSync unwrap failure!");
539         return result;
540     }
541 
542     napi_valuetype valueType = napi_undefined;
543     napi_typeof(env, argv[PARAM0], &valueType);
544     if (valueType != napi_number) {
545         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
546         return result;
547     }
548 
549     int32_t deviceFlag;
550     napi_get_value_int32(env, argv[PARAM0], &deviceFlag);
551     if (!AudioCommonNapi::IsLegalInputArgumentDeviceFlag(deviceFlag)) {
552         AudioCommonNapi::throwError(env, NAPI_ERR_INVALID_PARAM);
553         return result;
554     }
555 
556     vector<sptr<AudioDeviceDescriptor>> deviceDescriptors = audioRoutingManagerNapi->audioMngr_->GetDevices(
557         static_cast<DeviceFlag>(deviceFlag));
558 
559     napi_value valueParam = nullptr;
560     SetDeviceDescriptors(env, result, valueParam, deviceDescriptors);
561 
562     return result;
563 }
564 
CheckParams(size_t argc,napi_env env,napi_value * argv,std::unique_ptr<AudioRoutingManagerAsyncContext> & asyncContext,const int32_t refCount,napi_value & result)565 void AudioRoutingManagerNapi::CheckParams(size_t argc, napi_env env, napi_value* argv,
566     std::unique_ptr<AudioRoutingManagerAsyncContext>& asyncContext, const int32_t refCount, napi_value& result)
567 {
568     if (argc < ARGS_ONE) {
569             asyncContext->status = NAPI_ERR_INVALID_PARAM;
570     }
571     for (size_t i = PARAM0; i < argc; i++) {
572         napi_valuetype valueType = napi_undefined;
573         napi_typeof(env, argv[i], &valueType);
574 
575         if (i == PARAM0 && valueType == napi_number) {
576             napi_get_value_int32(env, argv[i], &asyncContext->deviceFlag);
577             HiLog::Info(LABEL, " GetDevices deviceFlag = %{public}d", asyncContext->deviceFlag);
578             if (!AudioCommonNapi::IsLegalInputArgumentDeviceFlag(asyncContext->deviceFlag)) {
579                 asyncContext->status = asyncContext->status ==
580                     NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED;
581             }
582         } else if (i == PARAM1) {
583             if (valueType == napi_function) {
584                 napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
585             }
586             break;
587         } else {
588             asyncContext->status = NAPI_ERR_INVALID_PARAM;
589             HiLog::Error(LABEL, "ERROR: type mismatch");
590         }
591     }
592 
593     if (asyncContext->callbackRef == nullptr) {
594         napi_create_promise(env, &asyncContext->deferred, &result);
595     } else {
596         napi_get_undefined(env, &result);
597     }
598 }
599 
SelectOutputDevice(napi_env env,napi_callback_info info)600 napi_value AudioRoutingManagerNapi::SelectOutputDevice(napi_env env, napi_callback_info info)
601 {
602     napi_status status;
603     const int32_t refCount = 1;
604     napi_value result = nullptr;
605     size_t argc = ARGS_TWO;
606     napi_value argv[ARGS_TWO] = {0};
607     napi_value thisVar = nullptr;
608     void *data = nullptr;
609     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
610 
611     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
612 
613     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
614     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
615         if (argc < ARGS_ONE) {
616             asyncContext->status = NAPI_ERR_INVALID_PARAM;
617         }
618         for (size_t i = PARAM0; i < argc; i++) {
619             napi_valuetype valueType = napi_undefined;
620             napi_typeof(env, argv[i], &valueType);
621 
622             if (i == PARAM0 && valueType == napi_object) {
623                 ParseAudioDeviceDescriptorVector(env, argv[i], asyncContext->deviceDescriptors,
624                     asyncContext->bArgTransFlag);
625             } else if (i == PARAM1) {
626                 if (valueType == napi_function) {
627                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
628                 }
629                 break;
630             } else {
631                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
632             }
633         }
634 
635         if (asyncContext->callbackRef == nullptr) {
636             napi_create_promise(env, &asyncContext->deferred, &result);
637         } else {
638             napi_get_undefined(env, &result);
639         }
640 
641         napi_value resource = nullptr;
642         napi_create_string_utf8(env, "SelectOutputDevice", NAPI_AUTO_LENGTH, &resource);
643 
644         status = napi_create_async_work(
645             env, nullptr, resource,
646             [](napi_env env, void *data) {
647                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
648                 if (context->bArgTransFlag) {
649                     context->status = context->objectInfo->audioMngr_->SelectOutputDevice(context->deviceDescriptors);
650                 } else {
651                     context->status = context->status ==
652                         NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED;
653                 }
654             },
655             SelectOutputDeviceAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
656         if (status != napi_ok) {
657             result = nullptr;
658         } else {
659             status = napi_queue_async_work(env, asyncContext->work);
660             if (status == napi_ok) {
661                 asyncContext.release();
662             } else {
663                 result = nullptr;
664             }
665         }
666     }
667     return result;
668 }
669 
GetActiveOutputDeviceAsyncCallbackComplete(napi_env env,napi_status status,void * data)670 static void GetActiveOutputDeviceAsyncCallbackComplete(napi_env env, napi_status status, void* data)
671 {
672     auto asyncContext = static_cast<AudioRoutingManagerAsyncContext*>(data);
673     napi_value result[ARGS_TWO] = {0};
674     napi_value valueParam = nullptr;
675     if (asyncContext == nullptr) {
676         HiLog::Error(LABEL, "ERROR: AudioRoutingManagerAsyncContext* is Null!");
677         return;
678     }
679     SetDevicesInfo(asyncContext->outDeviceDescriptors, env, result, ARGS_TWO, valueParam);
680 
681     napi_get_undefined(env, &result[PARAM0]);
682     if (!asyncContext->status) {
683         napi_get_undefined(env, &valueParam);
684     }
685     CommonCallbackRoutine(env, asyncContext, result[PARAM1]);
686 }
687 
GetActiveOutputDeviceDescriptors(napi_env env,napi_callback_info info)688 napi_value AudioRoutingManagerNapi::GetActiveOutputDeviceDescriptors(napi_env env, napi_callback_info info)
689 {
690     napi_status status;
691     const int32_t refCount = 1;
692     napi_value result = nullptr;
693     size_t argc = ARGS_ONE;
694     napi_value argv[ARGS_ONE] = {0};
695     napi_value thisVar = nullptr;
696     void *data = nullptr;
697     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
698 
699     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
700 
701     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
702     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
703         napi_valuetype valueType = napi_undefined;
704         napi_typeof(env, argv[PARAM0], &valueType);
705 
706         if (argc == PARAM1 && valueType == napi_function) {
707                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
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, "GetActiveOutputDeviceDescriptors", 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->status == SUCCESS) {
724                     context->outDeviceDescriptors = context->objectInfo->audioMngr_->GetActiveOutputDeviceDescriptors();
725                     context->status = SUCCESS;
726                 }
727             },
728             GetActiveOutputDeviceAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
729         if (status != napi_ok) {
730             result = nullptr;
731         } else {
732             status = napi_queue_async_work(env, asyncContext->work);
733             if (status == napi_ok) {
734                 asyncContext.release();
735             } else {
736                 result = nullptr;
737             }
738         }
739     }
740     return result;
741 }
742 
GetPreferredOutputDeviceForRendererInfoAsyncCallbackComplete(napi_env env,napi_status status,void * data)743 static void GetPreferredOutputDeviceForRendererInfoAsyncCallbackComplete(napi_env env, napi_status status, void *data)
744 {
745     auto asyncContext = static_cast<AudioRoutingManagerAsyncContext*>(data);
746     napi_value result[ARGS_TWO] = {0};
747     napi_value valueParam = nullptr;
748     if (asyncContext == nullptr) {
749         HiLog::Error(LABEL, "ERROR: AudioRoutingManagerAsyncContext* is Null!");
750         return;
751     }
752     SetDevicesInfo(asyncContext->outDeviceDescriptors, env, result, ARGS_TWO, valueParam);
753 
754     napi_get_undefined(env, &result[PARAM0]);
755     if (!asyncContext->status) {
756         napi_get_undefined(env, &valueParam);
757     }
758     CommonCallbackRoutine(env, asyncContext, result[PARAM1]);
759 }
760 
CheckPreferredOutputDeviceForRendererInfo(napi_env env,std::unique_ptr<AudioRoutingManagerAsyncContext> & asyncContext,size_t argc,napi_value * argv)761 bool AudioRoutingManagerNapi::CheckPreferredOutputDeviceForRendererInfo(napi_env env,
762     std::unique_ptr<AudioRoutingManagerAsyncContext>& asyncContext, size_t argc, napi_value* argv)
763 {
764     const int32_t refCount = 1;
765     if (argc < ARGS_ONE) {
766         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
767         return false;
768     }
769     for (size_t i = PARAM0; i < argc; i++) {
770         napi_valuetype valueType = napi_undefined;
771         napi_typeof(env, argv[i], &valueType);
772 
773         if (i == PARAM0 && valueType == napi_object) {
774             ParseAudioRendererInfo(env, argv[i], &asyncContext->rendererInfo);
775         } else if (i == PARAM1) {
776             if (valueType == napi_function) {
777                 napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
778             }
779             break;
780         } else {
781             AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
782             return false;
783         }
784     }
785     return true;
786 }
787 
GetPreferOutputDeviceForRendererInfo(napi_env env,napi_callback_info info)788 napi_value AudioRoutingManagerNapi::GetPreferOutputDeviceForRendererInfo(napi_env env, napi_callback_info info)
789 {
790     // for api compatibility, leave some time for applications to adapt to new one
791     return GetPreferredOutputDeviceForRendererInfo(env, info);
792 }
793 
GetPreferredOutputDeviceForRendererInfo(napi_env env,napi_callback_info info)794 napi_value AudioRoutingManagerNapi::GetPreferredOutputDeviceForRendererInfo(napi_env env, napi_callback_info info)
795 {
796     napi_status status;
797     napi_value result = nullptr;
798     size_t argc = ARGS_TWO;
799     napi_value argv[ARGS_TWO] = {0};
800     napi_value thisVar = nullptr;
801     void *data = nullptr;
802     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
803 
804     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
805 
806     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
807     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
808         if (!CheckPreferredOutputDeviceForRendererInfo(env, asyncContext, argc, argv)) {
809             return nullptr;
810         }
811         if (asyncContext->callbackRef == nullptr) {
812             napi_create_promise(env, &asyncContext->deferred, &result);
813         } else {
814             napi_get_undefined(env, &result);
815         }
816 
817         napi_value resource = nullptr;
818         napi_create_string_utf8(env, "GetPreferredOutputDeviceForRendererInfo", NAPI_AUTO_LENGTH, &resource);
819 
820         status = napi_create_async_work(
821             env, nullptr, resource,
822             [](napi_env env, void *data) {
823                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
824                 if (context->status == SUCCESS) {
825                     context->status = context->objectInfo->audioRoutingMngr_->GetPreferredOutputDeviceForRendererInfo(
826                         context->rendererInfo, context->outDeviceDescriptors);
827                 }
828             }, GetPreferredOutputDeviceForRendererInfoAsyncCallbackComplete,
829             static_cast<void*>(asyncContext.get()), &asyncContext->work);
830         if (status != napi_ok) {
831             result = nullptr;
832         } else {
833             status = napi_queue_async_work(env, asyncContext->work);
834             if (status == napi_ok) {
835                 asyncContext.release();
836             } else {
837                 result = nullptr;
838             }
839         }
840     }
841     return result;
842 }
843 
GetPreferredOutputDeviceForRendererInfoSync(napi_env env,napi_callback_info info)844 napi_value AudioRoutingManagerNapi::GetPreferredOutputDeviceForRendererInfoSync(napi_env env, napi_callback_info info)
845 {
846     napi_status status;
847     napi_value result = nullptr;
848     void *native = nullptr;
849 
850     GET_PARAMS(env, info, ARGS_ONE);
851 
852     if (argc < ARGS_ONE) {
853         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
854         return result;
855     }
856 
857     status = napi_unwrap(env, thisVar, &native);
858     auto *audioRoutingManagerNapi = reinterpret_cast<AudioRoutingManagerNapi *>(native);
859     if (status != napi_ok || audioRoutingManagerNapi == nullptr) {
860         AUDIO_ERR_LOG("GetPreferredOutputDeviceForRendererInfoSync unwrap failure!");
861         return result;
862     }
863 
864     napi_valuetype valueType = napi_undefined;
865     napi_typeof(env, argv[PARAM0], &valueType);
866     if (valueType != napi_object) {
867         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
868         return result;
869     }
870 
871     AudioRendererInfo rendererInfo;
872     ParseAudioRendererInfo(env, argv[PARAM0], &rendererInfo);
873 
874     vector<sptr<AudioDeviceDescriptor>> outDeviceDescriptors;
875     audioRoutingManagerNapi->audioRoutingMngr_->GetPreferredOutputDeviceForRendererInfo(
876         rendererInfo, outDeviceDescriptors);
877 
878     napi_value valueParam = nullptr;
879     SetDeviceDescriptors(env, result, valueParam, outDeviceDescriptors);
880 
881     return result;
882 }
883 
isValidSourceType(int32_t intValue)884 static bool isValidSourceType(int32_t intValue)
885 {
886     SourceType sourceTypeValue = static_cast<SourceType>(intValue);
887     switch (sourceTypeValue) {
888         case SourceType::SOURCE_TYPE_MIC:
889         case SourceType::SOURCE_TYPE_PLAYBACK_CAPTURE:
890         case SourceType::SOURCE_TYPE_ULTRASONIC:
891         case SourceType::SOURCE_TYPE_VOICE_COMMUNICATION:
892         case SourceType::SOURCE_TYPE_VOICE_RECOGNITION:
893         case SourceType::SOURCE_TYPE_WAKEUP:
894             return true;
895         default:
896             return false;
897     }
898 }
899 
ParseAudioCapturerInfo(napi_env env,napi_value root,AudioCapturerInfo * capturerInfo)900 static void ParseAudioCapturerInfo(napi_env env, napi_value root, AudioCapturerInfo *capturerInfo)
901 {
902     napi_value tempValue = nullptr;
903     int32_t intValue = {0};
904 
905     if (napi_get_named_property(env, root, "source", &tempValue) == napi_ok) {
906         napi_get_value_int32(env, tempValue, &intValue);
907         if (isValidSourceType(intValue)) {
908             capturerInfo->sourceType = static_cast<SourceType>(intValue);
909         } else {
910             capturerInfo->sourceType = SourceType::SOURCE_TYPE_INVALID;
911         }
912     }
913 
914     if (napi_get_named_property(env, root, "capturerFlags", &tempValue) == napi_ok) {
915         napi_get_value_int32(env, tempValue, &intValue);
916         capturerInfo->capturerFlags = intValue;
917     }
918 }
919 
CheckPreferredInputDeviceForCaptureInfo(napi_env env,std::unique_ptr<AudioRoutingManagerAsyncContext> & asyncContext,size_t argc,napi_value * argv)920 bool AudioRoutingManagerNapi::CheckPreferredInputDeviceForCaptureInfo(napi_env env,
921     std::unique_ptr<AudioRoutingManagerAsyncContext> &asyncContext, size_t argc, napi_value *argv)
922 {
923     const int32_t refCount = 1;
924     if (argc < ARGS_ONE) {
925         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
926         return false;
927     }
928     for (size_t i = PARAM0; i < argc; i++) {
929         napi_valuetype valueType = napi_undefined;
930         napi_typeof(env, argv[i], &valueType);
931 
932         if (i == PARAM0 && valueType == napi_object) {
933             ParseAudioCapturerInfo(env, argv[i], &asyncContext->captureInfo);
934         } else if (i == PARAM1) {
935             if (valueType == napi_function) {
936                 napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
937             }
938             break;
939         } else {
940             AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
941             return false;
942         }
943     }
944     return true;
945 }
946 
GetPreferredInputDeviceForCapturerInfoAsyncCallbackComplete(napi_env env,napi_status status,void * data)947 static void GetPreferredInputDeviceForCapturerInfoAsyncCallbackComplete(napi_env env, napi_status status, void *data)
948 {
949     auto asyncContext = static_cast<AudioRoutingManagerAsyncContext*>(data);
950     napi_value result[ARGS_TWO] = {0};
951     napi_value valueParam = nullptr;
952     if (asyncContext == nullptr) {
953         AUDIO_ERR_LOG("asyncContext is Null!");
954         return;
955     }
956     SetDevicesInfo(asyncContext->inputDeviceDescriptors, env, result, ARGS_TWO, valueParam);
957 
958     napi_get_undefined(env, &result[PARAM0]);
959     if (!asyncContext->status) {
960         napi_get_undefined(env, &valueParam);
961     }
962     CommonCallbackRoutine(env, asyncContext, result[PARAM1]);
963 }
964 
GetPreferredInputDeviceForCapturerInfo(napi_env env,napi_callback_info info)965 napi_value AudioRoutingManagerNapi::GetPreferredInputDeviceForCapturerInfo(napi_env env, napi_callback_info info)
966 {
967     napi_status status;
968     napi_value result = nullptr;
969     size_t argc = ARGS_TWO;
970     napi_value argv[ARGS_TWO] = {0};
971     napi_value thisVar = nullptr;
972     void *data = nullptr;
973     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
974 
975     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
976 
977     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
978     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
979         if (!CheckPreferredInputDeviceForCaptureInfo(env, asyncContext, argc, argv)) {
980             return nullptr;
981         }
982         if (asyncContext->callbackRef == nullptr) {
983             napi_create_promise(env, &asyncContext->deferred, &result);
984         } else {
985             napi_get_undefined(env, &result);
986         }
987 
988         napi_value resource = nullptr;
989         napi_create_string_utf8(env, "GetPreferredInputDeviceForCapturerInfo", NAPI_AUTO_LENGTH, &resource);
990 
991         status = napi_create_async_work(
992             env, nullptr, resource,
993             [](napi_env env, void *data) {
994                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
995                 if (context->status != SUCCESS) {
996                     return;
997                 }
998                 if (context->captureInfo.sourceType == SourceType::SOURCE_TYPE_INVALID) {
999                         context->status = NAPI_ERR_INVALID_PARAM;
1000                 } else {
1001                     context->status = context->objectInfo->audioRoutingMngr_->GetPreferredInputDeviceForCapturerInfo(
1002                         context->captureInfo, context->inputDeviceDescriptors);
1003                 }
1004             }, GetPreferredInputDeviceForCapturerInfoAsyncCallbackComplete,
1005             static_cast<void*>(asyncContext.get()), &asyncContext->work);
1006         if (status != napi_ok) {
1007             result = nullptr;
1008         } else {
1009             status = napi_queue_async_work(env, asyncContext->work);
1010             if (status == napi_ok) {
1011                 asyncContext.release();
1012             } else {
1013                 result = nullptr;
1014             }
1015         }
1016     }
1017     return result;
1018 }
1019 
GetPreferredInputDeviceForCapturerInfoSync(napi_env env,napi_callback_info info)1020 napi_value AudioRoutingManagerNapi::GetPreferredInputDeviceForCapturerInfoSync(napi_env env, napi_callback_info info)
1021 {
1022     napi_status status;
1023     napi_value result = nullptr;
1024     void *native = nullptr;
1025 
1026     GET_PARAMS(env, info, ARGS_ONE);
1027 
1028     if (argc < ARGS_ONE) {
1029         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
1030         return result;
1031     }
1032 
1033     status = napi_unwrap(env, thisVar, &native);
1034     auto *audioRoutingManagerNapi = reinterpret_cast<AudioRoutingManagerNapi *>(native);
1035     if (status != napi_ok || audioRoutingManagerNapi == nullptr) {
1036         AUDIO_ERR_LOG("GetPreferredInputDeviceForCapturerInfoSync unwrap failure!");
1037         return result;
1038     }
1039 
1040     napi_valuetype valueType = napi_undefined;
1041     napi_typeof(env, argv[PARAM0], &valueType);
1042     if (valueType != napi_object) {
1043         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
1044         return result;
1045     }
1046 
1047     AudioCapturerInfo capturerInfo;
1048     ParseAudioCapturerInfo(env, argv[PARAM0], &capturerInfo);
1049     if (capturerInfo.sourceType == SourceType::SOURCE_TYPE_INVALID) {
1050         AudioCommonNapi::throwError(env, NAPI_ERR_INVALID_PARAM);
1051         return result;
1052     }
1053 
1054     vector<sptr<AudioDeviceDescriptor>> outDeviceDescriptors;
1055     audioRoutingManagerNapi->audioRoutingMngr_->GetPreferredInputDeviceForCapturerInfo(
1056         capturerInfo, outDeviceDescriptors);
1057 
1058     napi_value valueParam = nullptr;
1059     SetDeviceDescriptors(env, result, valueParam, outDeviceDescriptors);
1060 
1061     return result;
1062 }
1063 
SelectOutputDeviceByFilter(napi_env env,napi_callback_info info)1064 napi_value AudioRoutingManagerNapi::SelectOutputDeviceByFilter(napi_env env, napi_callback_info info)
1065 {
1066     napi_status status;
1067     const int32_t refCount = 1;
1068     napi_value result = nullptr;
1069     size_t argc = ARGS_THREE;
1070     napi_value argv[ARGS_THREE] = {0};
1071     napi_value thisVar = nullptr;
1072     void *data = nullptr;
1073     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1074 
1075     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
1076 
1077     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1078     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1079         if (argc < ARGS_TWO) {
1080             asyncContext->status = NAPI_ERR_INVALID_PARAM;
1081         }
1082         for (size_t i = PARAM0; i < argc; i++) {
1083             napi_valuetype valueType = napi_undefined;
1084             napi_typeof(env, argv[i], &valueType);
1085 
1086             if (i == PARAM0 && valueType == napi_object) {
1087                 ParseAudioRendererFilter(env, argv[i], asyncContext->audioRendererFilter, asyncContext->bArgTransFlag);
1088             } else if (i == PARAM1 && valueType == napi_object) {
1089                 ParseAudioDeviceDescriptorVector(env, argv[i], asyncContext->deviceDescriptors,
1090                     asyncContext->bArgTransFlag);
1091             } else if (i == PARAM2) {
1092                 if (valueType == napi_function) {
1093                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
1094                 }
1095                 break;
1096             } else {
1097                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
1098             }
1099         }
1100 
1101         if (asyncContext->callbackRef == nullptr) {
1102             napi_create_promise(env, &asyncContext->deferred, &result);
1103         } else {
1104             napi_get_undefined(env, &result);
1105         }
1106 
1107         napi_value resource = nullptr;
1108         napi_create_string_utf8(env, "SelectOutputDeviceByFilter", NAPI_AUTO_LENGTH, &resource);
1109 
1110         status = napi_create_async_work(
1111             env, nullptr, resource,
1112             [](napi_env env, void *data) {
1113                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
1114                 if (context->bArgTransFlag) {
1115                     context->status = context->objectInfo->audioMngr_->SelectOutputDevice(
1116                         context->audioRendererFilter, context->deviceDescriptors);
1117                 } else {
1118                     context->status = context->status ==
1119                         NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED;
1120                 }
1121             },
1122             SelectOutputDeviceAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1123         if (status != napi_ok) {
1124             result = nullptr;
1125         } else {
1126             status = napi_queue_async_work(env, asyncContext->work);
1127             if (status == napi_ok) {
1128                 asyncContext.release();
1129             } else {
1130                 result = nullptr;
1131             }
1132         }
1133     }
1134 
1135     return result;
1136 }
1137 
ParseAudioCapturerFilter(napi_env env,napi_value root,sptr<AudioCapturerFilter> & audioCapturerFilter)1138 static void ParseAudioCapturerFilter(napi_env env, napi_value root, sptr<AudioCapturerFilter> &audioCapturerFilter)
1139 {
1140     napi_value tempValue = nullptr;
1141     int32_t intValue = {0};
1142 
1143     audioCapturerFilter = new(std::nothrow) AudioCapturerFilter();
1144     if (napi_get_named_property(env, root, "uid", &tempValue) == napi_ok) {
1145         napi_get_value_int32(env, tempValue, &intValue);
1146         audioCapturerFilter->uid = intValue;
1147     }
1148 }
1149 
SelectInputDeviceAsyncCallbackComplete(napi_env env,napi_status status,void * data)1150 static void SelectInputDeviceAsyncCallbackComplete(napi_env env, napi_status status, void *data)
1151 {
1152     auto asyncContext = static_cast<AudioRoutingManagerAsyncContext*>(data);
1153     napi_value valueParam = nullptr;
1154 
1155     if (asyncContext != nullptr) {
1156         if (!asyncContext->status) {
1157             napi_get_undefined(env, &valueParam);
1158         }
1159         CommonCallbackRoutine(env, asyncContext, valueParam);
1160     } else {
1161         HiLog::Error(LABEL, "ERROR: AudioRoutingManagerAsyncContext* is Null!");
1162     }
1163 }
1164 
SelectInputDevice(napi_env env,napi_callback_info info)1165 napi_value AudioRoutingManagerNapi::SelectInputDevice(napi_env env, napi_callback_info info)
1166 {
1167     napi_status status;
1168     const int32_t refCount = 1;
1169     napi_value result = nullptr;
1170     size_t argc = ARGS_TWO;
1171     napi_value argv[ARGS_TWO] = {0};
1172     napi_value thisVar = nullptr;
1173     void *data = nullptr;
1174     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1175 
1176     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
1177 
1178     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1179     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1180         if (argc < ARGS_ONE) {
1181             asyncContext->status = NAPI_ERR_INVALID_PARAM;
1182         }
1183         for (size_t i = PARAM0; i < argc; i++) {
1184             napi_valuetype valueType = napi_undefined;
1185             napi_typeof(env, argv[i], &valueType);
1186             if (i == PARAM0 && valueType == napi_object) {
1187                 ParseAudioDeviceDescriptorVector(env, argv[i], asyncContext->deviceDescriptors,
1188                     asyncContext->bArgTransFlag);
1189             } else if (i == PARAM1) {
1190                 if (valueType == napi_function) {
1191                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
1192                 }
1193                 break;
1194             } else {
1195                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
1196             }
1197 
1198             if (!asyncContext->bArgTransFlag) {
1199                 break;
1200             }
1201         }
1202 
1203         if (asyncContext->callbackRef == nullptr) {
1204             napi_create_promise(env, &asyncContext->deferred, &result);
1205         } else {
1206             napi_get_undefined(env, &result);
1207         }
1208 
1209         napi_value resource = nullptr;
1210         napi_create_string_utf8(env, "SelectInputDevice", NAPI_AUTO_LENGTH, &resource);
1211 
1212         status = napi_create_async_work(
1213             env, nullptr, resource,
1214             [](napi_env env, void *data) {
1215                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
1216                 if (context->bArgTransFlag) {
1217                     context->status = context->objectInfo->audioMngr_->SelectInputDevice(context->deviceDescriptors);
1218                 } else {
1219                     context->status = ERR_INVALID_PARAM;
1220                 }
1221             },
1222             SelectInputDeviceAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1223         if (status != napi_ok) {
1224             result = nullptr;
1225         } else {
1226             status = napi_queue_async_work(env, asyncContext->work);
1227             if (status == napi_ok) {
1228                 asyncContext.release();
1229             } else {
1230                 result = nullptr;
1231             }
1232         }
1233     }
1234 
1235     return result;
1236 }
1237 
SelectInputDeviceByFilter(napi_env env,napi_callback_info info)1238 napi_value AudioRoutingManagerNapi::SelectInputDeviceByFilter(napi_env env, napi_callback_info info)
1239 {
1240     napi_status status;
1241     const int32_t refCount = 1;
1242     napi_value result = nullptr;
1243 
1244     size_t argc = ARGS_THREE;
1245     napi_value argv[ARGS_TWO] = {0};
1246     napi_value thisVar = nullptr;
1247     void *data = nullptr;
1248     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1249     NAPI_ASSERT(env, argc >= ARGS_THREE, "requires 2 parameters minimum");
1250 
1251     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
1252 
1253     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1254     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1255         if (argc < ARGS_TWO) {
1256             asyncContext->status = NAPI_ERR_INVALID_PARAM;
1257         }
1258         for (size_t i = PARAM0; i < argc; i++) {
1259             napi_valuetype valueType = napi_undefined;
1260             napi_typeof(env, argv[i], &valueType);
1261             if (i == PARAM0 && valueType == napi_object) {
1262                 ParseAudioCapturerFilter(env, argv[i], asyncContext->audioCapturerFilter);
1263             } else if (i == PARAM1 && valueType == napi_object) {
1264                 ParseAudioDeviceDescriptorVector(env, argv[i], asyncContext->deviceDescriptors,
1265                     asyncContext->bArgTransFlag);
1266             } else if (i == PARAM2) {
1267                 if (valueType == napi_function) {
1268                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
1269                 }
1270                 break;
1271             } else {
1272                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
1273             }
1274 
1275             if (!asyncContext->bArgTransFlag) {
1276                 break;
1277             }
1278         }
1279 
1280         if (asyncContext->callbackRef == nullptr) {
1281             napi_create_promise(env, &asyncContext->deferred, &result);
1282         } else {
1283             napi_get_undefined(env, &result);
1284         }
1285 
1286         napi_value resource = nullptr;
1287         napi_create_string_utf8(env, "SelectInputDeviceByFilter", NAPI_AUTO_LENGTH, &resource);
1288 
1289         status = napi_create_async_work(
1290             env, nullptr, resource,
1291             [](napi_env env, void *data) {
1292                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
1293                 if (context->bArgTransFlag) {
1294                     context->status = context->objectInfo->audioMngr_->SelectInputDevice(
1295                         context->audioCapturerFilter, context->deviceDescriptors);
1296                 } else {
1297                     context->status = context->status ==
1298                         NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED;
1299                 }
1300             },
1301             SelectInputDeviceAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1302         if (status != napi_ok) {
1303             result = nullptr;
1304         } else {
1305             status = napi_queue_async_work(env, asyncContext->work);
1306             if (status == napi_ok) {
1307                 asyncContext.release();
1308             } else {
1309                 result = nullptr;
1310             }
1311         }
1312     }
1313 
1314     return result;
1315 }
1316 
RegisterDeviceChangeCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,AudioRoutingManagerNapi * routingMgrNapi)1317 void AudioRoutingManagerNapi::RegisterDeviceChangeCallback(napi_env env, size_t argc, napi_value* args,
1318     const std::string& cbName, AudioRoutingManagerNapi* routingMgrNapi)
1319 {
1320     int32_t flag = 3;
1321     napi_valuetype valueType = napi_undefined;
1322     napi_typeof(env, args[PARAM1], &valueType);
1323     if (valueType == napi_number) {
1324         napi_get_value_int32(env, args[PARAM1], &flag);
1325         AUDIO_INFO_LOG("RegisterDeviceChangeCallback:On deviceFlag: %{public}d", flag);
1326         if (!AudioCommonNapi::IsLegalInputArgumentDeviceFlag(flag)) {
1327             AudioCommonNapi::throwError(env, NAPI_ERR_INVALID_PARAM);
1328         }
1329     } else {
1330         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
1331     }
1332 
1333     napi_valuetype handler = napi_undefined;
1334     napi_typeof(env, args[PARAM2], &handler);
1335     if (handler != napi_function) {
1336         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
1337     }
1338     DeviceFlag deviceFlag = DeviceFlag(flag);
1339     if (!routingMgrNapi->deviceChangeCallbackNapi_) {
1340         routingMgrNapi->deviceChangeCallbackNapi_= std::make_shared<AudioManagerCallbackNapi>(env);
1341     }
1342     CHECK_AND_RETURN_LOG(routingMgrNapi->deviceChangeCallbackNapi_,
1343         "RegisterDeviceChangeCallback: Memory Allocation Failed !");
1344 
1345     int32_t ret = routingMgrNapi->audioMngr_->SetDeviceChangeCallback(deviceFlag,
1346         routingMgrNapi->deviceChangeCallbackNapi_);
1347     if (ret) {
1348         AUDIO_ERR_LOG("RegisterDeviceChangeCallback: Registering Device Change Callback Failed %{public}d", ret);
1349         AudioCommonNapi::throwError(env, ret);
1350         return;
1351     }
1352 
1353     std::shared_ptr<AudioManagerCallbackNapi> cb =
1354         std::static_pointer_cast<AudioManagerCallbackNapi>(routingMgrNapi->deviceChangeCallbackNapi_);
1355     cb->SaveRoutingManagerDeviceChangeCbRef(deviceFlag, args[PARAM2]);
1356 }
1357 
RegisterPreferredOutputDeviceChangeCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,AudioRoutingManagerNapi * routingMgrNapi)1358 void AudioRoutingManagerNapi::RegisterPreferredOutputDeviceChangeCallback(napi_env env, size_t argc, napi_value* args,
1359     const std::string& cbName, AudioRoutingManagerNapi* routingMgrNapi)
1360 {
1361     napi_valuetype valueType = napi_undefined;
1362     napi_typeof(env, args[PARAM1], &valueType);
1363     if (valueType != napi_object) {
1364         AudioCommonNapi::throwError(env, NAPI_ERR_INVALID_PARAM);
1365     }
1366 
1367     AudioRendererInfo rendererInfo;
1368     ParseAudioRendererInfo(env, args[PARAM1], &rendererInfo);
1369     AudioStreamType streamType = AudioSystemManager::GetStreamType(rendererInfo.contentType,
1370         rendererInfo.streamUsage);
1371 
1372     if (!routingMgrNapi->preferredOutputDeviceCallbackNapi_) {
1373         routingMgrNapi->preferredOutputDeviceCallbackNapi_ =
1374             std::make_shared<AudioPreferredOutputDeviceChangeCallbackNapi>(env);
1375         if (!routingMgrNapi->preferredOutputDeviceCallbackNapi_) {
1376             AUDIO_ERR_LOG("RegisterPreferredOutputDeviceChangeCallback: Memory Allocation Failed !!");
1377             return;
1378         }
1379 
1380         int32_t ret = routingMgrNapi->audioRoutingMngr_->SetPreferredOutputDeviceChangeCallback(
1381             rendererInfo, routingMgrNapi->preferredOutputDeviceCallbackNapi_);
1382         if (ret) {
1383             AUDIO_ERR_LOG("Registering Active Output DeviceChange Callback Failed %{public}d", ret);
1384             AudioCommonNapi::throwError(env, ret);
1385             return;
1386         }
1387     }
1388 
1389     std::shared_ptr<AudioPreferredOutputDeviceChangeCallbackNapi> cb =
1390         std::static_pointer_cast<AudioPreferredOutputDeviceChangeCallbackNapi>(
1391         routingMgrNapi->preferredOutputDeviceCallbackNapi_);
1392     cb->SaveCallbackReference(streamType, args[PARAM2]);
1393 }
1394 
RegisterPreferredInputDeviceChangeCallback(napi_env env,size_t argc,napi_value * args,const std::string & cbName,AudioRoutingManagerNapi * routingMgrNapi)1395 void AudioRoutingManagerNapi::RegisterPreferredInputDeviceChangeCallback(napi_env env, size_t argc, napi_value *args,
1396     const std::string &cbName, AudioRoutingManagerNapi *routingMgrNapi)
1397 {
1398     napi_valuetype valueType = napi_undefined;
1399     napi_typeof(env, args[PARAM1], &valueType);
1400     if (valueType != napi_object) {
1401         AudioCommonNapi::throwError(env, NAPI_ERR_INVALID_PARAM);
1402     }
1403 
1404     AudioCapturerInfo captureInfo;
1405     ParseAudioCapturerInfo(env, args[PARAM1], &captureInfo);
1406     if (captureInfo.sourceType == SourceType::SOURCE_TYPE_INVALID) {
1407         AudioCommonNapi::throwError(env, NAPI_ERR_INVALID_PARAM);
1408         return;
1409     }
1410 
1411     if (!routingMgrNapi->preferredInputDeviceCallbackNapi_) {
1412         routingMgrNapi->preferredInputDeviceCallbackNapi_ =
1413             std::make_shared<AudioPreferredInputDeviceChangeCallbackNapi>(env);
1414         if (!routingMgrNapi->preferredInputDeviceCallbackNapi_) {
1415             AUDIO_ERR_LOG("RegisterPreferredInputDeviceChangeCallback: Memory Allocation Failed !!");
1416             return;
1417         }
1418 
1419         int32_t ret = routingMgrNapi->audioRoutingMngr_->SetPreferredInputDeviceChangeCallback(
1420             captureInfo, routingMgrNapi->preferredInputDeviceCallbackNapi_);
1421         if (ret) {
1422             AUDIO_ERR_LOG("Registering Active Input DeviceChange Callback Failed %{public}d", ret);
1423             AudioCommonNapi::throwError(env, ret);
1424             return;
1425         }
1426     }
1427 
1428     std::shared_ptr<AudioPreferredInputDeviceChangeCallbackNapi> cb =
1429         std::static_pointer_cast<AudioPreferredInputDeviceChangeCallbackNapi>(
1430         routingMgrNapi->preferredInputDeviceCallbackNapi_);
1431     cb->SaveCallbackReference(captureInfo.sourceType, args[PARAM2]);
1432 }
1433 
RegisterCallback(napi_env env,napi_value jsThis,size_t argc,napi_value * args,const std::string & cbName)1434 void AudioRoutingManagerNapi::RegisterCallback(napi_env env, napi_value jsThis, size_t argc,
1435     napi_value* args, const std::string& cbName)
1436 {
1437     AudioRoutingManagerNapi* routingMgrNapi = nullptr;
1438     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void**>(&routingMgrNapi));
1439     if ((status != napi_ok) || (routingMgrNapi == nullptr) || (routingMgrNapi->audioMngr_ == nullptr)
1440         || (routingMgrNapi->audioRoutingMngr_ == nullptr)) {
1441         AUDIO_ERR_LOG("AudioRoutingMgrNapi::Failed to retrieve stream mgr napi instance.");
1442 
1443         return;
1444     }
1445 
1446     if (!cbName.compare(DEVICE_CHANGE_CALLBACK_NAME)) {
1447         RegisterDeviceChangeCallback(env, argc, args, cbName, routingMgrNapi);
1448     } else if (!cbName.compare(PREFERRED_OUTPUT_DEVICE_CALLBACK_NAME) ||
1449         !cbName.compare(PREFER_OUTPUT_DEVICE_CALLBACK_NAME)) {
1450         RegisterPreferredOutputDeviceChangeCallback(env, argc, args, cbName, routingMgrNapi);
1451     } else if (!cbName.compare(PREFERRED_INPUT_DEVICE_CALLBACK_NAME)) {
1452         RegisterPreferredInputDeviceChangeCallback(env, argc, args, cbName, routingMgrNapi);
1453     } else {
1454         AUDIO_ERR_LOG("AudioRoutingMgrNapi::No such supported");
1455         AudioCommonNapi::throwError(env, NAPI_ERR_INVALID_PARAM);
1456     }
1457 }
1458 
On(napi_env env,napi_callback_info info)1459 napi_value AudioRoutingManagerNapi::On(napi_env env, napi_callback_info info)
1460 {
1461     AUDIO_INFO_LOG("On inter");
1462 
1463     const size_t requireArgc = PARAM2;
1464     const size_t maxArgc = PARAM3;
1465     size_t argc = PARAM3;
1466 
1467     napi_value undefinedResult = nullptr;
1468     napi_get_undefined(env, &undefinedResult);
1469 
1470     napi_value args[requireArgc + 1] = { nullptr, nullptr, nullptr };
1471     napi_value jsThis = nullptr;
1472     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
1473     bool isArgcCountRight = argc == requireArgc || argc == maxArgc;
1474     THROW_ERROR_ASSERT(env, status == napi_ok && isArgcCountRight, NAPI_ERR_INPUT_INVALID);
1475 
1476     napi_valuetype eventType = napi_undefined;
1477     napi_typeof(env, args[0], &eventType);
1478     THROW_ERROR_ASSERT(env, eventType == napi_string, NAPI_ERR_INPUT_INVALID);
1479     std::string callbackName = AudioCommonNapi::GetStringArgument(env, args[0]);
1480     AUDIO_INFO_LOG("On callbackName: %{public}s", callbackName.c_str());
1481 
1482     if (argc == requireArgc) {
1483         napi_valuetype handler = napi_undefined;
1484         napi_typeof(env, args[1], &handler);
1485         THROW_ERROR_ASSERT(env, handler == napi_function, NAPI_ERR_INPUT_INVALID);
1486     }
1487 
1488     RegisterCallback(env, jsThis, argc, args, callbackName);
1489 
1490     return undefinedResult;
1491 }
1492 
UnregisterDeviceChangeCallback(napi_env env,napi_value callback,AudioRoutingManagerNapi * routingMgrNapi)1493 void AudioRoutingManagerNapi::UnregisterDeviceChangeCallback(napi_env env, napi_value callback,
1494     AudioRoutingManagerNapi* routingMgrNapi)
1495 {
1496     if (routingMgrNapi->deviceChangeCallbackNapi_ != nullptr) {
1497         std::shared_ptr<AudioManagerCallbackNapi> cb =
1498             std::static_pointer_cast<AudioManagerCallbackNapi>(
1499             routingMgrNapi->deviceChangeCallbackNapi_);
1500         if (callback != nullptr) {
1501             cb->RemoveRoutingManagerDeviceChangeCbRef(env, callback);
1502         }
1503         if (callback == nullptr || cb->GetRoutingManagerDeviceChangeCbListSize() == 0) {
1504             int32_t ret = routingMgrNapi->audioMngr_->UnsetDeviceChangeCallback(DeviceFlag::ALL_L_D_DEVICES_FLAG);
1505             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetDeviceChangeCallback Failed");
1506             routingMgrNapi->deviceChangeCallbackNapi_.reset();
1507             routingMgrNapi->deviceChangeCallbackNapi_ = nullptr;
1508 
1509             cb->RemoveAllRoutingManagerDeviceChangeCb();
1510         }
1511     } else {
1512         AUDIO_ERR_LOG("UnregisterDeviceChangeCallback: deviceChangeCallbackNapi_ is null");
1513     }
1514 }
1515 
UnregisterPreferredOutputDeviceChangeCallback(napi_env env,napi_value callback,AudioRoutingManagerNapi * routingMgrNapi)1516 void AudioRoutingManagerNapi::UnregisterPreferredOutputDeviceChangeCallback(napi_env env, napi_value callback,
1517     AudioRoutingManagerNapi* routingMgrNapi)
1518 {
1519     if (routingMgrNapi->preferredOutputDeviceCallbackNapi_ != nullptr) {
1520         std::shared_ptr<AudioPreferredOutputDeviceChangeCallbackNapi> cb =
1521             std::static_pointer_cast<AudioPreferredOutputDeviceChangeCallbackNapi>(
1522             routingMgrNapi->preferredOutputDeviceCallbackNapi_);
1523         if (callback == nullptr) {
1524             int32_t ret = routingMgrNapi->audioRoutingMngr_->UnsetPreferredOutputDeviceChangeCallback();
1525             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetPreferredOutputDeviceChangeCallback Failed");
1526 
1527             routingMgrNapi->preferredOutputDeviceCallbackNapi_.reset();
1528             routingMgrNapi->preferredOutputDeviceCallbackNapi_ = nullptr;
1529             cb->RemoveAllCallbacks();
1530             return;
1531         }
1532         cb->RemoveCallbackReference(env, callback);
1533     } else {
1534         AUDIO_ERR_LOG("UnregisterPreferredOutputDeviceChangeCallback: preferredOutputDeviceCallbackNapi_ is null");
1535     }
1536 }
1537 
UnregisterPreferredInputDeviceChangeCallback(napi_env env,napi_value callback,AudioRoutingManagerNapi * routingMgrNapi)1538 void AudioRoutingManagerNapi::UnregisterPreferredInputDeviceChangeCallback(napi_env env, napi_value callback,
1539     AudioRoutingManagerNapi *routingMgrNapi)
1540 {
1541     if (routingMgrNapi->preferredInputDeviceCallbackNapi_ != nullptr) {
1542         std::shared_ptr<AudioPreferredInputDeviceChangeCallbackNapi> cb =
1543             std::static_pointer_cast<AudioPreferredInputDeviceChangeCallbackNapi>(
1544             routingMgrNapi->preferredInputDeviceCallbackNapi_);
1545         if (callback == nullptr) {
1546             int32_t ret = routingMgrNapi->audioRoutingMngr_->UnsetPreferredInputDeviceChangeCallback();
1547             CHECK_AND_RETURN_LOG(ret == SUCCESS, "UnsetPreferredInputDeviceChangeCallback Failed");
1548 
1549             routingMgrNapi->preferredInputDeviceCallbackNapi_.reset();
1550             routingMgrNapi->preferredInputDeviceCallbackNapi_ = nullptr;
1551             cb->RemoveAllCallbacks();
1552             return;
1553         }
1554         cb->RemoveCallbackReference(env, callback);
1555     } else {
1556         AUDIO_ERR_LOG("UnregisterPreferredInputDeviceChangeCallback: preferredInputDeviceCallbackNapi_ is null");
1557     }
1558 }
1559 
UnregisterCallback(napi_env env,napi_value jsThis,const std::string & callbackName,napi_value callback)1560 napi_value AudioRoutingManagerNapi::UnregisterCallback(napi_env env, napi_value jsThis,
1561     const std::string& callbackName, napi_value callback)
1562 {
1563     napi_value undefinedResult = nullptr;
1564     napi_get_undefined(env, &undefinedResult);
1565     AudioRoutingManagerNapi* routingMgrNapi = nullptr;
1566     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&routingMgrNapi));
1567     NAPI_ASSERT(env, status == napi_ok && routingMgrNapi != nullptr, "Failed to retrieve audio mgr napi instance.");
1568     NAPI_ASSERT(env, routingMgrNapi->audioMngr_ != nullptr, "audio system mgr instance is null.");
1569 
1570     if (!callbackName.compare(DEVICE_CHANGE_CALLBACK_NAME)) {
1571         UnregisterDeviceChangeCallback(env, callback, routingMgrNapi);
1572     } else if (!callbackName.compare(PREFERRED_OUTPUT_DEVICE_CALLBACK_NAME) ||
1573         !callbackName.compare(PREFER_OUTPUT_DEVICE_CALLBACK_NAME)) {
1574         UnregisterPreferredOutputDeviceChangeCallback(env, callback, routingMgrNapi);
1575     } else if (!callbackName.compare(PREFERRED_INPUT_DEVICE_CALLBACK_NAME)) {
1576         UnregisterPreferredInputDeviceChangeCallback(env, callback, routingMgrNapi);
1577     } else {
1578         AUDIO_ERR_LOG("off no such supported");
1579         AudioCommonNapi::throwError(env, NAPI_ERR_INVALID_PARAM);
1580     }
1581 
1582     return undefinedResult;
1583 }
1584 
Off(napi_env env,napi_callback_info info)1585 napi_value AudioRoutingManagerNapi::Off(napi_env env, napi_callback_info info)
1586 {
1587     napi_value undefinedResult = nullptr;
1588     napi_get_undefined(env, &undefinedResult);
1589 
1590     const size_t minArgCount = 1;
1591     size_t argCount = 2;
1592     napi_value args[minArgCount + 1] = {nullptr, nullptr};
1593     napi_value jsThis = nullptr;
1594     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
1595     if (status != napi_ok || argCount < minArgCount) {
1596         AUDIO_ERR_LOG("Off fail to napi_get_cb_info/Requires min 1 parameters");
1597         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
1598         return undefinedResult;
1599     }
1600 
1601     napi_valuetype eventType = napi_undefined;
1602     if (napi_typeof(env, args[PARAM0], &eventType) != napi_ok || eventType != napi_string) {
1603         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
1604         return undefinedResult;
1605     }
1606 
1607     napi_valuetype secondArgsType = napi_undefined;
1608     if (argCount > minArgCount &&
1609         (napi_typeof(env, args[PARAM1], &secondArgsType) != napi_ok || secondArgsType != napi_function)) {
1610         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
1611         return undefinedResult;
1612     }
1613     std::string callbackName = AudioCommonNapi::GetStringArgument(env, args[0]);
1614 
1615     if (argCount == minArgCount) {
1616         args[PARAM1] = nullptr;
1617     }
1618     AUDIO_INFO_LOG("Off callbackName: %{public}s", callbackName.c_str());
1619 
1620     return UnregisterCallback(env, jsThis, callbackName, args[PARAM1]);
1621 }
1622 
SetCommunicationDevice(napi_env env,napi_callback_info info)1623 napi_value AudioRoutingManagerNapi::SetCommunicationDevice(napi_env env, napi_callback_info info)
1624 {
1625     napi_status status;
1626     const int32_t refCount = 1;
1627     napi_value result = nullptr;
1628 
1629     GET_PARAMS(env, info, ARGS_THREE);
1630 
1631     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
1632 
1633     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1634     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1635         if (argc < ARGS_TWO) {
1636             asyncContext->status = NAPI_ERR_INVALID_PARAM;
1637         }
1638         for (size_t i = PARAM0; i < argc; i++) {
1639             napi_valuetype valueType = napi_undefined;
1640             napi_typeof(env, argv[i], &valueType);
1641 
1642             if (i == PARAM0 && valueType == napi_number) {
1643                 napi_get_value_int32(env, argv[i], &asyncContext->deviceType);
1644                 if (!AudioCommonNapi::IsLegalInputArgumentCommunicationDeviceType(asyncContext->deviceType)) {
1645                 asyncContext->status = asyncContext->status ==
1646                     NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED;
1647                 }
1648             } else if (i == PARAM1 && valueType == napi_boolean) {
1649                 napi_get_value_bool(env, argv[i], &asyncContext->isActive);
1650             } else if (i == PARAM2) {
1651                 if (valueType == napi_function) {
1652                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
1653                 }
1654                 break;
1655             } else {
1656                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
1657             }
1658         }
1659 
1660         if (asyncContext->callbackRef == nullptr) {
1661             napi_create_promise(env, &asyncContext->deferred, &result);
1662         } else {
1663             napi_get_undefined(env, &result);
1664         }
1665 
1666         napi_value resource = nullptr;
1667         napi_create_string_utf8(env, "SetCommunicationDeviceActive", NAPI_AUTO_LENGTH, &resource);
1668 
1669         status = napi_create_async_work(
1670             env, nullptr, resource,
1671             [](napi_env env, void *data) {
1672                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
1673                 if (context->status == 0) {
1674                     context->status = context->objectInfo->audioMngr_->SetDeviceActive(
1675                         static_cast<ActiveDeviceType>(context->deviceType), context->isActive);
1676                 }
1677             },
1678             SetFunctionAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1679         if (status != napi_ok) {
1680             result = nullptr;
1681         } else {
1682             status = napi_queue_async_work(env, asyncContext->work);
1683             if (status == napi_ok) {
1684                 asyncContext.release();
1685             } else {
1686                 result = nullptr;
1687             }
1688         }
1689     }
1690 
1691     return result;
1692 }
1693 
IsCommunicationDeviceActive(napi_env env,napi_callback_info info)1694 napi_value AudioRoutingManagerNapi::IsCommunicationDeviceActive(napi_env env, napi_callback_info info)
1695 {
1696     napi_status status;
1697     const int32_t refCount = 1;
1698     napi_value result = nullptr;
1699 
1700     GET_PARAMS(env, info, ARGS_TWO);
1701 
1702     unique_ptr<AudioRoutingManagerAsyncContext> asyncContext = make_unique<AudioRoutingManagerAsyncContext>();
1703 
1704     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
1705     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
1706         if (argc < ARGS_ONE) {
1707             asyncContext->status = NAPI_ERR_INVALID_PARAM;
1708         }
1709         for (size_t i = PARAM0; i < argc; i++) {
1710             napi_valuetype valueType = napi_undefined;
1711             napi_typeof(env, argv[i], &valueType);
1712 
1713             if (i == PARAM0 && valueType == napi_number) {
1714                 napi_get_value_int32(env, argv[i], &asyncContext->deviceType);
1715                 if (!AudioCommonNapi::IsLegalInputArgumentActiveDeviceType(asyncContext->deviceType)) {
1716                     asyncContext->status = asyncContext->status ==
1717                         NAPI_ERR_INVALID_PARAM? NAPI_ERR_INVALID_PARAM : NAPI_ERR_UNSUPPORTED;
1718                 }
1719             } else if (i == PARAM1) {
1720                 if (valueType == napi_function) {
1721                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
1722                 }
1723                 break;
1724             } else {
1725                 asyncContext->status = NAPI_ERR_INVALID_PARAM;
1726             }
1727         }
1728 
1729         if (asyncContext->callbackRef == nullptr) {
1730             napi_create_promise(env, &asyncContext->deferred, &result);
1731         } else {
1732             napi_get_undefined(env, &result);
1733         }
1734 
1735         napi_value resource = nullptr;
1736         napi_create_string_utf8(env, "IsCommunicationDeviceActive", NAPI_AUTO_LENGTH, &resource);
1737 
1738         status = napi_create_async_work(
1739             env, nullptr, resource,
1740             [](napi_env env, void *data) {
1741                 auto context = static_cast<AudioRoutingManagerAsyncContext*>(data);
1742                 if (context->status == SUCCESS) {
1743                     context->isActive = context->objectInfo->audioMngr_->
1744                         IsDeviceActive(static_cast<ActiveDeviceType>(context->deviceType));
1745                     context->isTrue = context->isActive;
1746                     context->status = 0;
1747                 }
1748             },
1749             IsTrueAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
1750         if (status != napi_ok) {
1751             result = nullptr;
1752         } else {
1753             status = napi_queue_async_work(env, asyncContext->work);
1754             if (status == napi_ok) {
1755                 asyncContext.release();
1756             } else {
1757                 result = nullptr;
1758             }
1759         }
1760     }
1761 
1762     return result;
1763 }
1764 
IsCommunicationDeviceActiveSync(napi_env env,napi_callback_info info)1765 napi_value AudioRoutingManagerNapi::IsCommunicationDeviceActiveSync(napi_env env, napi_callback_info info)
1766 {
1767     napi_status status;
1768     napi_value result = nullptr;
1769     void *native = nullptr;
1770 
1771     GET_PARAMS(env, info, ARGS_ONE);
1772 
1773     if (argc < ARGS_ONE) {
1774         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
1775         return result;
1776     }
1777 
1778     status = napi_unwrap(env, thisVar, &native);
1779     auto *audioRoutingManagerNapi = reinterpret_cast<AudioRoutingManagerNapi *>(native);
1780     if (status != napi_ok || audioRoutingManagerNapi == nullptr) {
1781         AUDIO_ERR_LOG("IsCommunicationDeviceActiveSync unwrap failure!");
1782         return result;
1783     }
1784 
1785     napi_valuetype valueType = napi_undefined;
1786     napi_typeof(env, argv[PARAM0], &valueType);
1787     if (valueType != napi_number) {
1788         AudioCommonNapi::throwError(env, NAPI_ERR_INPUT_INVALID);
1789         return result;
1790     }
1791 
1792     int32_t deviceType;
1793     napi_get_value_int32(env, argv[PARAM0], &deviceType);
1794     if (!AudioCommonNapi::IsLegalInputArgumentActiveDeviceType(deviceType)) {
1795         AudioCommonNapi::throwError(env, NAPI_ERR_INVALID_PARAM);
1796         return result;
1797     }
1798 
1799     bool isActive = audioRoutingManagerNapi->audioMngr_->IsDeviceActive(static_cast<ActiveDeviceType>(deviceType));
1800     napi_get_boolean(env, isActive, &result);
1801 
1802     return result;
1803 }
1804 
1805 } // namespace AudioStandard
1806 } // namespace OHOS
1807