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