• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef LOG_TAG
16 #define LOG_TAG "NapiAudioSessionMgr"
17 #endif
18 
19 #include "napi_audio_error.h"
20 #include "napi_param_utils.h"
21 #include "napi_audio_enum.h"
22 #include "audio_errors.h"
23 #include "napi_audio_session_callback.h"
24 #include "napi_audio_session_state_callback.h"
25 #include "napi_audio_session_device_callback.h"
26 #include "napi_audio_session_manager.h"
27 
28 namespace OHOS {
29 namespace AudioStandard {
30 using namespace std;
31 using namespace HiviewDFX;
32 static __thread napi_ref g_sessionMgrConstructor = nullptr;
33 
34 const std::string AUDIO_SESSION_MGR_NAPI_CLASS_NAME = "AudioSessionManager";
35 
NapiAudioSessionMgr()36 NapiAudioSessionMgr::NapiAudioSessionMgr()
37     : env_(nullptr), audioSessionMngr_(nullptr) {}
38 
39 NapiAudioSessionMgr::~NapiAudioSessionMgr() = default;
40 
Destructor(napi_env env,void * nativeObject,void * finalizeHint)41 void NapiAudioSessionMgr::Destructor(napi_env env, void *nativeObject, void *finalizeHint)
42 {
43     if (nativeObject == nullptr) {
44         AUDIO_WARNING_LOG("Native object is null");
45         return;
46     }
47     auto obj = static_cast<NapiAudioSessionMgr *>(nativeObject);
48     ObjectRefMap<NapiAudioSessionMgr>::DecreaseRef(obj);
49     AUDIO_INFO_LOG("Decrease obj count");
50 }
51 
Construct(napi_env env,napi_callback_info info)52 napi_value NapiAudioSessionMgr::Construct(napi_env env, napi_callback_info info)
53 {
54     AUDIO_DEBUG_LOG("Construct");
55     napi_status status;
56     napi_value result = nullptr;
57     NapiParamUtils::GetUndefinedValue(env);
58 
59     size_t argc = ARGS_TWO;
60     napi_value argv[ARGS_TWO] = {0};
61     napi_value thisVar = nullptr;
62     void *data = nullptr;
63     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
64     unique_ptr<NapiAudioSessionMgr> napiSessionMgr = make_unique<NapiAudioSessionMgr>();
65     CHECK_AND_RETURN_RET_LOG(napiSessionMgr != nullptr, result, "No memory");
66 
67     napiSessionMgr->env_ = env;
68     napiSessionMgr->audioSessionMngr_ = AudioSessionManager::GetInstance();
69     ObjectRefMap<NapiAudioSessionMgr>::Insert(napiSessionMgr.get());
70 
71     status = napi_wrap(env, thisVar, static_cast<void*>(napiSessionMgr.get()),
72         NapiAudioSessionMgr::Destructor, nullptr, nullptr);
73     if (status != napi_ok) {
74         ObjectRefMap<NapiAudioSessionMgr>::Erase(napiSessionMgr.get());
75         return result;
76     }
77     napiSessionMgr.release();
78     return thisVar;
79 }
80 
Init(napi_env env,napi_value exports)81 napi_value NapiAudioSessionMgr::Init(napi_env env, napi_value exports)
82 {
83     napi_status status;
84     napi_value constructor;
85     napi_value result = nullptr;
86     const int32_t refCount = ARGS_ONE;
87     napi_get_undefined(env, &result);
88 
89     napi_property_descriptor audio_session_mgr_properties[] = {
90         DECLARE_NAPI_FUNCTION("on", On),
91         DECLARE_NAPI_FUNCTION("off", Off),
92         DECLARE_NAPI_FUNCTION("activateAudioSession", ActivateAudioSession),
93         DECLARE_NAPI_FUNCTION("deactivateAudioSession", DeactivateAudioSession),
94         DECLARE_NAPI_FUNCTION("isAudioSessionActivated", IsAudioSessionActivated),
95         DECLARE_NAPI_FUNCTION("setAudioSessionScene", SetAudioSessionScene),
96         DECLARE_NAPI_FUNCTION("getDefaultOutputDevice", GetDefaultOutputDevice),
97         DECLARE_NAPI_FUNCTION("setDefaultOutputDevice", SetDefaultOutputDevice),
98     };
99 
100     status = napi_define_class(env, AUDIO_SESSION_MGR_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct, nullptr,
101         sizeof(audio_session_mgr_properties) / sizeof(audio_session_mgr_properties[PARAM0]),
102         audio_session_mgr_properties, &constructor);
103     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_define_class fail");
104 
105     status = napi_create_reference(env, constructor, refCount, &g_sessionMgrConstructor);
106     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_create_reference fail");
107     status = napi_set_named_property(env, exports, AUDIO_SESSION_MGR_NAPI_CLASS_NAME.c_str(), constructor);
108     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_set_named_property fail");
109     return exports;
110 }
111 
CreateSessionManagerWrapper(napi_env env)112 napi_value NapiAudioSessionMgr::CreateSessionManagerWrapper(napi_env env)
113 {
114     napi_status status;
115     napi_value result = nullptr;
116     napi_value constructor;
117 
118     status = napi_get_reference_value(env, g_sessionMgrConstructor, &constructor);
119     if (status != napi_ok) {
120         AUDIO_ERR_LOG("Failed in CreateSessionManagerWrapper, %{public}d", status);
121         goto fail;
122     }
123     status = napi_new_instance(env, constructor, PARAM0, nullptr, &result);
124     if (status != napi_ok) {
125         AUDIO_ERR_LOG("napi_new_instance failed, status:%{public}d", status);
126         goto fail;
127     }
128     return result;
129 
130 fail:
131     napi_get_undefined(env, &result);
132     return result;
133 }
134 
CheckContextStatus(std::shared_ptr<AudioSessionMgrAsyncContext> context)135 bool NapiAudioSessionMgr::CheckContextStatus(std::shared_ptr<AudioSessionMgrAsyncContext> context)
136 {
137     CHECK_AND_RETURN_RET_LOG(context != nullptr, false, "context object is nullptr.");
138     if (context->native == nullptr) {
139         context->SignError(NAPI_ERR_SYSTEM);
140         return false;
141     }
142     return true;
143 }
144 
CheckAudioSessionStatus(NapiAudioSessionMgr * napi,std::shared_ptr<AudioSessionMgrAsyncContext> context)145 bool NapiAudioSessionMgr::CheckAudioSessionStatus(NapiAudioSessionMgr *napi,
146     std::shared_ptr<AudioSessionMgrAsyncContext> context)
147 {
148     CHECK_AND_RETURN_RET_LOG(napi != nullptr, false, "napi object is nullptr.");
149     if (napi->audioSessionMngr_ == nullptr) {
150         context->SignError(NAPI_ERR_SYSTEM);
151         return false;
152     }
153     return true;
154 }
155 
ActivateAudioSession(napi_env env,napi_callback_info info)156 napi_value NapiAudioSessionMgr::ActivateAudioSession(napi_env env, napi_callback_info info)
157 {
158     auto context = std::make_shared<AudioSessionMgrAsyncContext>();
159     if (context == nullptr) {
160         AUDIO_ERR_LOG("ActivateAudioSession failed : no memory");
161         NapiAudioError::ThrowError(env, "ActivateAudioSession failed : no memory", NAPI_ERR_NO_MEMORY);
162         return NapiParamUtils::GetUndefinedValue(env);
163     }
164 
165     auto inputParser = [env, context](size_t argc, napi_value *argv) {
166         NAPI_CHECK_ARGS_RETURN_VOID(context, argc >= ARGS_ONE, "invalid arguments",
167             NAPI_ERR_INPUT_INVALID);
168         context->status = NapiParamUtils::GetAudioSessionStrategy(env, context->audioSessionStrategy, argv[PARAM0]);
169         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "getAudioSessionStrategy failed",
170             NAPI_ERR_INVALID_PARAM);
171     };
172     context->GetCbInfo(env, info, inputParser);
173 
174     if ((context->status != napi_ok) && (context->errCode == NAPI_ERR_INPUT_INVALID)) {
175         NapiAudioError::ThrowError(env, context->errCode, context->errMessage);
176         return NapiParamUtils::GetUndefinedValue(env);
177     }
178 
179     auto executor = [context]() {
180         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
181         auto obj = reinterpret_cast<NapiAudioSessionMgr*>(context->native);
182         ObjectRefMap objectGuard(obj);
183         auto *napiSessionMgr = objectGuard.GetPtr();
184         if (napiSessionMgr == nullptr || napiSessionMgr->audioSessionMngr_ == nullptr) {
185             context->SignError(NAPI_ERR_SYSTEM, "System error. Internal variable exception.");
186             AUDIO_ERR_LOG("The napiSessionMgr or audioSessionMngr is nullptr");
187             return;
188         }
189         context->intValue = napiSessionMgr->audioSessionMngr_->ActivateAudioSession(context->audioSessionStrategy);
190         if (context->intValue != SUCCESS) {
191             context->SignError(NAPI_ERR_SYSTEM, "System error. Set app volume fail.");
192         }
193     };
194 
195     auto complete = [env, context](napi_value &output) {
196         NapiParamUtils::SetValueInt32(env, context->intValue, output);
197     };
198     return NapiAsyncWork::Enqueue(env, context, "ActivateAudioSession", executor, complete);
199 }
200 
DeactivateAudioSession(napi_env env,napi_callback_info info)201 napi_value NapiAudioSessionMgr::DeactivateAudioSession(napi_env env, napi_callback_info info)
202 {
203     auto context = std::make_shared<AudioSessionMgrAsyncContext>();
204     if (context == nullptr) {
205         AUDIO_ERR_LOG("DeactivateAudioSession failed : no memory");
206         NapiAudioError::ThrowError(env, "DeactivateAudioSession failed : no memory",
207             NAPI_ERR_NO_MEMORY);
208         return NapiParamUtils::GetUndefinedValue(env);
209     }
210     context->GetCbInfo(env, info);
211 
212     auto executor = [context]() {
213         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
214         auto obj = reinterpret_cast<NapiAudioSessionMgr*>(context->native);
215         ObjectRefMap objectGuard(obj);
216         auto *napiSessionMgr = objectGuard.GetPtr();
217         if (napiSessionMgr == nullptr || napiSessionMgr->audioSessionMngr_ == nullptr) {
218             context->SignError(NAPI_ERR_SYSTEM, "System error. Internal variable exception.");
219             AUDIO_ERR_LOG("The napiSessionMgr or audioSessionMngr is nullptr");
220             return;
221         }
222         context->intValue = napiSessionMgr->audioSessionMngr_->DeactivateAudioSession();
223         if (context->intValue != SUCCESS) {
224             context->SignError(NAPI_ERR_SYSTEM, "System error. Set app volume fail.");
225         }
226     };
227 
228     auto complete = [env, context](napi_value &output) {
229         NapiParamUtils::SetValueInt32(env, context->intValue, output);
230     };
231     return NapiAsyncWork::Enqueue(env, context, "DeactivateAudioSession", executor, complete);
232 }
233 
IsAudioSessionActivated(napi_env env,napi_callback_info info)234 napi_value NapiAudioSessionMgr::IsAudioSessionActivated(napi_env env, napi_callback_info info)
235 {
236     napi_value result = nullptr;
237     auto context = std::make_shared<AudioSessionMgrAsyncContext>();
238     if (context == nullptr) {
239         AUDIO_ERR_LOG("IsAudioSessionActivated failed : no memory");
240         NapiAudioError::ThrowError(env, "IsAudioSessionActivated failed : no memory",
241             NAPI_ERR_NO_MEMORY);
242         return NapiParamUtils::GetUndefinedValue(env);
243     }
244     context->GetCbInfo(env, info);
245 
246     CHECK_AND_RETURN_RET_LOG(CheckContextStatus(context), result,  "context object state is error.");
247     auto obj = reinterpret_cast<NapiAudioSessionMgr*>(context->native);
248     ObjectRefMap objectGuard(obj);
249     auto *napiSessionMgr = objectGuard.GetPtr();
250     if (napiSessionMgr == nullptr || napiSessionMgr->audioSessionMngr_ == nullptr) {
251         AUDIO_ERR_LOG("The napiSessionMgr or audioSessionMngr is nullptr");
252         return nullptr;
253     }
254     context->isActive = napiSessionMgr->audioSessionMngr_->IsAudioSessionActivated();
255     NapiParamUtils::SetValueBoolean(env, context->isActive, result);
256     return result;
257 }
258 
RegisterCallback(napi_env env,napi_value jsThis,napi_value * args,const std::string & cbName)259 void NapiAudioSessionMgr::RegisterCallback(napi_env env, napi_value jsThis,
260     napi_value *args, const std::string &cbName)
261 {
262     if (!cbName.compare(AUDIOSESSION_CALLBACK_NAME)) {
263         NapiAudioSessionMgr *napiSessionMgr = nullptr;
264         napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiSessionMgr));
265         CHECK_AND_RETURN_LOG((status == napi_ok) && (napiSessionMgr != nullptr) &&
266             (napiSessionMgr->audioSessionMngr_ != nullptr), "Failed to retrieve session mgr napi instance.");
267         RegisterAudioSessionCallback(env, args, cbName, napiSessionMgr);
268     } else if (!cbName.compare(AUDIOSESSION_STATE_CALLBACK_NAME)) {
269         NapiAudioSessionMgr *napiSessionMgr = nullptr;
270         napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiSessionMgr));
271         if ((status != napi_ok) || (napiSessionMgr == nullptr) || (napiSessionMgr->audioSessionMngr_ == nullptr)) {
272             AUDIO_ERR_LOG("NapiAudioSessionMgr can not get session mgr napi instance");
273             NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM, "can not get session mgr napi instance");
274             return;
275         }
276         RegisterAudioSessionStateCallback(env, args, cbName, napiSessionMgr);
277     } else if (!cbName.compare(AUDIOSESSION_DEVICE_CALLBACK_NAME)) {
278         NapiAudioSessionMgr *napiSessionMgr = nullptr;
279         napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiSessionMgr));
280         if ((status != napi_ok) || (napiSessionMgr == nullptr) || (napiSessionMgr->audioSessionMngr_ == nullptr)) {
281             AUDIO_ERR_LOG("NapiAudioSessionMgr can not get session mgr napi instance");
282             NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM, "can not get session mgr napi instance");
283             return;
284         }
285         RegisterAudioSessionDeviceCallback(env, args, cbName, napiSessionMgr);
286     } else {
287         AUDIO_ERR_LOG("NapiAudioSessionMgr::No such callback supported");
288         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
289             "parameter verification failed: The param of type is not supported");
290     }
291 }
292 
RegisterAudioSessionCallback(napi_env env,napi_value * args,const std::string & cbName,NapiAudioSessionMgr * napiSessionMgr)293 void NapiAudioSessionMgr::RegisterAudioSessionCallback(napi_env env, napi_value *args,
294     const std::string &cbName, NapiAudioSessionMgr *napiSessionMgr)
295 {
296     if (!napiSessionMgr->audioSessionCallbackNapi_) {
297         napiSessionMgr->audioSessionCallbackNapi_ = std::make_shared<NapiAudioSessionCallback>(env);
298         CHECK_AND_RETURN_LOG(napiSessionMgr->audioSessionCallbackNapi_ != nullptr,
299             "NapiAudioSessionMgr: Memory Allocation Failed !!");
300 
301         int32_t ret =
302             napiSessionMgr->audioSessionMngr_->SetAudioSessionCallback(napiSessionMgr->audioSessionCallbackNapi_);
303         CHECK_AND_RETURN_LOG(ret == SUCCESS, "Registering of AudioSessionDeactiveEvent Callback Failed");
304     }
305 
306     std::shared_ptr<NapiAudioSessionCallback> cb =
307         std::static_pointer_cast<NapiAudioSessionCallback>(napiSessionMgr->audioSessionCallbackNapi_);
308     cb->SaveCallbackReference(args[PARAM1]);
309     if (!cb->GetAudioSessionTsfnFlag()) {
310         cb->CreateAudioSessionTsfn(env);
311     }
312 
313     AUDIO_INFO_LOG("OnRendererStateChangeCallback is successful");
314 }
315 
RegisterAudioSessionStateCallback(napi_env env,napi_value * args,const std::string & cbName,NapiAudioSessionMgr * napiSessionMgr)316 void NapiAudioSessionMgr::RegisterAudioSessionStateCallback(napi_env env, napi_value *args,
317     const std::string &cbName, NapiAudioSessionMgr *napiSessionMgr)
318 {
319     if (args[PARAM1] == nullptr) {
320         AUDIO_ERR_LOG("OnAudioSessionStateChangeCallback failed, callback function is nullptr");
321         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM, "callback function is nullptr");
322         return;
323     }
324 
325     std::lock_guard<std::mutex> lock(napiSessionMgr->sessionStateCbMutex_);
326     CHECK_AND_RETURN_LOG(GetAudioSessionStateCallback(args[PARAM1], napiSessionMgr) == nullptr,
327         "The callback function already registered.");
328 
329     std::shared_ptr<AudioSessionStateChangedCallback> stateChangedCallback =
330         std::make_shared<NapiAudioSessionStateCallback>(env);
331     if (stateChangedCallback == nullptr) {
332         AUDIO_ERR_LOG("NapiAudioSessionMgr: Memory Allocation Failed!");
333         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY, "Memory Allocation Failed!");
334         return;
335     }
336 
337     int32_t ret = napiSessionMgr->audioSessionMngr_->SetAudioSessionStateChangeCallback(stateChangedCallback);
338     if (ret != SUCCESS) {
339         AUDIO_ERR_LOG("SetAudioSessionStateChangeCallback is failed, ret = %{public}d", ret);
340         NapiAudioError::ThrowError(env, NAPI_ERR_SYSTEM);
341         return;
342     }
343 
344     std::shared_ptr<NapiAudioSessionStateCallback> cb =
345         std::static_pointer_cast<NapiAudioSessionStateCallback>(stateChangedCallback);
346     napiSessionMgr->sessionStateCallbackList_.push_back(cb);
347     cb->SaveCallbackReference(args[PARAM1]);
348     if (!cb->GetAudioSessionStateTsfnFlag()) {
349         cb->CreateAudioSessionStateTsfn(env);
350     }
351 
352     AUDIO_INFO_LOG("OnAudioSessionStateChangeCallback is successful");
353 }
354 
RegisterAudioSessionDeviceCallback(napi_env env,napi_value * args,const std::string & cbName,NapiAudioSessionMgr * napiSessionMgr)355 void NapiAudioSessionMgr::RegisterAudioSessionDeviceCallback(napi_env env, napi_value *args,
356     const std::string &cbName, NapiAudioSessionMgr *napiSessionMgr)
357 {
358     if (args[PARAM1] == nullptr) {
359         AUDIO_ERR_LOG("OnAudioSessionDeviceCallback failed, callback function is nullptr");
360         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM, "callback function is nullptr");
361         return;
362     }
363 
364     std::lock_guard<std::mutex> lock(napiSessionMgr->sessionDeviceCbMutex_);
365     CHECK_AND_RETURN_LOG(GetAudioSessionDeviceCallback(args[PARAM1], napiSessionMgr) == nullptr,
366         "The callback function already registered.");
367 
368     std::shared_ptr<AudioSessionCurrentDeviceChangedCallback> deviceChangedCallback =
369         std::make_shared<NapiAudioSessionDeviceCallback>(env);
370     if (deviceChangedCallback == nullptr) {
371         AUDIO_ERR_LOG("NapiAudioSessionMgr: Memory Allocation Failed!");
372         NapiAudioError::ThrowError(env, NAPI_ERR_NO_MEMORY, "Memory Allocation Failed!");
373         return;
374     }
375 
376     int32_t ret = napiSessionMgr->audioSessionMngr_->SetAudioSessionCurrentDeviceChangeCallback(deviceChangedCallback);
377     if (ret != SUCCESS) {
378         AUDIO_ERR_LOG("RegisterAudioSessionDeviceCallback is failed, ret = %{public}d", ret);
379         NapiAudioError::ThrowError(env, NAPI_ERR_SYSTEM);
380         return;
381     }
382 
383     std::shared_ptr<NapiAudioSessionDeviceCallback> cb =
384         std::static_pointer_cast<NapiAudioSessionDeviceCallback>(deviceChangedCallback);
385     napiSessionMgr->sessionDeviceCallbackList_.push_back(cb);
386     cb->SaveCallbackReference(args[PARAM1]);
387     if (!cb->GetAudioSessionDeviceTsfnFlag()) {
388         cb->CreateAudioSessionDeviceTsfn(env);
389     }
390 
391     AUDIO_INFO_LOG("RegisterAudioSessionDeviceCallback is successful");
392 }
393 
On(napi_env env,napi_callback_info info)394 napi_value NapiAudioSessionMgr::On(napi_env env, napi_callback_info info)
395 {
396     const size_t requireArgc = ARGS_TWO;
397     size_t argc = ARGS_THREE;
398 
399     napi_value undefinedResult = nullptr;
400     napi_get_undefined(env, &undefinedResult);
401 
402     napi_value args[requireArgc + PARAM1] = {nullptr, nullptr, nullptr};
403     napi_value jsThis = nullptr;
404     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
405     CHECK_AND_RETURN_RET_LOG(status == napi_ok && argc == requireArgc, NapiAudioError::ThrowErrorAndReturn(env,
406         NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified"),
407         "status for arguments error");
408 
409     napi_valuetype eventType = napi_undefined;
410     napi_typeof(env, args[PARAM0], &eventType);
411     CHECK_AND_RETURN_RET_LOG(eventType == napi_string, NapiAudioError::ThrowErrorAndReturn(env,
412         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of eventType must be string"),
413         "eventType error");
414     std::string callbackName = NapiParamUtils::GetStringArgument(env, args[PARAM0]);
415     AUDIO_DEBUG_LOG("AudioStreamMgrNapi: On callbackName: %{public}s", callbackName.c_str());
416 
417     napi_valuetype handler = napi_undefined;
418     napi_typeof(env, args[PARAM1], &handler);
419     CHECK_AND_RETURN_RET_LOG(
420         handler == napi_function, NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
421         "incorrect parameter types: The type of handler must be function"), "handler is invalid");
422     RegisterCallback(env, jsThis, args, callbackName);
423     return undefinedResult;
424 }
425 
UnregisterCallback(napi_env env,napi_value jsThis)426 void NapiAudioSessionMgr::UnregisterCallback(napi_env env, napi_value jsThis)
427 {
428     AUDIO_INFO_LOG("UnregisterCallback");
429     NapiAudioSessionMgr *napiSessionMgr = nullptr;
430     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiSessionMgr));
431     CHECK_AND_RETURN_LOG((status == napi_ok) && (napiSessionMgr != nullptr) &&
432         (napiSessionMgr->audioSessionMngr_ != nullptr), "Failed to retrieve session mgr  instance.");
433 
434     int32_t ret = napiSessionMgr->audioSessionMngr_->UnsetAudioSessionCallback();
435     if (ret) {
436         AUDIO_ERR_LOG("Unset AudioSessionCallback Failed");
437         return;
438     }
439     if (napiSessionMgr->audioSessionCallbackNapi_ != nullptr) {
440         napiSessionMgr->audioSessionCallbackNapi_.reset();
441         napiSessionMgr->audioSessionCallbackNapi_ = nullptr;
442     }
443     AUDIO_ERR_LOG("Unset AudioSessionCallback Success");
444 }
445 
UnregisterCallbackCarryParam(napi_env env,napi_value jsThis,napi_value * args,size_t len)446 void NapiAudioSessionMgr::UnregisterCallbackCarryParam(napi_env env, napi_value jsThis, napi_value *args, size_t len)
447 {
448     AUDIO_INFO_LOG("UnregisterCallback");
449     NapiAudioSessionMgr *napiSessionMgr = nullptr;
450     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiSessionMgr));
451     CHECK_AND_RETURN_LOG((status == napi_ok) && (napiSessionMgr != nullptr) &&
452         (napiSessionMgr->audioSessionMngr_ != nullptr), "Failed to retrieve session mgr  instance.");
453     if (!napiSessionMgr->audioSessionCallbackNapi_) {
454         napiSessionMgr->audioSessionCallbackNapi_ = std::make_shared<NapiAudioSessionCallback>(env);
455         CHECK_AND_RETURN_LOG(napiSessionMgr->audioSessionCallbackNapi_ != nullptr,
456             "Memory Allocation Failed !!");
457         int32_t ret =
458             napiSessionMgr->audioSessionMngr_->UnsetAudioSessionCallback(napiSessionMgr->audioSessionCallbackNapi_);
459         CHECK_AND_RETURN_LOG(ret == SUCCESS, "Unregister Callback CarryParam Failed");
460     }
461     std::shared_ptr<NapiAudioSessionCallback> cb =
462         std::static_pointer_cast<NapiAudioSessionCallback>(napiSessionMgr->audioSessionCallbackNapi_);
463     cb->SaveCallbackReference(args[PARAM0]);
464     AUDIO_ERR_LOG("Unset AudioSessionCallback Success");
465 }
466 
UnregisterSessionStateCallback(napi_env env,napi_value jsThis)467 void NapiAudioSessionMgr::UnregisterSessionStateCallback(napi_env env, napi_value jsThis)
468 {
469     AUDIO_INFO_LOG("UnregisterCallback state");
470     NapiAudioSessionMgr *napiSessionMgr = nullptr;
471     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiSessionMgr));
472     if ((status != napi_ok) || (napiSessionMgr == nullptr) || (napiSessionMgr->audioSessionMngr_ == nullptr)) {
473         AUDIO_ERR_LOG("NapiAudioSessionMgr can not get session mgr napi instance");
474         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM, "can not get session mgr napi instance");
475         return;
476     }
477 
478     std::lock_guard<std::mutex> lock(napiSessionMgr->sessionStateCbMutex_);
479     CHECK_AND_RETURN_LOG(!napiSessionMgr->sessionStateCallbackList_.empty(),
480         "Not register callback function, no need unregister.");
481 
482     int32_t ret = napiSessionMgr->audioSessionMngr_->UnsetAudioSessionStateChangeCallback();
483     if (ret != SUCCESS) {
484         AUDIO_ERR_LOG("UnsetAudioSessionStateChangeCallback Failed, ret = %{public}d", ret);
485         NapiAudioError::ThrowError(env, NAPI_ERR_SYSTEM);
486         return;
487     }
488 
489     for (auto it = napiSessionMgr->sessionStateCallbackList_.rbegin();
490         it != napiSessionMgr->sessionStateCallbackList_.rend(); ++it) {
491         std::shared_ptr<NapiAudioSessionStateCallback> cb =
492             std::static_pointer_cast<NapiAudioSessionStateCallback>(*it);
493         cb.reset();
494     }
495     napiSessionMgr->sessionStateCallbackList_.clear();
496 
497     AUDIO_ERR_LOG("UnregisterSessionStateCallback Success");
498 }
499 
UnregisterSessionStateCallbackCarryParam(napi_env env,napi_value jsThis,napi_value * args,size_t len)500 void NapiAudioSessionMgr::UnregisterSessionStateCallbackCarryParam(
501     napi_env env, napi_value jsThis, napi_value *args, size_t len)
502 {
503     AUDIO_INFO_LOG("UnregisterCallback StateChanged.");
504     if (args[PARAM1] == nullptr) {
505         AUDIO_ERR_LOG("UnregisterSessionStateCallbackCarryParam failed, callback function is nullptr");
506         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM, "callback function is nullptr");
507         return;
508     }
509 
510     NapiAudioSessionMgr *napiSessionMgr = nullptr;
511     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiSessionMgr));
512     if ((status != napi_ok) || (napiSessionMgr == nullptr) || (napiSessionMgr->audioSessionMngr_ == nullptr)) {
513         AUDIO_ERR_LOG("NapiAudioSessionMgr can not get session mgr napi instance");
514         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM, "can not get session mgr napi instance");
515         return;
516     }
517 
518     std::lock_guard<std::mutex> lock(napiSessionMgr->sessionStateCbMutex_);
519     std::shared_ptr<NapiAudioSessionStateCallback> cb = GetAudioSessionStateCallback(args[PARAM1], napiSessionMgr);
520     CHECK_AND_RETURN_LOG(cb != nullptr, "The callback function not registered.");
521     std::shared_ptr<AudioSessionStateChangedCallback> stateChangedCallback =
522         std::static_pointer_cast<AudioSessionStateChangedCallback>(cb);
523 
524     int32_t ret = napiSessionMgr->audioSessionMngr_->UnsetAudioSessionStateChangeCallback(stateChangedCallback);
525     if (ret != SUCCESS) {
526         AUDIO_ERR_LOG("UnregisterSessionStateCallbackCarryParam Failed, ret = %{public}d", ret);
527         NapiAudioError::ThrowError(env, NAPI_ERR_SYSTEM);
528         return;
529     }
530 
531     napiSessionMgr->sessionStateCallbackList_.remove(cb);
532     cb.reset();
533 
534     AUDIO_ERR_LOG("UnregisterSessionStateCallbackCarryParam Success");
535 }
536 
UnregisterSessionDeviceCallback(napi_env env,napi_value jsThis)537 void NapiAudioSessionMgr::UnregisterSessionDeviceCallback(napi_env env, napi_value jsThis)
538 {
539     AUDIO_INFO_LOG("UnregisterCallback device");
540     NapiAudioSessionMgr *napiSessionMgr = nullptr;
541     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiSessionMgr));
542     if ((status != napi_ok) || (napiSessionMgr == nullptr) || (napiSessionMgr->audioSessionMngr_ == nullptr)) {
543         AUDIO_ERR_LOG("NapiAudioSessionMgr can not get session mgr napi instance");
544         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM, "can not get session mgr napi instance");
545         return;
546     }
547 
548     std::lock_guard<std::mutex> lock(napiSessionMgr->sessionDeviceCbMutex_);
549     CHECK_AND_RETURN_LOG(!napiSessionMgr->sessionDeviceCallbackList_.empty(),
550         "Not register callback function, no need unregister.");
551 
552     int32_t ret = napiSessionMgr->audioSessionMngr_->UnsetAudioSessionCurrentDeviceChangeCallback();
553     if (ret != SUCCESS) {
554         AUDIO_ERR_LOG("UnregisterSessionDeviceCallback is failed, ret = %{public}d", ret);
555         NapiAudioError::ThrowError(env, NAPI_ERR_SYSTEM);
556         return;
557     }
558 
559     for (auto it = napiSessionMgr->sessionDeviceCallbackList_.rbegin();
560         it != napiSessionMgr->sessionDeviceCallbackList_.rend(); ++it) {
561         std::shared_ptr<NapiAudioSessionDeviceCallback> cb =
562             std::static_pointer_cast<NapiAudioSessionDeviceCallback>(*it);
563         cb.reset();
564     }
565     napiSessionMgr->sessionDeviceCallbackList_.clear();
566 
567     AUDIO_ERR_LOG("UnregisterSessionDeviceCallback Success");
568 }
569 
UnregisterSessionDeviceCallbackCarryParam(napi_env env,napi_value jsThis,napi_value * args,size_t len)570 void NapiAudioSessionMgr::UnregisterSessionDeviceCallbackCarryParam(
571     napi_env env, napi_value jsThis, napi_value *args, size_t len)
572 {
573     AUDIO_INFO_LOG("UnregisterCallback device changed.");
574     if (args[PARAM1] == nullptr) {
575         AUDIO_ERR_LOG("UnregisterSessionDeviceCallbackCarryParam failed, callback function is nullptr");
576         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM, "callback function is nullptr");
577         return;
578     }
579 
580     NapiAudioSessionMgr *napiSessionMgr = nullptr;
581     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&napiSessionMgr));
582     if ((status != napi_ok) || (napiSessionMgr == nullptr) || (napiSessionMgr->audioSessionMngr_ == nullptr)) {
583         AUDIO_ERR_LOG("NapiAudioSessionMgr can not get session mgr napi instance");
584         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM, "can not get session mgr napi instance");
585         return;
586     }
587 
588     std::lock_guard<std::mutex> lock(napiSessionMgr->sessionDeviceCbMutex_);
589     std::shared_ptr<NapiAudioSessionDeviceCallback> cb = GetAudioSessionDeviceCallback(args[PARAM1], napiSessionMgr);
590     CHECK_AND_RETURN_LOG(cb != nullptr, "The callback function not registered.");
591     std::shared_ptr<AudioSessionCurrentDeviceChangedCallback> deviceCallback =
592         std::static_pointer_cast<AudioSessionCurrentDeviceChangedCallback>(cb);
593 
594     int32_t ret = napiSessionMgr->audioSessionMngr_->UnsetAudioSessionCurrentDeviceChangeCallback(deviceCallback);
595     if (ret != SUCCESS) {
596         AUDIO_ERR_LOG("UnsetAudioSessionCurrentDeviceChangeCallback is failed, ret = %{public}d", ret);
597         NapiAudioError::ThrowError(env, NAPI_ERR_SYSTEM);
598         return;
599     }
600 
601     napiSessionMgr->sessionDeviceCallbackList_.remove(cb);
602     cb.reset();
603 
604     AUDIO_ERR_LOG("UnregisterSessionDeviceCallbackCarryParam Success");
605 }
606 
Off(napi_env env,napi_callback_info info)607 napi_value NapiAudioSessionMgr::Off(napi_env env, napi_callback_info info)
608 {
609     const size_t requireArgc = ARGS_ONE;
610     size_t argc = PARAM2;
611 
612     napi_value undefinedResult = nullptr;
613     napi_get_undefined(env, &undefinedResult);
614 
615     napi_value args[requireArgc + PARAM1] = {nullptr, nullptr};
616     napi_value jsThis = nullptr;
617     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
618     if (status != napi_ok || argc < requireArgc) {
619         AUDIO_ERR_LOG("Off fail to napi_get_cb_info/Requires min 1 parameters");
620         NapiAudioError::ThrowError(env, NAPI_ERR_INPUT_INVALID, "mandatory parameters are left unspecified");
621         return undefinedResult;
622     }
623 
624     napi_valuetype eventType = napi_undefined;
625     napi_typeof(env, args[PARAM0], &eventType);
626     CHECK_AND_RETURN_RET_LOG(eventType == napi_string, NapiAudioError::ThrowErrorAndReturn(env,
627         NAPI_ERR_INPUT_INVALID, "incorrect parameter types: The type of eventType must be string"), "event error");
628     std::string callbackName = NapiParamUtils::GetStringArgument(env, args[PARAM0]);
629     if (!callbackName.compare(AUDIOSESSION_CALLBACK_NAME)) {
630         napi_valuetype handler = napi_undefined;
631         napi_typeof(env, args[PARAM1], &handler);
632         if (handler == napi_function) {
633             UnregisterCallbackCarryParam(env, jsThis, args, sizeof(args));
634         } else {
635             UnregisterCallback(env, jsThis);
636         }
637     } else if (!callbackName.compare(AUDIOSESSION_STATE_CALLBACK_NAME)) {
638         napi_valuetype handler = napi_undefined;
639         napi_typeof(env, args[PARAM1], &handler);
640         if (handler == napi_function) {
641             UnregisterSessionStateCallbackCarryParam(env, jsThis, args, sizeof(args));
642         } else {
643             UnregisterSessionStateCallback(env, jsThis);
644         }
645     } else if (!callbackName.compare(AUDIOSESSION_DEVICE_CALLBACK_NAME)) {
646         napi_valuetype handler = napi_undefined;
647         napi_typeof(env, args[PARAM1], &handler);
648         if (handler == napi_function) {
649             UnregisterSessionDeviceCallbackCarryParam(env, jsThis, args, sizeof(args));
650         } else {
651             UnregisterSessionDeviceCallback(env, jsThis);
652         }
653     } else {
654         AUDIO_ERR_LOG("NapiAudioSessionMgr::No such callback supported");
655         NapiAudioError::ThrowError(env, NAPI_ERR_INVALID_PARAM,
656             "parameter verification failed: The param of type is not supported");
657     }
658     return undefinedResult;
659 }
660 
SetAudioSessionScene(napi_env env,napi_callback_info info)661 napi_value NapiAudioSessionMgr::SetAudioSessionScene(napi_env env, napi_callback_info info)
662 {
663     napi_value result = nullptr;
664     size_t argc = ARGS_ONE;
665     napi_value args[ARGS_ONE] = {};
666     auto *napiSessionMgr = GetParamWithSync(env, info, argc, args);
667     CHECK_AND_RETURN_RET_LOG(argc >= ARGS_ONE, NapiAudioError::ThrowErrorAndReturn(env,
668         NAPI_ERR_INVALID_PARAM, "argcCount invalid"), "argcCount invalid");
669 
670     int32_t scene;
671     napi_status status = NapiParamUtils::GetValueInt32(env, scene, args[PARAM0]);
672     CHECK_AND_RETURN_RET_LOG((status == napi_ok) && NapiAudioEnum::IsLegalInputArgumentSessionScene(scene),
673         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_INVALID_PARAM,
674         "parameter verification failed: The param of scene must be enum AudioSessionScene"),
675         "valueType invalid");
676 
677     CHECK_AND_RETURN_RET_LOG(napiSessionMgr != nullptr, NapiAudioError::ThrowErrorAndReturn(env,
678         NAPI_ERR_INVALID_PARAM, "can not get session"), "napiSessionMgr is nullptr");
679     CHECK_AND_RETURN_RET_LOG(napiSessionMgr->audioSessionMngr_ != nullptr, NapiAudioError::ThrowErrorAndReturn(env,
680         NAPI_ERR_INVALID_PARAM, "can not get session"), "audioSessionMngr_ is nullptr");
681 
682     int32_t ret = napiSessionMgr->audioSessionMngr_->SetAudioSessionScene(static_cast<AudioSessionScene>(scene));
683     if (ret == ERR_NOT_SUPPORTED) {
684         AUDIO_ERR_LOG("SetAudioSessionScene Failed, not supported ret = %{public}d", ret);
685         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_ILLEGAL_STATE);
686     } else if (ret != SUCCESS) {
687         AUDIO_ERR_LOG("SetAudioSessionScene Failed, ret = %{public}d", ret);
688         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_SYSTEM);
689     }
690 
691     return result;
692 }
693 
GetParamWithSync(const napi_env & env,napi_callback_info info,size_t & argc,napi_value * args)694 NapiAudioSessionMgr *NapiAudioSessionMgr::GetParamWithSync(const napi_env &env, napi_callback_info info,
695     size_t &argc, napi_value *args)
696 {
697     NapiAudioSessionMgr *napiSessionMgr = nullptr;
698     napi_value jsThis = nullptr;
699 
700     napi_status status = napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr);
701     CHECK_AND_RETURN_RET_LOG((status == napi_ok) && jsThis != nullptr, nullptr,
702         "GetParamWithSync fail to napi_get_cb_info");
703 
704     status = napi_unwrap(env, jsThis, (void **)&napiSessionMgr);
705     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "napi_unwrap failed");
706     CHECK_AND_RETURN_RET_LOG(napiSessionMgr != nullptr && napiSessionMgr->audioSessionMngr_ != nullptr,
707         napiSessionMgr, "GetParamWithSync fail to napi_unwrap");
708     return napiSessionMgr;
709 }
710 
GetDefaultOutputDevice(napi_env env,napi_callback_info info)711 napi_value NapiAudioSessionMgr::GetDefaultOutputDevice(napi_env env, napi_callback_info info)
712 {
713     napi_value result = nullptr;
714     size_t argc = PARAM0;
715     auto *napiSessionMgr = GetParamWithSync(env, info, argc, nullptr);
716     CHECK_AND_RETURN_RET_LOG(argc == PARAM0, NapiAudioError::ThrowErrorAndReturn(env,
717         NAPI_ERR_INVALID_PARAM, "argcCount invalid"), "argcCount invalid");
718 
719     CHECK_AND_RETURN_RET_LOG(napiSessionMgr != nullptr, NapiAudioError::ThrowErrorAndReturn(env,
720         NAPI_ERR_INVALID_PARAM, "can not get session"), "napiSessionMgr is nullptr");
721     CHECK_AND_RETURN_RET_LOG(napiSessionMgr->audioSessionMngr_ != nullptr, NapiAudioError::ThrowErrorAndReturn(env,
722         NAPI_ERR_INVALID_PARAM, "can not get session"), "audioSessionMngr_ is nullptr");
723 
724     DeviceType deviceType = DeviceType::DEVICE_TYPE_INVALID;
725     int32_t ret = napiSessionMgr->audioSessionMngr_->GetDefaultOutputDevice(deviceType);
726     if (ret != SUCCESS) {
727         AUDIO_ERR_LOG("GetDefaultOutputDevice Failed, ret = %{public}d", ret);
728         NapiAudioError::ThrowErrorAndReturn(env, NAPI_ERR_ILLEGAL_STATE, "get deviceType state error");
729         return result;
730     }
731     AUDIO_INFO_LOG("GetDefaultOutputDevice successful, deviceType = %{public}d.", static_cast<int32_t>(deviceType));
732 
733     NapiParamUtils::SetValueInt32(env, deviceType, result);
734     return result;
735 }
736 
SetDefaultOutputDevice(napi_env env,napi_callback_info info)737 napi_value NapiAudioSessionMgr::SetDefaultOutputDevice(napi_env env, napi_callback_info info)
738 {
739     auto context = std::make_shared<AudioSessionMgrAsyncContext>();
740     if (context == nullptr) {
741         AUDIO_ERR_LOG("SetDefaultOutputDevice failed : no memory");
742         NapiAudioError::ThrowError(env, "SetDefaultOutputDevice failed : no memory", NAPI_ERR_NO_MEMORY);
743         return NapiParamUtils::GetUndefinedValue(env);
744     }
745 
746     auto inputParser = [env, context](size_t argc, napi_value *argv) {
747         NAPI_CHECK_ARGS_RETURN_VOID(context, argc == ARGS_ONE, "invalid arguments", NAPI_ERR_INVALID_PARAM);
748         context->status = NapiParamUtils::GetValueInt32(env, context->deviceType, argv[PARAM0]);
749         NAPI_CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok,
750             "incorrect parameter types: The type of mode must be number", NAPI_ERR_INVALID_PARAM);
751         NAPI_CHECK_ARGS_RETURN_VOID(context,
752             NapiAudioEnum::IsLegalInputArgumentDefaultOutputDeviceType(context->deviceType),
753             "parameter verification failed: The param of mode must be enum deviceType",
754             NAPI_ERR_INVALID_PARAM);
755     };
756     context->GetCbInfo(env, info, inputParser);
757 
758     if ((context->status != napi_ok) && (context->errCode == NAPI_ERR_INVALID_PARAM)) {
759         NapiAudioError::ThrowError(env, context->errCode, context->errMessage);
760         return NapiParamUtils::GetUndefinedValue(env);
761     }
762 
763     auto executor = [context]() {
764         CHECK_AND_RETURN_LOG(CheckContextStatus(context), "context object state is error.");
765         auto obj = reinterpret_cast<NapiAudioSessionMgr*>(context->native);
766         ObjectRefMap objectGuard(obj);
767         auto *napiSessionMgr = objectGuard.GetPtr();
768         CHECK_AND_RETURN_LOG(CheckAudioSessionStatus(napiSessionMgr, context),
769             "context object state is error.");
770         DeviceType deviceType = static_cast<DeviceType>(context->deviceType);
771         context->intValue = napiSessionMgr->audioSessionMngr_->SetDefaultOutputDevice(deviceType);
772         if (context->intValue != SUCCESS) {
773             context->SignError(NAPI_ERR_SYSTEM);
774         }
775     };
776 
777     auto complete = [env](napi_value &output) {
778         output = NapiParamUtils::GetUndefinedValue(env);
779     };
780     return NapiAsyncWork::Enqueue(env, context, "SetDefaultOutputDevice", executor, complete);
781 }
782 
GetAudioSessionStateCallback(napi_value argv,NapiAudioSessionMgr * napiSessionMgr)783 std::shared_ptr<NapiAudioSessionStateCallback> NapiAudioSessionMgr::GetAudioSessionStateCallback(
784     napi_value argv, NapiAudioSessionMgr *napiSessionMgr)
785 {
786     std::shared_ptr<NapiAudioSessionStateCallback> cb = nullptr;
787     for (auto &iter : napiSessionMgr->sessionStateCallbackList_) {
788         if (iter == nullptr) {
789             continue;
790         }
791 
792         if (iter->ContainSameJsCallback(argv)) {
793             cb = iter;
794         }
795     }
796     return cb;
797 }
798 
GetAudioSessionDeviceCallback(napi_value argv,NapiAudioSessionMgr * napiSessionMgr)799 std::shared_ptr<NapiAudioSessionDeviceCallback> NapiAudioSessionMgr::GetAudioSessionDeviceCallback(
800     napi_value argv, NapiAudioSessionMgr *napiSessionMgr)
801 {
802     std::shared_ptr<NapiAudioSessionDeviceCallback> cb = nullptr;
803     for (auto &iter : napiSessionMgr->sessionDeviceCallbackList_) {
804         if (iter == nullptr) {
805             continue;
806         }
807 
808         if (iter->ContainSameJsCallback(argv)) {
809             cb = iter;
810         }
811     }
812     return cb;
813 }
814 
815 }  // namespace AudioStandard
816 }  // namespace OHOS
817