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