• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "napi_avsession_manager.h"
17 #include "avcontrol_command.h"
18 #include "avplayback_state.h"
19 #include "avsession_errors.h"
20 #include "key_event.h"
21 #include "ability.h"
22 #include "napi_base_context.h"
23 #include "napi_utils.h"
24 #include "napi_async_work.h"
25 #include "napi_avsession.h"
26 #include "napi_avsession_controller.h"
27 #include "napi_control_command.h"
28 #include "avsession_trace.h"
29 #include "avsession_sysevent.h"
30 #include "ipc_skeleton.h"
31 #include "tokenid_kit.h"
32 
33 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
34 #include "napi_avcast_controller.h"
35 #endif
36 
37 namespace OHOS::AVSession {
38 using namespace Security::AccessToken;
39 std::map<std::string, std::pair<NapiAVSessionManager::OnEventHandlerType, NapiAVSessionManager::OffEventHandlerType>>
40     NapiAVSessionManager::eventHandlers_ = {
41     { "sessionCreate", { OnSessionCreate, OffSessionCreate } },
42     { "sessionDestroy", { OnSessionDestroy, OffSessionDestroy } },
43     { "topSessionChange", { OnTopSessionChange, OffTopSessionChange } },
44     { "sessionServiceDie", { OnServiceDie, OffServiceDie } },
45     { "deviceAvailable", { OnDeviceAvailable, OffDeviceAvailable } },
46     { "deviceOffline", { OnDeviceOffline, OffDeviceOffline } },
47 };
48 
49 std::shared_ptr<NapiSessionListener> NapiAVSessionManager::listener_;
50 std::shared_ptr<NapiAsyncCallback> NapiAVSessionManager::asyncCallback_;
51 std::list<napi_ref> NapiAVSessionManager::serviceDiedCallbacks_;
52 
53 std::map<int32_t, int32_t> NapiAVSessionManager::errcode_ = {
54     {AVSESSION_ERROR, 6600101},
55     {ERR_NO_MEMORY, 6600101},
56     {ERR_SERVICE_NOT_EXIST, 6600101},
57     {ERR_SESSION_LISTENER_EXIST, 6600101},
58     {ERR_MARSHALLING, 6600101},
59     {ERR_UNMARSHALLING, 6600101},
60     {ERR_IPC_SEND_REQUEST, 6600101},
61     {ERR_CONTROLLER_IS_EXIST, 6600101},
62     {ERR_START_ABILITY_IS_RUNNING, 6600101},
63     {ERR_ABILITY_NOT_AVAILABLE, 6600101},
64     {ERR_START_ABILITY_TIMEOUT, 6600101},
65     {ERR_SESSION_NOT_EXIST, 6600102},
66     {ERR_CONTROLLER_NOT_EXIST, 6600103},
67     {ERR_RPC_SEND_REQUEST, 6600104},
68     {ERR_COMMAND_NOT_SUPPORT, 6600105},
69     {ERR_SESSION_DEACTIVE, 6600106},
70     {ERR_COMMAND_SEND_EXCEED_MAX, 6600107},
71     {ERR_DEVICE_CONNECTION_FAILED, 6600108},
72     {ERR_REMOTE_CONNECTION_NOT_EXIST, 6600109},
73     {ERR_NO_PERMISSION, 202},
74     {ERR_INVALID_PARAM, 401},
75 };
Init(napi_env env,napi_value exports)76 napi_value NapiAVSessionManager::Init(napi_env env, napi_value exports)
77 {
78     napi_property_descriptor descriptors[] = {
79         DECLARE_NAPI_STATIC_FUNCTION("createAVSession", CreateAVSession),
80         DECLARE_NAPI_STATIC_FUNCTION("getAllSessionDescriptors", GetAllSessionDescriptors),
81         DECLARE_NAPI_STATIC_FUNCTION("getHistoricalSessionDescriptors", GetHistoricalSessionDescriptors),
82         DECLARE_NAPI_STATIC_FUNCTION("createController", CreateController),
83         DECLARE_NAPI_STATIC_FUNCTION("getAVCastController", GetAVCastController),
84         DECLARE_NAPI_STATIC_FUNCTION("castAudio", CastAudio),
85         DECLARE_NAPI_STATIC_FUNCTION("on", OnEvent),
86         DECLARE_NAPI_STATIC_FUNCTION("off", OffEvent),
87         DECLARE_NAPI_STATIC_FUNCTION("sendSystemAVKeyEvent", SendSystemAVKeyEvent),
88         DECLARE_NAPI_STATIC_FUNCTION("sendSystemControlCommand", SendSystemControlCommand),
89         DECLARE_NAPI_STATIC_FUNCTION("startCastDeviceDiscovery", StartCastDiscovery),
90         DECLARE_NAPI_STATIC_FUNCTION("stopCastDeviceDiscovery", StopCastDiscovery),
91         DECLARE_NAPI_STATIC_FUNCTION("setDiscoverable", SetDiscoverable),
92         DECLARE_NAPI_STATIC_FUNCTION("startCasting", StartCast),
93         DECLARE_NAPI_STATIC_FUNCTION("stopCasting", StopCast),
94     };
95 
96     napi_status status = napi_define_properties(env, exports, sizeof(descriptors) / sizeof(napi_property_descriptor),
97                                                 descriptors);
98     if (status != napi_ok) {
99         SLOGE("define manager properties failed");
100         return NapiUtils::GetUndefinedValue(env);
101     }
102     return exports;
103 }
104 
CreateAVSession(napi_env env,napi_callback_info info)105 napi_value NapiAVSessionManager::CreateAVSession(napi_env env, napi_callback_info info)
106 {
107     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::CreateAVSession");
108     struct ConcreteContext : public ContextBase {
109         std::string tag_;
110         int32_t type_{};
111         AppExecFwk::ElementName elementName_;
112         std::shared_ptr<AVSession> session_;
113     };
114     auto context = std::make_shared<ConcreteContext>();
115     context->taskId = NAPI_CREATE_AVSESSION_TASK_ID;
116 
117     auto inputParser = [env, context](size_t argc, napi_value* argv) {
118         // require 3 arguments <context> <tag> <type>
119         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_THREE, "invalid arguments",
120             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
121         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->elementName_);
122         CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "invalid context",
123             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
124         context->status = NapiUtils::GetValue(env, argv[ARGV_SECOND], context->tag_);
125         CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok && !context->tag_.empty(), "invalid tag",
126             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
127         std::string typeString;
128         context->status = NapiUtils::GetValue(env, argv[ARGV_THIRD], typeString);
129         CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok && !typeString.empty(), "invalid type",
130             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
131         context->type_ = NapiUtils::ConvertSessionType(typeString);
132         CHECK_ARGS_RETURN_VOID(context, context->type_ >= 0, "wrong session type",
133             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
134         context->status = napi_ok;
135     };
136     context->GetCbInfo(env, info, inputParser);
137 
138     auto executor = [context]() {
139         context->session_ = AVSessionManager::GetInstance().CreateSession(context->tag_, context->type_,
140                                                                           context->elementName_);
141         if (context->session_ == nullptr) {
142             context->status = napi_generic_failure;
143             context->errMessage = "CreateAVSession failed : native create session failed";
144             context->errCode = NapiAVSessionManager::errcode_[AVSESSION_ERROR];
145         }
146     };
147 
148     auto complete = [context](napi_value& output) {
149         context->status = NapiAVSession::NewInstance(context->env, context->session_, output);
150         CHECK_STATUS_RETURN_VOID(context, "convert native object to javascript object failed",
151             NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
152     };
153 
154     return NapiAsyncWork::Enqueue(env, context, "CreateAVSession", executor, complete);
155 }
156 
GetAllSessionDescriptors(napi_env env,napi_callback_info info)157 napi_value NapiAVSessionManager::GetAllSessionDescriptors(napi_env env, napi_callback_info info)
158 {
159     struct ConcreteContext : public ContextBase {
160         std::vector<AVSessionDescriptor> descriptors_;
161     };
162     auto context = std::make_shared<ConcreteContext>();
163     context->GetCbInfo(env, info);
164 
165     auto executor = [context]() {
166         int32_t ret = AVSessionManager::GetInstance().GetAllSessionDescriptors(context->descriptors_);
167         if (ret != AVSESSION_SUCCESS) {
168             if (ret == ERR_NO_PERMISSION) {
169                 context->errMessage = "GetAllSessionDescriptors failed : native no permission";
170             } else {
171                 context->errMessage = "GetAllSessionDescriptors failed : native server exception";
172             }
173             context->status = napi_generic_failure;
174             context->errCode = NapiAVSessionManager::errcode_[ret];
175         }
176     };
177 
178     auto complete = [env, context](napi_value& output) {
179         context->status = NapiUtils::SetValue(env, context->descriptors_, output);
180         CHECK_STATUS_RETURN_VOID(context, "convert native object to javascript object failed",
181             NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
182     };
183 
184     return NapiAsyncWork::Enqueue(env, context, "GetAllSessionDescriptors", executor, complete);
185 }
186 
GetHistoricalSessionDescriptors(napi_env env,napi_callback_info info)187 napi_value NapiAVSessionManager::GetHistoricalSessionDescriptors(napi_env env, napi_callback_info info)
188 {
189     struct ConcreteContext : public ContextBase {
190         int32_t maxSize_ {};
191         std::vector<AVSessionDescriptor> descriptors_;
192     };
193     auto context = std::make_shared<ConcreteContext>();
194 
195     auto input = [env, context](size_t argc, napi_value* argv) {
196         if (argc == ARGC_ONE && !NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_undefined)
197             && !NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_null)) {
198             context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->maxSize_);
199             CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "invalid arguments",
200                 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
201             CHECK_ARGS_RETURN_VOID(context,
202                 (context->maxSize_ >= (int32_t)HISTORICAL_MIN_NUM && context->maxSize_ <= (int32_t)HISTORICAL_MAX_NUM),
203                 "invalid arguments", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
204         } else {
205             context->maxSize_ = HISTORICAL_UNSET_NUM;
206         }
207     };
208 
209     context->GetCbInfo(env, info, input);
210 
211     auto executor = [context]() {
212         int32_t ret = AVSessionManager::GetInstance().GetHistoricalSessionDescriptors(context->maxSize_,
213             context->descriptors_);
214         if (ret != AVSESSION_SUCCESS) {
215             if (ret == ERR_NO_PERMISSION) {
216                 context->errMessage = "GetHistoricalSessionDescriptors failed : native no permission";
217             } else {
218                 context->errMessage = "GetHistoricalSessionDescriptors failed : native server exception";
219             }
220             context->status = napi_generic_failure;
221             context->errCode = NapiAVSessionManager::errcode_[ret];
222         }
223     };
224 
225     auto complete = [env, context](napi_value& output) {
226         context->status = NapiUtils::SetValue(env, context->descriptors_, output);
227         CHECK_STATUS_RETURN_VOID(context, "convert native object to javascript object failed",
228             NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
229     };
230 
231     return NapiAsyncWork::Enqueue(env, context, "GetHistoricalSessionDescriptors", executor, complete);
232 }
233 
CreateController(napi_env env,napi_callback_info info)234 napi_value NapiAVSessionManager::CreateController(napi_env env, napi_callback_info info)
235 {
236     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::CreateController");
237     struct ConcreteContext : public ContextBase {
238         std::string sessionId_ {};
239         std::shared_ptr<AVSessionController> controller_;
240     };
241     auto context = std::make_shared<ConcreteContext>();
242     auto input = [env, context](size_t argc, napi_value* argv) {
243         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE, "invalid arguments",
244             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
245         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->sessionId_);
246         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (!context->sessionId_.empty()),
247                                "invalid sessionId", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
248     };
249     context->GetCbInfo(env, info, input);
250     context->taskId = NAPI_CREATE_CONTROLLER_TASK_ID;
251 
252     auto executor = [context]() {
253         int32_t ret = AVSessionManager::GetInstance().CreateController(context->sessionId_, context->controller_);
254         if (ret != AVSESSION_SUCCESS) {
255             if (ret == ERR_NO_PERMISSION) {
256                 context->errMessage = "CreateController failed : native no permission";
257             } else if (ret == ERR_INVALID_PARAM) {
258                 context->errMessage = "CreateController failed : native invalid parameters";
259             } else if (ret == ERR_SESSION_NOT_EXIST) {
260                 context->errMessage = "CreateController failed : native session not exist";
261             } else {
262                 context->errMessage = "CreateController failed : native server exception";
263             }
264             context->status = napi_generic_failure;
265             context->errCode = NapiAVSessionManager::errcode_[ret];
266         }
267     };
268 
269     auto complete = [env, context](napi_value& output) {
270         context->status = NapiAVSessionController::NewInstance(env, context->controller_, output);
271         CHECK_STATUS_RETURN_VOID(context, "convert native object to javascript object failed",
272             NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
273     };
274 
275     return NapiAsyncWork::Enqueue(env, context, "CreateController", executor, complete);
276 }
277 
GetAVCastController(napi_env env,napi_callback_info info)278 napi_value NapiAVSessionManager::GetAVCastController(napi_env env, napi_callback_info info)
279 {
280 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
281     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::GetAVCastController");
282     struct ConcreteContext : public ContextBase {
283         std::string sessionId_ {};
284         std::shared_ptr<AVCastController> castController_;
285     };
286     auto context = std::make_shared<ConcreteContext>();
287     auto input = [env, context](size_t argc, napi_value* argv) {
288         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE, "invalid arguments",
289             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
290         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->sessionId_);
291         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (!context->sessionId_.empty()),
292             "invalid sessionId", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
293     };
294     context->GetCbInfo(env, info, input);
295     context->taskId = NAPI_CREATE_CAST_CONTROLLER_TASK_ID;
296 
297     auto executor = [context]() {
298         int32_t ret = AVSessionManager::GetInstance().GetAVCastController(context->sessionId_,
299             context->castController_);
300         if (ret != AVSESSION_SUCCESS) {
301             if (ret == ERR_NO_PERMISSION) {
302                 context->errMessage = "GetAVCastController failed : native no permission";
303             } else if (ret == ERR_INVALID_PARAM) {
304                 context->errMessage = "GetAVCastController failed : native invalid parameters";
305             } else if (ret == ERR_SESSION_NOT_EXIST) {
306                 context->errMessage = "GetAVCastController failed : native session not exist";
307             } else {
308                 context->errMessage = "GetAVCastController failed : native server exception";
309             }
310             context->status = napi_generic_failure;
311             context->errCode = NapiAVSessionManager::errcode_[ret];
312         }
313     };
314 
315     auto complete = [env, context](napi_value& output) {
316         context->status = NapiAVCastController::NewInstance(env, context->castController_, output);
317         CHECK_STATUS_RETURN_VOID(context, "convert native object to javascript object failed",
318             NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
319     };
320 
321     return NapiAsyncWork::Enqueue(env, context, "GetAVCastController", executor, complete);
322 #else
323     return nullptr;
324 #endif
325 }
326 
CastAudio(napi_env env,napi_callback_info info)327 napi_value NapiAVSessionManager::CastAudio(napi_env env, napi_callback_info info)
328 {
329     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::CastAudio");
330     struct ConcreteContext : public ContextBase {
331         SessionToken sessionToken_ {};
332         bool isAll_ = false;
333         std::vector<AudioStandard::AudioDeviceDescriptor> audioDeviceDescriptors_;
334     };
335     auto context = std::make_shared<ConcreteContext>();
336     auto input = [env, context](size_t argc, napi_value* argv) {
337         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_TWO, "invalid arguments",
338             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
339         napi_valuetype type = napi_undefined;
340         context->status = napi_typeof(env, argv[ARGV_FIRST], &type);
341         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (type == napi_string || type == napi_object),
342                                "invalid type invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
343         if (type == napi_string) {
344             std::string flag;
345             context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], flag);
346             CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (flag == "all"),
347                                    "invalid argument", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
348             context->isAll_ = true;
349         }
350         if (type == napi_object) {
351             context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->sessionToken_);
352             CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (!context->sessionToken_.sessionId.empty()),
353                                    "invalid session token", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
354         }
355         context->status = NapiUtils::GetValue(env, argv[ARGV_SECOND], context->audioDeviceDescriptors_);
356         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (context->audioDeviceDescriptors_.size() > 0),
357                                "invalid AudioDeviceDescriptor", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
358     };
359     context->GetCbInfo(env, info, input);
360     context->taskId = NAPI_CAST_AUDIO_TASK_ID;
361     auto executor = [context]() {
362         int32_t ret = AVSESSION_ERROR;
363         if (context->isAll_) {
364             ret = AVSessionManager::GetInstance().CastAudioForAll(context->audioDeviceDescriptors_);
365         } else {
366             ret = AVSessionManager::GetInstance().CastAudio(context->sessionToken_, context->audioDeviceDescriptors_);
367         }
368         if (ret != AVSESSION_SUCCESS) {
369             ErrCodeToMessage(ret, "CastAudio", context->errMessage);
370             context->status = napi_generic_failure;
371             context->errCode = NapiAVSessionManager::errcode_[ret];
372         }
373     };
374     auto complete = [env](napi_value& output) { output = NapiUtils::GetUndefinedValue(env); };
375     return NapiAsyncWork::Enqueue(env, context, "CastAudio", executor, complete);
376 }
377 
ErrCodeToMessage(int32_t errCode,const std::string & tag,std::string & message)378 void NapiAVSessionManager::ErrCodeToMessage(int32_t errCode, const std::string& tag, std::string& message)
379 {
380     message = tag;
381     SLOGE("check error code for message:%{public}d", errCode);
382     switch (errCode) {
383         case ERR_SESSION_NOT_EXIST:
384             message.append(" failed : native session not exist");
385             break;
386         case ERR_INVALID_PARAM:
387             message.append(" failed : native invalid parameters");
388             break;
389         case ERR_NO_PERMISSION:
390             message.append(" failed : native no permission");
391             break;
392         default:
393             message.append(" failed : native server exception");
394             break;
395     }
396 }
397 
RegisterNativeSessionListener(napi_env env)398 napi_status NapiAVSessionManager::RegisterNativeSessionListener(napi_env env)
399 {
400     if (listener_ != nullptr) {
401         return napi_ok;
402     }
403 
404     listener_ = std::make_shared<NapiSessionListener>();
405     if (listener_ == nullptr) {
406         SLOGE("OnEvent failed : no memory");
407         NapiUtils::ThrowError(env, "OnEvent failed : no memory", NapiAVSessionManager::errcode_[ERR_NO_MEMORY]);
408         return napi_generic_failure;
409     }
410     int32_t ret = AVSessionManager::GetInstance().RegisterSessionListener(listener_);
411     if (ret != AVSESSION_SUCCESS) {
412         SLOGE("native register session listener failed");
413         if (ret == ERR_INVALID_PARAM) {
414             NapiUtils::ThrowError(env, "OnEvent failed : native invalid parameters",
415                 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
416         } else if (ret == ERR_NO_PERMISSION) {
417             NapiUtils::ThrowError(env, "OnEvent failed : native no permission",
418                 NapiAVSessionManager::errcode_[ERR_NO_PERMISSION]);
419         } else {
420             NapiUtils::ThrowError(env, "OnEvent failed : native server exception",
421                 NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
422         }
423         return napi_generic_failure;
424     }
425 
426     return napi_ok;
427 }
428 
OnEvent(napi_env env,napi_callback_info info)429 napi_value NapiAVSessionManager::OnEvent(napi_env env, napi_callback_info info)
430 {
431     auto context = std::make_shared<ContextBase>();
432     if (context == nullptr) {
433         SLOGE("OnEvent failed : no memory");
434         NapiUtils::ThrowError(env, "OnEvent failed : no memory", NapiAVSessionManager::errcode_[ERR_NO_MEMORY]);
435         return NapiUtils::GetUndefinedValue(env);
436     }
437 
438     std::string eventName;
439     napi_value callback = nullptr;
440     auto input = [&eventName, &callback, env, &context](size_t argc, napi_value* argv) {
441         uint64_t fullTokenId = IPCSkeleton::GetCallingFullTokenID();
442         bool isSystemApp = TokenIdKit::IsSystemAppByFullTokenID(fullTokenId);
443         CHECK_ARGS_RETURN_VOID(context, isSystemApp, "Check system permission error",
444             NapiAVSessionManager::errcode_[ERR_NO_PERMISSION]);
445 
446         /* require 2 arguments <event, callback> */
447         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_TWO, "invalid argument number",
448             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
449         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], eventName);
450         CHECK_STATUS_RETURN_VOID(context, "get event name failed", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
451         napi_valuetype type = napi_undefined;
452         context->status = napi_typeof(env, argv[ARGV_SECOND], &type);
453         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (type == napi_function),
454                                "callback type invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
455         callback = argv[ARGV_SECOND];
456     };
457 
458     context->GetCbInfo(env, info, input, true);
459     if (context->status != napi_ok) {
460         NapiUtils::ThrowError(env, context->errMessage.c_str(), context->errCode);
461         return NapiUtils::GetUndefinedValue(env);
462     }
463 
464     auto it = eventHandlers_.find(eventName);
465     if (it == eventHandlers_.end()) {
466         SLOGE("event name invalid");
467         NapiUtils::ThrowError(env, "event name invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
468         return NapiUtils::GetUndefinedValue(env);
469     }
470 
471     if (RegisterNativeSessionListener(env) == napi_generic_failure) {
472         return NapiUtils::GetUndefinedValue(env);
473     }
474 
475     if (it->second.first(env, callback) != napi_ok) {
476         NapiUtils::ThrowError(env, "add event callback failed", NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
477     }
478 
479     return NapiUtils::GetUndefinedValue(env);
480 }
481 
OffEvent(napi_env env,napi_callback_info info)482 napi_value NapiAVSessionManager::OffEvent(napi_env env, napi_callback_info info)
483 {
484     auto context = std::make_shared<ContextBase>();
485     if (context == nullptr) {
486         SLOGE("OnEvent failed : no memory");
487         NapiUtils::ThrowError(env, "OnEvent failed : no memory", NapiAVSessionManager::errcode_[ERR_NO_MEMORY]);
488         return NapiUtils::GetUndefinedValue(env);
489     }
490 
491     std::string eventName;
492     napi_value callback = nullptr;
493     auto input = [&eventName, env, &context, &callback](size_t argc, napi_value* argv) {
494         uint64_t fullTokenId = IPCSkeleton::GetCallingFullTokenID();
495         bool isSystemApp = TokenIdKit::IsSystemAppByFullTokenID(fullTokenId);
496         CHECK_ARGS_RETURN_VOID(context, isSystemApp, "Check system permission error",
497             NapiAVSessionManager::errcode_[ERR_NO_PERMISSION]);
498 
499         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE || argc == ARGC_TWO, "invalid argument number",
500             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
501         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], eventName);
502         CHECK_STATUS_RETURN_VOID(context, "get event name failed",
503             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
504         if (argc == ARGC_TWO) {
505             callback = argv[ARGV_SECOND];
506         }
507     };
508 
509     context->GetCbInfo(env, info, input, true);
510     if (context->status != napi_ok) {
511         NapiUtils::ThrowError(env, context->errMessage.c_str(), context->errCode);
512         return NapiUtils::GetUndefinedValue(env);
513     }
514 
515     auto it = eventHandlers_.find(eventName);
516     if (it == eventHandlers_.end()) {
517         SLOGE("event name invalid");
518         NapiUtils::ThrowError(env, "event name invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
519         return NapiUtils::GetUndefinedValue(env);
520     }
521 
522     if (it->second.second(env, callback) != napi_ok) {
523         NapiUtils::ThrowError(env, "remove event callback failed", NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
524     }
525 
526     return NapiUtils::GetUndefinedValue(env);
527 }
528 
SendSystemAVKeyEvent(napi_env env,napi_callback_info info)529 napi_value NapiAVSessionManager::SendSystemAVKeyEvent(napi_env env, napi_callback_info info)
530 {
531     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::SendSystemAVKeyEvent");
532     struct ConcreteContext : public ContextBase {
533         std::shared_ptr<MMI::KeyEvent> keyEvent_;
534     };
535     auto context = std::make_shared<ConcreteContext>();
536     auto input = [env, context](size_t argc, napi_value* argv) {
537         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE, "invalid arguments",
538             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
539         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->keyEvent_);
540         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (context->keyEvent_ != nullptr),
541                                "invalid keyEvent", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
542     };
543     context->GetCbInfo(env, info, input);
544     context->taskId = NAPI_SEND_SYSTEM_AV_KEY_EVENT_TASK_ID;
545 
546     auto executor = [context]() {
547         int32_t ret = AVSessionManager::GetInstance().SendSystemAVKeyEvent(*context->keyEvent_);
548         if (ret != AVSESSION_SUCCESS) {
549             if (ret == ERR_COMMAND_NOT_SUPPORT) {
550                 context->errMessage = "SendSystemAVKeyEvent failed : native invalid keyEvent";
551             } else if (ret == ERR_NO_PERMISSION) {
552                 context->errMessage = "SendSystemAVKeyEvent failed : native no permission";
553             } else {
554                 context->errMessage = "SendSystemAVKeyEvent failed : native server exception";
555             }
556             context->status = napi_generic_failure;
557             context->errCode = NapiAVSessionManager::errcode_[ret];
558         }
559     };
560 
561     return NapiAsyncWork::Enqueue(env, context, "SendSystemAVKeyEvent", executor);
562 }
563 
SendSystemControlCommand(napi_env env,napi_callback_info info)564 napi_value NapiAVSessionManager::SendSystemControlCommand(napi_env env, napi_callback_info info)
565 {
566     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::SendSystemControlCommand");
567     struct ConcrentContext : public ContextBase {
568         AVControlCommand command;
569     };
570     auto context = std::make_shared<ConcrentContext>();
571     auto input = [env, context](size_t argc, napi_value* argv) {
572         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE, "invalid arguments",
573             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
574         context->status = NapiControlCommand::GetValue(env, argv[ARGV_FIRST], context->command);
575         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok), "invalid command",
576             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
577     };
578     context->GetCbInfo(env, info, input);
579     context->taskId = NAPI_SEND_SYSTEM_CONTROL_COMMAND_TASK_ID;
580 
581     auto executor = [context]() {
582         int32_t ret = AVSessionManager::GetInstance().SendSystemControlCommand(context->command);
583 #ifdef ENABLE_AVSESSION_SYSEVENT_CONTROL
584             double speed;
585             int64_t time;
586             int32_t mode;
587             std::string assetId;
588             context->command.GetSpeed(speed);
589             context->command.GetSeekTime(time);
590             context->command.GetLoopMode(mode);
591             context->command.GetAssetId(assetId);
592             HISYSEVENT_FAULT("CONTROL_COMMAND_FAILED", "ERROR_TYPE", "SEND_CMD_FAILED",
593                 "CMD", context->command.GetCommand(), "TIME", time, "SPEED", speed, "MODE", mode, "ASSETID", assetId,
594                 "ERROR_CODE", ret, "ERROR_INFO", "native send control command failed");
595 #endif
596         if (ret != AVSESSION_SUCCESS) {
597             if (ret == ERR_COMMAND_NOT_SUPPORT) {
598                 context->errMessage = "SendSystemControlCommand failed : native invalid command";
599             } else if (ret == ERR_NO_PERMISSION) {
600                 context->errMessage = "SendSystemControlCommand failed : native send control command no permission";
601                 HISYSEVENT_SECURITY("CONTROL_PERMISSION_DENIED", "ERROR_CODE", ret,
602                                     "ERROR_INFO", "SendSystemControlCommand failed : native no permission");
603             } else if (ret == ERR_COMMAND_SEND_EXCEED_MAX) {
604                 context->errMessage = "SendSystemControlCommand failed : native send command overload";
605             } else {
606                 context->errMessage = "SendSystemControlCommand failed : native server exception";
607             }
608             context->status = napi_generic_failure;
609             context->errCode = NapiAVSessionManager::errcode_[ret];
610         }
611     };
612 
613     return NapiAsyncWork::Enqueue(env, context, "SendSystemControlCommand", executor);
614 }
615 
StartCastDiscovery(napi_env env,napi_callback_info info)616 napi_value NapiAVSessionManager::StartCastDiscovery(napi_env env, napi_callback_info info)
617 {
618 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
619     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::StartCastDiscovery");
620     struct ConcreteContext : public ContextBase {
621         int32_t castDeviceCapability_;
622     };
623     auto context = std::make_shared<ConcreteContext>();
624     auto input = [env, context](size_t argc, napi_value* argv) {
625         if (argc == ARGC_ONE && !NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_undefined)
626             && !NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_null)) {
627             context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->castDeviceCapability_);
628             CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "invalid castDeviceCapability",
629                 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
630         } else {
631             context->castDeviceCapability_ = ProtocolType::TYPE_CAST_PLUS_STREAM;
632         }
633     };
634     context->GetCbInfo(env, info, input);
635     context->taskId = NAPI_START_CAST_DISCOVERY_TASK_ID;
636 
637     auto executor = [context]() {
638         int32_t ret = AVSessionManager::GetInstance().StartCastDiscovery(context->castDeviceCapability_);
639         if (ret != AVSESSION_SUCCESS) {
640             if (ret == ERR_NO_PERMISSION) {
641                 context->errMessage = "StartCastDiscovery failed : native no permission";
642             } else if (ret == ERR_INVALID_PARAM) {
643                 context->errMessage = "StartCastDiscovery failed : native invalid parameters";
644             } else if (ret == ERR_SESSION_NOT_EXIST) {
645                 context->errMessage = "StartCastDiscovery failed : native session not exist";
646             } else {
647                 context->errMessage = "StartCastDiscovery failed : native server exception";
648             }
649             context->status = napi_generic_failure;
650             context->errCode = NapiAVSessionManager::errcode_[ret];
651         }
652     };
653     return NapiAsyncWork::Enqueue(env, context, "StartCastDiscovery", executor);
654 #else
655     return nullptr;
656 #endif
657 }
658 
StopCastDiscovery(napi_env env,napi_callback_info info)659 napi_value NapiAVSessionManager::StopCastDiscovery(napi_env env, napi_callback_info info)
660 {
661 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
662     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::StopCastDiscovery");
663     auto context = std::make_shared<ContextBase>();
664     if (context == nullptr) {
665         SLOGE("Activate failed : no memory");
666         NapiUtils::ThrowError(env, "Activate failed : no memory", NapiAVSessionManager::errcode_[ERR_NO_MEMORY]);
667         return NapiUtils::GetUndefinedValue(env);
668     }
669 
670     context->GetCbInfo(env, info);
671     context->taskId = NAPI_STOP_CAST_DISCOVERY_TASK_ID;
672 
673     auto executor = [context]() {
674         int32_t ret = AVSESSION_ERROR;
675         ret = AVSessionManager::GetInstance().StopCastDiscovery();
676         if (ret != AVSESSION_SUCCESS) {
677             if (ret == ERR_NO_PERMISSION) {
678                 context->errMessage = "StopCastDiscovery failed : native no permission";
679             } else if (ret == ERR_INVALID_PARAM) {
680                 context->errMessage = "StopCastDiscovery failed : native invalid parameters";
681             } else if (ret == ERR_SESSION_NOT_EXIST) {
682                 context->errMessage = "StopCastDiscovery failed : native session not exist";
683             } else {
684                 context->errMessage = "StopCastDiscovery failed : native server exception";
685             }
686             context->status = napi_generic_failure;
687             context->errCode = NapiAVSessionManager::errcode_[ret];
688         }
689     };
690     auto complete = [env](napi_value& output) {
691         output = NapiUtils::GetUndefinedValue(env);
692     };
693     return NapiAsyncWork::Enqueue(env, context, "StopCastDiscovery", executor, complete);
694 #else
695     return nullptr;
696 #endif
697 }
698 
SetDiscoverable(napi_env env,napi_callback_info info)699 napi_value NapiAVSessionManager::SetDiscoverable(napi_env env, napi_callback_info info)
700 {
701 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
702     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::SetDiscoverable");
703     struct ConcreteContext : public ContextBase {
704         bool enable_;
705     };
706     auto context = std::make_shared<ConcreteContext>();
707     auto input = [env, context](size_t argc, napi_value* argv) {
708         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE, "invalid arguments",
709             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
710         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->enable_);
711         CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "get streamIds_ failed",
712             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
713     };
714     context->GetCbInfo(env, info, input);
715     context->taskId = NAPI_SET_DISCOVERABLE_TASK_ID;
716 
717     auto executor = [context]() {
718         int32_t ret = AVSessionManager::GetInstance().SetDiscoverable(context->enable_);
719         if (ret != AVSESSION_SUCCESS) {
720             if (ret == ERR_NO_PERMISSION) {
721                 context->errMessage = "SetDiscoverable failed : native no permission";
722             } else if (ret == ERR_INVALID_PARAM) {
723                 context->errMessage = "SetDiscoverable failed : native invalid parameters";
724             } else if (ret == ERR_SESSION_NOT_EXIST) {
725                 context->errMessage = "SetDiscoverable failed : native session not exist";
726             } else {
727                 context->errMessage = "SetDiscoverable failed : native server exception";
728             }
729             context->status = napi_generic_failure;
730             context->errCode = NapiAVSessionManager::errcode_[ret];
731         }
732     };
733     return NapiAsyncWork::Enqueue(env, context, "SetDiscoverable", executor);
734 #else
735     return nullptr;
736 #endif
737 }
738 
StartCast(napi_env env,napi_callback_info info)739 napi_value NapiAVSessionManager::StartCast(napi_env env, napi_callback_info info)
740 {
741 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
742     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::StartCast");
743     struct ConcreteContext : public ContextBase {
744         SessionToken sessionToken_ {};
745         OutputDeviceInfo outputdeviceInfo_;
746     };
747     auto context = std::make_shared<ConcreteContext>();
748     auto input = [env, context](size_t argc, napi_value* argv) {
749         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_TWO, "invalid arguments",
750             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
751 
752         napi_valuetype type = napi_undefined;
753         context->status = napi_typeof(env, argv[ARGV_FIRST], &type);
754         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (type == napi_object),
755             "invalid type invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
756         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->sessionToken_);
757         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok)
758             && (!context->sessionToken_.sessionId.empty()),
759             "invalid session token", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
760         context->status = NapiUtils::GetValue(env, argv[ARGV_SECOND], context->outputdeviceInfo_);
761         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok)
762             && (context->outputdeviceInfo_.deviceInfos_.size() > 0),
763             "invalid outputdeviceInfo", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
764     };
765     context->GetCbInfo(env, info, input);
766     context->taskId = NAPI_START_CAST_TASK_ID;
767 
768     auto executor = [context]() {
769         int32_t ret = AVSESSION_ERROR;
770         ret = AVSessionManager::GetInstance().StartCast(context->sessionToken_, context->outputdeviceInfo_);
771         if (ret != AVSESSION_SUCCESS) {
772             if (ret == ERR_NO_PERMISSION) {
773                 context->errMessage = "StartCast failed : native no permission";
774             } else if (ret == ERR_INVALID_PARAM) {
775                 context->errMessage = "StartCast failed : native invalid parameters";
776             } else if (ret == ERR_SESSION_NOT_EXIST) {
777                 context->errMessage = "StartCast failed : native session not exist";
778             } else {
779                 context->errMessage = "StartCast failed : native server exception";
780             }
781             context->status = napi_generic_failure;
782             context->errCode = NapiAVSessionManager::errcode_[ret];
783         }
784     };
785 
786     auto complete = [env](napi_value& output) { output = NapiUtils::GetUndefinedValue(env); };
787 
788     return NapiAsyncWork::Enqueue(env, context, "StartCast", executor, complete);
789 #else
790     return nullptr;
791 #endif
792 }
793 
StopCast(napi_env env,napi_callback_info info)794 napi_value NapiAVSessionManager::StopCast(napi_env env, napi_callback_info info)
795 {
796 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
797     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::StopCast");
798     struct ConcreteContext : public ContextBase {
799         SessionToken sessionToken_ {};
800     };
801     auto context = std::make_shared<ConcreteContext>();
802     auto input = [env, context](size_t argc, napi_value* argv) {
803         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE, "invalid arguments",
804             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
805 
806         napi_valuetype type = napi_undefined;
807         context->status = napi_typeof(env, argv[ARGV_FIRST], &type);
808         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (type == napi_object),
809             "invalid type invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
810         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->sessionToken_);
811         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (!context->sessionToken_.sessionId.empty()),
812             "invalid session token", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
813     };
814     context->GetCbInfo(env, info, input);
815     context->taskId = NAPI_STOP_CAST_TASK_ID;
816 
817     auto executor = [context]() {
818         int32_t ret = AVSESSION_ERROR;
819         ret = AVSessionManager::GetInstance().StopCast(context->sessionToken_);
820         if (ret != AVSESSION_SUCCESS) {
821             if (ret == ERR_NO_PERMISSION) {
822                 context->errMessage = "StopCast failed : native no permission";
823             } else if (ret == ERR_INVALID_PARAM) {
824                 context->errMessage = "StopCast failed : native invalid parameters";
825             } else if (ret == ERR_SESSION_NOT_EXIST) {
826                 context->errMessage = "StopCast failed : native session not exist";
827             } else {
828                 context->errMessage = "StopCast failed : native server exception";
829             }
830             context->status = napi_generic_failure;
831             context->errCode = NapiAVSessionManager::errcode_[ret];
832         }
833     };
834 
835     auto complete = [env](napi_value& output) { output = NapiUtils::GetUndefinedValue(env); };
836 
837     return NapiAsyncWork::Enqueue(env, context, "StopCast", executor, complete);
838 #else
839     return nullptr;
840 #endif
841 }
842 
OnSessionCreate(napi_env env,napi_value callback)843 napi_status NapiAVSessionManager::OnSessionCreate(napi_env env, napi_value callback)
844 {
845     return listener_->AddCallback(env, NapiSessionListener::EVENT_SESSION_CREATED, callback);
846 }
847 
OnSessionDestroy(napi_env env,napi_value callback)848 napi_status NapiAVSessionManager::OnSessionDestroy(napi_env env, napi_value callback)
849 {
850     return listener_->AddCallback(env, NapiSessionListener::EVENT_SESSION_DESTROYED, callback);
851 }
852 
OnTopSessionChange(napi_env env,napi_value callback)853 napi_status NapiAVSessionManager::OnTopSessionChange(napi_env env, napi_value callback)
854 {
855     return listener_->AddCallback(env, NapiSessionListener::EVENT_TOP_SESSION_CHANGED, callback);
856 }
857 
OnAudioSessionChecked(napi_env env,napi_value callback)858 napi_status NapiAVSessionManager::OnAudioSessionChecked(napi_env env, napi_value callback)
859 {
860     return listener_->AddCallback(env, NapiSessionListener::EVENT_AUDIO_SESSION_CHECKED, callback);
861 }
862 
OnDeviceAvailable(napi_env env,napi_value callback)863 napi_status NapiAVSessionManager::OnDeviceAvailable(napi_env env, napi_value callback)
864 {
865     return listener_->AddCallback(env, NapiSessionListener::EVENT_DEVICE_AVAILABLE, callback);
866 }
867 
OnDeviceOffline(napi_env env,napi_value callback)868 napi_status NapiAVSessionManager::OnDeviceOffline(napi_env env, napi_value callback)
869 {
870     return listener_->AddCallback(env, NapiSessionListener::EVENT_DEVICE_OFFLINE, callback);
871 }
872 
OnServiceDie(napi_env env,napi_value callback)873 napi_status NapiAVSessionManager::OnServiceDie(napi_env env, napi_value callback)
874 {
875     napi_ref ref = nullptr;
876     CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, serviceDiedCallbacks_, callback, ref),
877                              napi_generic_failure, "get callback reference failed");
878     CHECK_AND_RETURN_RET_LOG(ref == nullptr, napi_ok, "callback has been registered");
879     napi_status status = napi_create_reference(env, callback, ARGC_ONE, &ref);
880     if (status != napi_ok) {
881         SLOGE("napi_create_reference failed");
882         return status;
883     }
884     if (asyncCallback_ == nullptr) {
885         asyncCallback_ = std::make_shared<NapiAsyncCallback>(env);
886         if (asyncCallback_ == nullptr) {
887             SLOGE("no memory");
888             return napi_generic_failure;
889         }
890     }
891     serviceDiedCallbacks_.push_back(ref);
892     if (AVSessionManager::GetInstance().RegisterServiceDeathCallback(HandleServiceDied) != AVSESSION_SUCCESS) {
893         return napi_generic_failure;
894     }
895     return napi_ok;
896 }
897 
HandleServiceDied()898 void NapiAVSessionManager::HandleServiceDied()
899 {
900     if (!serviceDiedCallbacks_.empty() && asyncCallback_ != nullptr) {
901         for (auto callbackRef = serviceDiedCallbacks_.begin(); callbackRef != serviceDiedCallbacks_.end();
902              ++callbackRef) {
903             asyncCallback_->Call(*callbackRef);
904         }
905     }
906 }
907 
OffSessionCreate(napi_env env,napi_value callback)908 napi_status NapiAVSessionManager::OffSessionCreate(napi_env env, napi_value callback)
909 {
910     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
911     return listener_->RemoveCallback(env, NapiSessionListener::EVENT_SESSION_CREATED, callback);
912 }
913 
OffSessionDestroy(napi_env env,napi_value callback)914 napi_status NapiAVSessionManager::OffSessionDestroy(napi_env env, napi_value callback)
915 {
916     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
917     return listener_->RemoveCallback(env, NapiSessionListener::EVENT_SESSION_DESTROYED, callback);
918 }
919 
OffTopSessionChange(napi_env env,napi_value callback)920 napi_status NapiAVSessionManager::OffTopSessionChange(napi_env env, napi_value callback)
921 {
922     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
923     return listener_->RemoveCallback(env, NapiSessionListener::EVENT_TOP_SESSION_CHANGED, callback);
924 }
925 
OffAudioSessionChecked(napi_env env,napi_value callback)926 napi_status NapiAVSessionManager::OffAudioSessionChecked(napi_env env, napi_value callback)
927 {
928     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
929     return listener_->RemoveCallback(env, NapiSessionListener::EVENT_AUDIO_SESSION_CHECKED, callback);
930 }
931 
OffDeviceAvailable(napi_env env,napi_value callback)932 napi_status NapiAVSessionManager::OffDeviceAvailable(napi_env env, napi_value callback)
933 {
934     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
935     return listener_->RemoveCallback(env, NapiSessionListener::EVENT_DEVICE_AVAILABLE, callback);
936 }
937 
OffDeviceOffline(napi_env env,napi_value callback)938 napi_status NapiAVSessionManager::OffDeviceOffline(napi_env env, napi_value callback)
939 {
940     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
941     return listener_->RemoveCallback(env, NapiSessionListener::EVENT_DEVICE_OFFLINE, callback);
942 }
943 
OffServiceDie(napi_env env,napi_value callback)944 napi_status NapiAVSessionManager::OffServiceDie(napi_env env, napi_value callback)
945 {
946     AVSessionManager::GetInstance().UnregisterServiceDeathCallback();
947     if (callback == nullptr) {
948         for (auto callbackRef = serviceDiedCallbacks_.begin(); callbackRef != serviceDiedCallbacks_.end();
949              ++callbackRef) {
950             napi_status ret = napi_delete_reference(env, *callbackRef);
951             CHECK_AND_RETURN_RET_LOG(napi_ok == ret, ret, "delete callback reference failed");
952             *callbackRef = nullptr;
953         }
954         serviceDiedCallbacks_.clear();
955         return napi_ok;
956     }
957     napi_ref ref = nullptr;
958     CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, serviceDiedCallbacks_, callback, ref),
959                              napi_generic_failure, "get callback reference failed");
960     CHECK_AND_RETURN_RET_LOG(ref != nullptr, napi_ok, "callback has been remove");
961     serviceDiedCallbacks_.remove(ref);
962     return napi_delete_reference(env, ref);
963 }
964 }
965