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