• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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 #include "avsession_radar.h"
33 #include "permission_checker.h"
34 
35 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
36 #include "napi_avcast_controller.h"
37 #endif
38 
39 namespace OHOS::AVSession {
40 using namespace Security::AccessToken;
41 std::map<std::string, std::pair<NapiAVSessionManager::OnEventHandlerType, NapiAVSessionManager::OffEventHandlerType>>
42     NapiAVSessionManager::eventHandlers_ = {
43     { "sessionCreate", { OnSessionCreate, OffSessionCreate } },
44     { "sessionDestroy", { OnSessionDestroy, OffSessionDestroy } },
45     { "topSessionChange", { OnTopSessionChange, OffTopSessionChange } },
46     { "sessionServiceDie", { OnServiceDie, OffServiceDie } },
47     { "deviceAvailable", { OnDeviceAvailable, OffDeviceAvailable } },
48     { "deviceLogEvent", { OnDeviceLogEvent, OffDeviceLogEvent } },
49     { "deviceOffline", { OnDeviceOffline, OffDeviceOffline } },
50 };
51 
52 std::map<DistributedSessionType, std::pair<NapiAVSessionManager::OnEventHandlerType,
53     NapiAVSessionManager::OffEventHandlerType>> NapiAVSessionManager::distributedControllerEventHandlers_ = {
54     { DistributedSessionType::TYPE_SESSION_REMOTE, {
55         OnRemoteDistributedSessionChange, OffRemoteDistributedSessionChange } },
56 };
57 
58 const std::string NapiAVSessionManager::DISTRIBUTED_SESSION_CHANGE_EVENT = "distributedSessionChange";
59 
60 std::shared_ptr<NapiSessionListener> NapiAVSessionManager::listener_;
61 std::shared_ptr<NapiAsyncCallback> NapiAVSessionManager::asyncCallback_;
62 std::list<napi_ref> NapiAVSessionManager::serviceDiedCallbacks_;
63 std::mutex createControllerMutex_;
64 std::mutex listenerMutex_;
65 
66 std::map<int32_t, int32_t> NapiAVSessionManager::errcode_ = {
67     {AVSESSION_ERROR, 6600101},
68     {ERR_NO_MEMORY, 6600101},
69     {ERR_SERVICE_NOT_EXIST, 6600101},
70     {ERR_SESSION_LISTENER_EXIST, 6600101},
71     {ERR_MARSHALLING, 6600101},
72     {ERR_UNMARSHALLING, 6600101},
73     {ERR_IPC_SEND_REQUEST, 6600101},
74     {ERR_CONTROLLER_IS_EXIST, 6600101},
75     {ERR_START_ABILITY_IS_RUNNING, 6600101},
76     {ERR_ABILITY_NOT_AVAILABLE, 6600101},
77     {ERR_START_ABILITY_TIMEOUT, 6600101},
78     {ERR_SESSION_NOT_EXIST, 6600102},
79     {ERR_CONTROLLER_NOT_EXIST, 6600103},
80     {ERR_RPC_SEND_REQUEST, 6600104},
81     {ERR_COMMAND_NOT_SUPPORT, 6600105},
82     {ERR_SESSION_DEACTIVE, 6600106},
83     {ERR_COMMAND_SEND_EXCEED_MAX, 6600107},
84     {ERR_DEVICE_CONNECTION_FAILED, 6600108},
85     {ERR_REMOTE_CONNECTION_NOT_EXIST, 6600109},
86     {ERR_SESSION_IS_EXIST, 6600101},
87     {ERR_PERMISSION_DENIED, 201},
88     {ERR_NO_PERMISSION, 202},
89     {ERR_INVALID_PARAM, 401},
90 };
Init(napi_env env,napi_value exports)91 napi_value NapiAVSessionManager::Init(napi_env env, napi_value exports)
92 {
93     napi_property_descriptor descriptors[] = {
94         DECLARE_NAPI_STATIC_FUNCTION("createAVSession", CreateAVSession),
95         DECLARE_NAPI_STATIC_FUNCTION("getAllSessionDescriptors", GetAllSessionDescriptors),
96         DECLARE_NAPI_STATIC_FUNCTION("getHistoricalSessionDescriptors", GetHistoricalSessionDescriptors),
97         DECLARE_NAPI_STATIC_FUNCTION("getHistoricalAVQueueInfos", GetHistoricalAVQueueInfos),
98         DECLARE_NAPI_STATIC_FUNCTION("startAVPlayback", StartAVPlayback),
99         DECLARE_NAPI_STATIC_FUNCTION("createController", CreateController),
100         DECLARE_NAPI_STATIC_FUNCTION("getAVCastController", GetAVCastController),
101         DECLARE_NAPI_STATIC_FUNCTION("castAudio", CastAudio),
102         DECLARE_NAPI_STATIC_FUNCTION("on", OnEvent),
103         DECLARE_NAPI_STATIC_FUNCTION("off", OffEvent),
104         DECLARE_NAPI_STATIC_FUNCTION("sendSystemAVKeyEvent", SendSystemAVKeyEvent),
105         DECLARE_NAPI_STATIC_FUNCTION("sendSystemControlCommand", SendSystemControlCommand),
106         DECLARE_NAPI_STATIC_FUNCTION("startCastDeviceDiscovery", StartCastDiscovery),
107         DECLARE_NAPI_STATIC_FUNCTION("stopCastDeviceDiscovery", StopCastDiscovery),
108         DECLARE_NAPI_STATIC_FUNCTION("startDeviceLogging", StartDeviceLogging),
109         DECLARE_NAPI_STATIC_FUNCTION("stopDeviceLogging", StopDeviceLogging),
110         DECLARE_NAPI_STATIC_FUNCTION("setDiscoverable", SetDiscoverable),
111         DECLARE_NAPI_STATIC_FUNCTION("startCasting", StartCast),
112         DECLARE_NAPI_STATIC_FUNCTION("stopCasting", StopCast),
113         DECLARE_NAPI_STATIC_FUNCTION("getDistributedSessionController", GetDistributedSessionControllers),
114     };
115 
116     napi_status status = napi_define_properties(env, exports, sizeof(descriptors) / sizeof(napi_property_descriptor),
117                                                 descriptors);
118     if (status != napi_ok) {
119         SLOGE("define manager properties failed");
120         return NapiUtils::GetUndefinedValue(env);
121     }
122     return exports;
123 }
124 
125 std::shared_ptr<NapiAVSession> napiSession = nullptr;
126 
processMsg(std::shared_ptr<ContextBase> context,int32_t ret)127 void processMsg(std::shared_ptr<ContextBase> context, int32_t ret)
128 {
129     if (ret != AVSESSION_SUCCESS) {
130         if (ret == ERR_SESSION_IS_EXIST) {
131             context->errMessage = "CreateAVSession failed : session is existed";
132         } else {
133             context->errMessage = "CreateAVSession failed : native create session failed";
134         }
135         context->status = napi_generic_failure;
136         context->errCode = NapiAVSessionManager::errcode_[ret];
137     }
138 }
139 
CreateAVSession(napi_env env,napi_callback_info info)140 napi_value NapiAVSessionManager::CreateAVSession(napi_env env, napi_callback_info info)
141 {
142     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::CreateAVSession");
143     struct ConcreteContext : public ContextBase {
144         std::string tag_;
145         int32_t type_{};
146         AppExecFwk::ElementName elementName_;
147         std::shared_ptr<AVSession> session_;
148     };
149     auto context = std::make_shared<ConcreteContext>();
150     context->taskId = NAPI_CREATE_AVSESSION_TASK_ID;
151 
152     auto inputParser = [env, context](size_t argc, napi_value* argv) {
153         // require 3 arguments <context> <tag> <type>
154         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_THREE, "invalid arguments",
155             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
156         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->elementName_);
157         CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "invalid context",
158             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
159         context->status = NapiUtils::GetValue(env, argv[ARGV_SECOND], context->tag_);
160         CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok && !context->tag_.empty(), "invalid tag",
161             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
162         std::string typeString;
163         context->status = NapiUtils::GetValue(env, argv[ARGV_THIRD], typeString);
164         CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok && !typeString.empty(), "invalid type",
165             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
166         context->type_ = NapiUtils::ConvertSessionType(typeString);
167         CHECK_ARGS_RETURN_VOID(context, context->type_ >= 0, "wrong session type",
168             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
169         context->status = napi_ok;
170     };
171     context->GetCbInfo(env, info, inputParser);
172 
173     auto res = AVSessionManager::GetInstance().RegisterServiceStartCallback(HandleServiceStart);
174     SLOGI("RegisterServiceStartCallback res=%{public}d", res);
175 
176     auto executor = [context]() {
177         int32_t ret = AVSessionManager::GetInstance().CreateSession(context->tag_, context->type_,
178                                                                     context->elementName_, context->session_);
179         processMsg(context, ret);
180     };
181 
182     auto complete = [context](napi_value& output) {
183         context->status = NapiAVSession::NewInstance(context->env, context->session_, output, napiSession);
184         if (napiSession) {
185             SLOGI("NewInstance napiSession");
186             napiSession->SetSessionTag(context->tag_);
187             napiSession->SetSessionElement(context->elementName_);
188         }
189         CHECK_STATUS_RETURN_VOID(context, "convert native object to javascript object failed",
190             NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
191     };
192 
193     return NapiAsyncWork::Enqueue(env, context, "CreateAVSession", executor, complete);
194 }
195 
GetAllSessionDescriptors(napi_env env,napi_callback_info info)196 napi_value NapiAVSessionManager::GetAllSessionDescriptors(napi_env env, napi_callback_info info)
197 {
198     struct ConcreteContext : public ContextBase {
199         std::vector<AVSessionDescriptor> descriptors_;
200     };
201     auto context = std::make_shared<ConcreteContext>();
202     context->GetCbInfo(env, info);
203 
204     auto executor = [context]() {
205         int32_t ret = AVSessionManager::GetInstance().GetAllSessionDescriptors(context->descriptors_);
206         if (ret != AVSESSION_SUCCESS) {
207             if (ret == ERR_NO_PERMISSION) {
208                 context->errMessage = "GetAllSessionDescriptors failed : native no permission";
209             } else if (ret == ERR_PERMISSION_DENIED) {
210                 context->errMessage = "GetAllSessionDescriptors failed : native permission denied";
211             } else {
212                 context->errMessage = "GetAllSessionDescriptors failed : native server exception";
213             }
214             context->status = napi_generic_failure;
215             context->errCode = NapiAVSessionManager::errcode_[ret];
216         }
217     };
218 
219     auto complete = [env, context](napi_value& output) {
220         context->status = NapiUtils::SetValue(env, context->descriptors_, output);
221         CHECK_STATUS_RETURN_VOID(context, "convert native object to javascript object failed",
222             NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
223     };
224 
225     return NapiAsyncWork::Enqueue(env, context, "GetAllSessionDescriptors", executor, complete);
226 }
227 
GetHistoricalSessionDescriptors(napi_env env,napi_callback_info info)228 napi_value NapiAVSessionManager::GetHistoricalSessionDescriptors(napi_env env, napi_callback_info info)
229 {
230     struct ConcreteContext : public ContextBase {
231         int32_t maxSize_ {};
232         std::vector<AVSessionDescriptor> descriptors_;
233     };
234     auto context = std::make_shared<ConcreteContext>();
235 
236     auto input = [env, context](size_t argc, napi_value* argv) {
237         if (argc == ARGC_ONE && !NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_undefined)
238             && !NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_null)) {
239             context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->maxSize_);
240             CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "invalid arguments",
241                 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
242             CHECK_ARGS_RETURN_VOID(context,
243                 (context->maxSize_ >= static_cast<int32_t>(HISTORICAL_MIN_NUM)
244                 && context->maxSize_ <= static_cast<int32_t>(HISTORICAL_MAX_NUM)),
245                 "invalid arguments", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
246         } else {
247             context->maxSize_ = HISTORICAL_UNSET_NUM;
248         }
249     };
250 
251     context->GetCbInfo(env, info, input);
252 
253     auto executor = [context]() {
254         int32_t ret = AVSessionManager::GetInstance().GetHistoricalSessionDescriptors(context->maxSize_,
255             context->descriptors_);
256         if (ret != AVSESSION_SUCCESS) {
257             if (ret == ERR_NO_PERMISSION) {
258                 context->errMessage = "GetHistoricalSessionDescriptors failed : native no permission";
259             } else if (ret == ERR_PERMISSION_DENIED) {
260                 context->errMessage = "GetHistoricalSessionDescriptors failed : native permission denied";
261             } else {
262                 context->errMessage = "GetHistoricalSessionDescriptors 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 = NapiUtils::SetValue(env, context->descriptors_, 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, "GetHistoricalSessionDescriptors", executor, complete);
276 }
277 
GetHistoricalAVQueueInfos(napi_env env,napi_callback_info info)278 napi_value NapiAVSessionManager::GetHistoricalAVQueueInfos(napi_env env, napi_callback_info info)
279 {
280     struct ConcreteContext : public ContextBase {
281         int32_t maxSize_ {};
282         int32_t maxAppSize_ {};
283         std::vector<AVQueueInfo> avQueueInfos_;
284     };
285     auto context = std::make_shared<ConcreteContext>();
286 
287     auto input = [env, context](size_t argc, napi_value* argv) {
288         if (argc == ARGC_TWO && (!NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_undefined)
289             && !NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_null)
290             && !NapiUtils::TypeCheck(env, argv[ARGV_SECOND], napi_undefined)
291             && !NapiUtils::TypeCheck(env, argv[ARGV_SECOND], napi_null))) {
292             context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->maxSize_);
293             CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, " get avqueueinfo invalid maxSize",
294                 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
295 
296             context->status = NapiUtils::GetValue(env, argv[ARGV_SECOND], context->maxAppSize_);
297             CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, " get avqueueinfo invalid maxAppSize",
298                 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
299         }
300     };
301 
302     context->GetCbInfo(env, info, input);
303 
304     auto executor = [context]() {
305         int32_t ret = AVSessionManager::GetInstance().GetHistoricalAVQueueInfos(context->maxSize_,
306             context->maxAppSize_, context->avQueueInfos_);
307         if (ret != AVSESSION_SUCCESS) {
308             if (ret == ERR_NO_PERMISSION) {
309                 context->errMessage = "GetHistoricalAVQueueInfos failed : native no permission";
310             } else if (ret == ERR_PERMISSION_DENIED) {
311                 context->errMessage = "GetHistoricalAVQueueInfos failed : native permission denied";
312             } else {
313                 context->errMessage = "GetHistoricalAVQueueInfos failed : native server exception";
314             }
315             context->status = napi_generic_failure;
316             context->errCode = NapiAVSessionManager::errcode_[ret];
317         }
318     };
319 
320     auto complete = [env, context](napi_value& output) {
321         context->status = NapiUtils::SetValue(env, context->avQueueInfos_, output);
322         CHECK_STATUS_RETURN_VOID(context, "convert native object to javascript object failed",
323             NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
324     };
325 
326     return NapiAsyncWork::Enqueue(env, context, "GetHistoricalAVQueueInfos", executor, complete);
327 }
328 
StartAVPlayback(napi_env env,napi_callback_info info)329 napi_value NapiAVSessionManager::StartAVPlayback(napi_env env, napi_callback_info info)
330 {
331     struct ConcreteContext : public ContextBase {
332         std::string bundleName_ {};
333         std::string assetId_ {};
334     };
335     auto context = std::make_shared<ConcreteContext>();
336 
337     auto input = [env, context](size_t argc, napi_value* argv) {
338         if (argc == ARGC_TWO && (!NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_undefined)
339             && !NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_null)
340             && !NapiUtils::TypeCheck(env, argv[ARGV_SECOND], napi_undefined)
341             && !NapiUtils::TypeCheck(env, argv[ARGV_SECOND], napi_null))) {
342             context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->bundleName_);
343             CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok && !context->bundleName_.empty(),
344               " StartAVPlayback invalid bundlename", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
345 
346             context->status = NapiUtils::GetValue(env, argv[ARGV_SECOND], context->assetId_);
347             CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, " StartAVPlayback invalid assetId",
348                 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
349         }
350     };
351 
352     context->GetCbInfo(env, info, input);
353 
354     auto executor = [context]() {
355         int32_t ret = AVSessionManager::GetInstance().StartAVPlayback(context->bundleName_, context->assetId_);
356         if (ret != AVSESSION_SUCCESS) {
357             if (ret == ERR_NO_PERMISSION) {
358                 context->errMessage = "StartAVPlayback failed : native no permission";
359             } else if (ret == ERR_PERMISSION_DENIED) {
360                 context->errMessage = "StartAVPlayback failed : native permission denied";
361             } else {
362                 context->errMessage = "StartAVPlayback failed : native server exception";
363             }
364             context->status = napi_generic_failure;
365             context->errCode = NapiAVSessionManager::errcode_[ret];
366         }
367     };
368 
369     return NapiAsyncWork::Enqueue(env, context, "StartAVPlayback", executor);
370 }
371 
GetDistributedSessionControllers(napi_env env,napi_callback_info info)372 napi_value NapiAVSessionManager::GetDistributedSessionControllers(napi_env env, napi_callback_info info)
373 {
374     SLOGI("GetDistributedSessionControllers");
375     struct ConcreteContext : public ContextBase {
376         DistributedSessionType sessionType_ {};
377         std::vector<std::shared_ptr<AVSessionController>> controllers_;
378     };
379     auto context = std::make_shared<ConcreteContext>();
380 
381     auto input = [env, context](size_t argc, napi_value* argv) {
382         int32_t err = PermissionChecker::GetInstance().CheckPermission(
383             PermissionChecker::CHECK_SYSTEM_PERMISSION);
384         CHECK_ARGS_RETURN_VOID(context, err == ERR_NONE, "Check system permission error",
385             NapiAVSessionManager::errcode_[ERR_NO_PERMISSION]);
386         if (argc == ARGC_ONE && (!NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_undefined)
387             && !NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_null))) {
388             int32_t sessionTypeValue;
389             context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], sessionTypeValue);
390             context->sessionType_ = DistributedSessionType(sessionTypeValue);
391             CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok &&
392                 context->sessionType_ >= DistributedSessionType::TYPE_SESSION_REMOTE &&
393                 context->sessionType_ < DistributedSessionType::TYPE_SESSION_MAX,
394                 "GetDistributedControllers invalid sessionType", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
395         }
396     };
397 
398     context->GetCbInfo(env, info, input);
399 
400     auto executor = [context]() {
401         int32_t ret = AVSessionManager::GetInstance().GetDistributedSessionControllers(
402             context->sessionType_, context->controllers_);
403         SLOGI("GetDistributedControllers ret:%{public}d|Size:%{public}d", ret, (int) context->controllers_.size());
404         if (ret != AVSESSION_SUCCESS) {
405             if (ret == ERR_NO_PERMISSION) {
406                 context->errMessage = "GetDistributedSessionControllers failed : native no permission";
407             } else if (ret == ERR_PERMISSION_DENIED) {
408                 context->errMessage = "GetDistributedSessionControllers failed : native permission denied";
409             } else if (ret == ERR_REMOTE_CONNECTION_NOT_EXIST) {
410                 context->errMessage = "GetDistributedSessionControllers failed : connect not exist";
411             } else {
412                 context->errMessage = "GetDistributedSessionControllers failed : native server exception";
413             }
414             context->status = napi_generic_failure;
415             context->errCode = NapiAVSessionManager::errcode_[ret];
416         }
417     };
418 
419     auto complete = [env, context](napi_value& output) {
420         context->status = NapiUtils::SetValue(env, context->controllers_, output);
421         CHECK_STATUS_RETURN_VOID(context, "convert native object to javascript object failed",
422                                  NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
423     };
424     return NapiAsyncWork::Enqueue(env, context, "GetDistributedSessionControllers", executor, complete);
425 }
426 
CreateController(napi_env env,napi_callback_info info)427 napi_value NapiAVSessionManager::CreateController(napi_env env, napi_callback_info info)
428 {
429     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::CreateController");
430     struct ConcreteContext : public ContextBase {
431         std::string sessionId_ {};
432         std::shared_ptr<AVSessionController> controller_;
433     };
434     auto context = std::make_shared<ConcreteContext>();
435     auto input = [env, context](size_t argc, napi_value* argv) {
436         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE, "invalid arguments",
437             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
438         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->sessionId_);
439         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (!context->sessionId_.empty()),
440                                "invalid sessionId", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
441     };
442     context->GetCbInfo(env, info, input);
443     context->taskId = NAPI_CREATE_CONTROLLER_TASK_ID;
444     auto executor = [context]() {
445         int32_t ret = AVSessionManager::GetInstance().CreateController(context->sessionId_, context->controller_);
446         if (ret != AVSESSION_SUCCESS) {
447             if (ret == ERR_NO_PERMISSION) {
448                 context->errMessage = "CreateController failed : native no permission";
449             } else if (ret == ERR_PERMISSION_DENIED) {
450                 context->errMessage = "CreateController failed : native permission denied";
451             } else if (ret == ERR_INVALID_PARAM) {
452                 context->errMessage = "CreateController failed : native invalid parameters";
453             } else if (ret == ERR_SESSION_NOT_EXIST) {
454                 context->errMessage = "CreateController failed : native session not exist";
455             } else if (ret == ERR_CONTROLLER_IS_EXIST) {
456                 SLOGE("create controlller with already has one");
457                 context->errCode = ERR_CONTROLLER_IS_EXIST;
458                 return;
459             } else {
460                 context->errMessage = "CreateController failed : native server exception";
461             }
462             context->status = napi_generic_failure;
463             context->errCode = NapiAVSessionManager::errcode_[ret];
464         }
465     };
466     auto complete = [env, context](napi_value& output) {
467         SLOGE("check create controller with errCode %{public}d", static_cast<int>(context->errCode));
468         std::lock_guard lockGuard(createControllerMutex_);
469         if (context->errCode == ERR_CONTROLLER_IS_EXIST) {
470             SLOGE("check create controller meet repeat for sessionId: %{public}s", context->sessionId_.c_str());
471             context->status = NapiAVSessionController::RepeatedInstance(env, context->sessionId_, output);
472         } else {
473             context->status = NapiAVSessionController::NewInstance(env, context->controller_, output);
474         }
475         CHECK_STATUS_RETURN_VOID(context, "convert native object to javascript object failed",
476             NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
477     };
478     return NapiAsyncWork::Enqueue(env, context, "CreateController", executor, complete);
479 }
480 
GetAVCastController(napi_env env,napi_callback_info info)481 napi_value NapiAVSessionManager::GetAVCastController(napi_env env, napi_callback_info info)
482 {
483 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
484     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::GetAVCastController");
485     struct ConcreteContext : public ContextBase {
486         std::string sessionId_ {};
487         std::shared_ptr<AVCastController> castController_;
488     };
489     auto context = std::make_shared<ConcreteContext>();
490     auto input = [env, context](size_t argc, napi_value* argv) {
491         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE, "invalid arguments",
492             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
493         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->sessionId_);
494         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (!context->sessionId_.empty()),
495             "invalid sessionId", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
496     };
497     context->GetCbInfo(env, info, input);
498     context->taskId = NAPI_CREATE_CAST_CONTROLLER_TASK_ID;
499 
500     auto executor = [context]() {
501         int32_t ret = AVSessionManager::GetInstance().GetAVCastController(context->sessionId_,
502             context->castController_);
503         if (ret != AVSESSION_SUCCESS) {
504             if (ret == ERR_NO_PERMISSION) {
505                 context->errMessage = "GetAVCastController failed : native no permission";
506             } else if (ret == ERR_PERMISSION_DENIED) {
507                 context->errMessage = "GetAVCastController failed : native permission denied";
508             } else if (ret == ERR_INVALID_PARAM) {
509                 context->errMessage = "GetAVCastController failed : native invalid parameters";
510             } else if (ret == ERR_SESSION_NOT_EXIST) {
511                 context->errMessage = "GetAVCastController failed : native session not exist";
512             } else {
513                 context->errMessage = "GetAVCastController failed : native server exception";
514             }
515             context->status = napi_generic_failure;
516             context->errCode = NapiAVSessionManager::errcode_[ret];
517         }
518     };
519 
520     auto complete = [env, context](napi_value& output) {
521         context->status = NapiAVCastController::NewInstance(env, context->castController_, output);
522         CHECK_STATUS_RETURN_VOID(context, "convert native object to javascript object failed",
523             NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
524     };
525 
526     return NapiAsyncWork::Enqueue(env, context, "GetAVCastController", executor, complete);
527 #else
528     return nullptr;
529 #endif
530 }
531 
CastAudio(napi_env env,napi_callback_info info)532 napi_value NapiAVSessionManager::CastAudio(napi_env env, napi_callback_info info)
533 {
534     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::CastAudio");
535     struct ConcreteContext : public ContextBase {
536         SessionToken sessionToken_ {};
537         bool isAll_ = false;
538         std::vector<AudioStandard::AudioDeviceDescriptor> audioDeviceDescriptors_;
539     };
540     auto context = std::make_shared<ConcreteContext>();
541     auto input = [env, context](size_t argc, napi_value* argv) {
542         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_TWO, "invalid arguments",
543             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
544         napi_valuetype type = napi_undefined;
545         context->status = napi_typeof(env, argv[ARGV_FIRST], &type);
546         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (type == napi_string || type == napi_object),
547                                "invalid type invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
548         if (type == napi_string) {
549             std::string flag;
550             context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], flag);
551             CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (flag == "all"),
552                                    "invalid argument", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
553             context->isAll_ = true;
554         }
555         if (type == napi_object) {
556             context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->sessionToken_);
557             CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (!context->sessionToken_.sessionId.empty()),
558                                    "invalid session token", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
559         }
560         context->status = NapiUtils::GetValue(env, argv[ARGV_SECOND], context->audioDeviceDescriptors_);
561         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (context->audioDeviceDescriptors_.size() > 0),
562                                "invalid AudioDeviceDescriptor", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
563     };
564     context->GetCbInfo(env, info, input);
565     context->taskId = NAPI_CAST_AUDIO_TASK_ID;
566     auto executor = [context]() {
567         int32_t ret = AVSESSION_ERROR;
568         if (context->isAll_) {
569             ret = AVSessionManager::GetInstance().CastAudioForAll(context->audioDeviceDescriptors_);
570         } else {
571             ret = AVSessionManager::GetInstance().CastAudio(context->sessionToken_, context->audioDeviceDescriptors_);
572         }
573         if (ret != AVSESSION_SUCCESS) {
574             ErrCodeToMessage(ret, "CastAudio", context->errMessage);
575             context->status = napi_generic_failure;
576             context->errCode = NapiAVSessionManager::errcode_[ret];
577         }
578     };
579     auto complete = [env](napi_value& output) { output = NapiUtils::GetUndefinedValue(env); };
580     return NapiAsyncWork::Enqueue(env, context, "CastAudio", executor, complete);
581 }
582 
ErrCodeToMessage(int32_t errCode,const std::string & tag,std::string & message)583 void NapiAVSessionManager::ErrCodeToMessage(int32_t errCode, const std::string& tag, std::string& message)
584 {
585     message = tag;
586     SLOGE("check error code for message:%{public}d", errCode);
587     switch (errCode) {
588         case ERR_SESSION_NOT_EXIST:
589             message.append(" failed : native session not exist");
590             break;
591         case ERR_INVALID_PARAM:
592             message.append(" failed : native invalid parameters");
593             break;
594         case ERR_NO_PERMISSION:
595             message.append(" failed : native no permission");
596             break;
597         case ERR_PERMISSION_DENIED:
598             message.append(" failed : native permission denied");
599             break;
600         default:
601             message.append(" failed : native server exception");
602             break;
603     }
604 }
605 
RegisterNativeSessionListener(napi_env env)606 napi_status NapiAVSessionManager::RegisterNativeSessionListener(napi_env env)
607 {
608     std::lock_guard lockGuard(listenerMutex_);
609     if (listener_ != nullptr) {
610         return napi_ok;
611     }
612 
613     listener_ = std::make_shared<NapiSessionListener>();
614     if (AVSessionManager::GetInstance().RegisterServiceDeathCallback(HandleServiceDied) != AVSESSION_SUCCESS) {
615         SLOGE("register service death callback fail!");
616         return napi_generic_failure;
617     }
618     if (listener_ == nullptr) {
619         SLOGE("OnEvent failed : no memory");
620         NapiUtils::ThrowError(env, "OnEvent failed : no memory", NapiAVSessionManager::errcode_[ERR_NO_MEMORY]);
621         return napi_generic_failure;
622     }
623     int32_t ret = AVSessionManager::GetInstance().RegisterSessionListener(listener_);
624     if (ret != AVSESSION_SUCCESS) {
625         SLOGE("native register session listener failed");
626         if (ret == ERR_INVALID_PARAM) {
627             NapiUtils::ThrowError(env, "OnEvent failed : native invalid parameters",
628                 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
629         } else if (ret == ERR_NO_PERMISSION) {
630             NapiUtils::ThrowError(env, "OnEvent failed : native no permission",
631                 NapiAVSessionManager::errcode_[ERR_NO_PERMISSION]);
632         } else {
633             NapiUtils::ThrowError(env, "OnEvent failed : native server exception",
634                 NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
635         }
636         return napi_generic_failure;
637     }
638 
639     return napi_ok;
640 }
641 
OnEvent(napi_env env,napi_callback_info info)642 napi_value NapiAVSessionManager::OnEvent(napi_env env, napi_callback_info info)
643 {
644     auto context = std::make_shared<ContextBase>();
645     if (context == nullptr) {
646         SLOGE("OnEvent failed : no memory");
647         NapiUtils::ThrowError(env, "OnEvent failed : no memory", NapiAVSessionManager::errcode_[ERR_NO_MEMORY]);
648         return NapiUtils::GetUndefinedValue(env);
649     }
650 
651     std::string eventName;
652     napi_value callback = nullptr;
653     auto input = [&eventName, &callback, env, &context](size_t argc, napi_value* argv) {
654         int32_t err = PermissionChecker::GetInstance().CheckPermission(
655             PermissionChecker::CHECK_SYSTEM_PERMISSION);
656         CHECK_ARGS_RETURN_VOID(context, err == ERR_NONE, "Check system permission error",
657             NapiAVSessionManager::errcode_[ERR_NO_PERMISSION]);
658         /* require 2 arguments <event, callback> */
659         CHECK_ARGS_RETURN_VOID(context, argc >= ARGC_TWO, "invalid argument number",
660             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
661         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], eventName);
662         CHECK_STATUS_RETURN_VOID(context, "get event name failed", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
663         CHECK_RETURN_VOID(eventName != DISTRIBUTED_SESSION_CHANGE_EVENT,
664                           "no need process the distributed session changed event");
665         napi_valuetype type = napi_undefined;
666         context->status = napi_typeof(env, argv[ARGV_SECOND], &type);
667         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (type == napi_function),
668                                "callback type invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
669         callback = argv[ARGV_SECOND];
670     };
671 
672     context->GetCbInfo(env, info, input, true);
673     if (context->status != napi_ok) {
674         NapiUtils::ThrowError(env, context->errMessage.c_str(), context->errCode);
675         return NapiUtils::GetUndefinedValue(env);
676     }
677 
678     if (eventName == DISTRIBUTED_SESSION_CHANGE_EVENT) {
679         return OnDistributedSessionChangeEvent(env, info);
680     }
681 
682     auto it = eventHandlers_.find(eventName);
683     if (it == eventHandlers_.end()) {
684         SLOGE("event name invalid");
685         NapiUtils::ThrowError(env, "event name invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
686         return NapiUtils::GetUndefinedValue(env);
687     }
688 
689     if (RegisterNativeSessionListener(env) == napi_generic_failure) {
690         return NapiUtils::GetUndefinedValue(env);
691     }
692 
693     if (it->second.first(env, callback) != napi_ok) {
694         NapiUtils::ThrowError(env, "add event callback failed", NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
695     }
696 
697     return NapiUtils::GetUndefinedValue(env);
698 }
699 
OffEvent(napi_env env,napi_callback_info info)700 napi_value NapiAVSessionManager::OffEvent(napi_env env, napi_callback_info info)
701 {
702     auto context = std::make_shared<ContextBase>();
703     if (context == nullptr) {
704         SLOGE("OffEvent failed : no memory");
705         NapiUtils::ThrowError(env, "OffEvent failed : no memory", NapiAVSessionManager::errcode_[ERR_NO_MEMORY]);
706         return NapiUtils::GetUndefinedValue(env);
707     }
708 
709     std::string eventName;
710     napi_value callback = nullptr;
711     auto input = [&eventName, env, &context, &callback](size_t argc, napi_value* argv) {
712         int32_t err = PermissionChecker::GetInstance().CheckPermission(
713             PermissionChecker::CHECK_SYSTEM_PERMISSION);
714         CHECK_ARGS_RETURN_VOID(context, err == ERR_NONE, "Check system permission error",
715             NapiAVSessionManager::errcode_[ERR_NO_PERMISSION]);
716         CHECK_ARGS_RETURN_VOID(context, argc >= ARGC_ONE || argc <= ARGC_THREE, "invalid argument number",
717             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
718         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], eventName);
719         CHECK_STATUS_RETURN_VOID(context, "get event name failed",
720             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
721         if (argc == ARGC_TWO) {
722             callback = argv[ARGV_SECOND];
723         }
724     };
725 
726     context->GetCbInfo(env, info, input, true);
727     if (context->status != napi_ok) {
728         NapiUtils::ThrowError(env, context->errMessage.c_str(), context->errCode);
729         return NapiUtils::GetUndefinedValue(env);
730     }
731 
732     if (eventName == DISTRIBUTED_SESSION_CHANGE_EVENT) {
733         return OffDistributedSessionChangeEvent(env, info);
734     }
735 
736     auto it = eventHandlers_.find(eventName);
737     if (it == eventHandlers_.end()) {
738         SLOGE("event name invalid");
739         NapiUtils::ThrowError(env, "event name invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
740         return NapiUtils::GetUndefinedValue(env);
741     }
742 
743     if (it->second.second(env, callback) != napi_ok) {
744         NapiUtils::ThrowError(env, "remove event callback failed", NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
745     }
746 
747     return NapiUtils::GetUndefinedValue(env);
748 }
749 
OnDistributedSessionChangeEvent(napi_env env,napi_callback_info info)750 napi_value NapiAVSessionManager::OnDistributedSessionChangeEvent(napi_env env, napi_callback_info info)
751 {
752     SLOGI("OnDistributedSessionChangeEvent");
753     struct ConcreteContext : public ContextBase {
754         DistributedSessionType sessionType_ {};
755         napi_value callback_ = nullptr;
756     };
757     auto context = std::make_shared<ConcreteContext>();
758     if (context == nullptr) {
759         NapiUtils::ThrowError(env, "OnSessionEvent failed : no memory", NapiAVSessionManager::errcode_[ERR_NO_MEMORY]);
760         return NapiUtils::GetUndefinedValue(env);
761     }
762 
763     auto input = [env, &context](size_t argc, napi_value* argv) {
764         int32_t err = PermissionChecker::GetInstance().CheckPermission(
765             PermissionChecker::CHECK_SYSTEM_PERMISSION);
766         CHECK_ARGS_RETURN_VOID(context, err == ERR_NONE, "Check system permission error",
767             NapiAVSessionManager::errcode_[ERR_NO_PERMISSION]);
768         /* require 3 arguments <event, callback> */
769         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_THREE, "invalid argument number",
770             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
771         int32_t sessionTypeValue;
772         context->status = NapiUtils::GetValue(env, argv[ARGV_SECOND], sessionTypeValue);
773         CHECK_STATUS_RETURN_VOID(context, "get session type failed", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
774         context->sessionType_ = DistributedSessionType(sessionTypeValue);
775         CHECK_ARGS_RETURN_VOID(context, context->sessionType_ >= DistributedSessionType::TYPE_SESSION_REMOTE &&
776             context->sessionType_ < DistributedSessionType::TYPE_SESSION_MAX,
777             "GetDistributedSessionControllers invalid sessionType",
778             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
779         napi_valuetype type = napi_undefined;
780         context->status = napi_typeof(env, argv[ARGV_THIRD], &type);
781         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (type == napi_function),
782                                "callback type invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
783         context->callback_ = argv[ARGV_THIRD];
784     };
785 
786     context->GetCbInfo(env, info, input, true);
787     if (context->status != napi_ok) {
788         NapiUtils::ThrowError(env, context->errMessage.c_str(), context->errCode);
789         return NapiUtils::GetUndefinedValue(env);
790     }
791 
792     auto it = distributedControllerEventHandlers_.find(context->sessionType_);
793     if (it == distributedControllerEventHandlers_.end()) {
794         NapiUtils::ThrowError(env, "session type invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
795         return NapiUtils::GetUndefinedValue(env);
796     }
797 
798     if (RegisterNativeSessionListener(env) == napi_generic_failure) {
799         return NapiUtils::GetUndefinedValue(env);
800     }
801 
802     if (it->second.first(env, context->callback_) != napi_ok) {
803         NapiUtils::ThrowError(env, "add event callback failed", NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
804     }
805 
806     return NapiUtils::GetUndefinedValue(env);
807 }
808 
OffDistributedSessionChangeEvent(napi_env env,napi_callback_info info)809 napi_value NapiAVSessionManager::OffDistributedSessionChangeEvent(napi_env env, napi_callback_info info)
810 {
811     SLOGI("OffDistributedSessionChangeEvent");
812     struct ConcreteContext : public ContextBase {
813         DistributedSessionType sessionType_ {};
814         napi_value callback_ = nullptr;
815     };
816     auto context = std::make_shared<ConcreteContext>();
817     if (context == nullptr) {
818         NapiUtils::ThrowError(env, "OffSessionEvent failed : no memory", NapiAVSessionManager::errcode_[ERR_NO_MEMORY]);
819         return NapiUtils::GetUndefinedValue(env);
820     }
821 
822     auto input = [env, &context](size_t argc, napi_value* argv) {
823         int32_t err = PermissionChecker::GetInstance().CheckPermission(
824             PermissionChecker::CHECK_SYSTEM_PERMISSION);
825         CHECK_ARGS_RETURN_VOID(context, err == ERR_NONE, "Check system permission error",
826             NapiAVSessionManager::errcode_[ERR_NO_PERMISSION]);
827         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_TWO || argc == ARGC_THREE, "invalid argument number",
828             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
829         int32_t sessionTypeValue;
830         context->status = NapiUtils::GetValue(env, argv[ARGV_SECOND], sessionTypeValue);
831         CHECK_STATUS_RETURN_VOID(context, "get session type failed", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
832         context->sessionType_ = DistributedSessionType(sessionTypeValue);
833         CHECK_ARGS_RETURN_VOID(context, context->sessionType_ >= DistributedSessionType::TYPE_SESSION_REMOTE &&
834             context->sessionType_ < DistributedSessionType::TYPE_SESSION_MAX,
835             "GetDistributedSessionControllers invalid sessionType",
836             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
837         if (argc == ARGC_THREE) {
838             napi_valuetype type = napi_undefined;
839             context->status = napi_typeof(env, argv[ARGV_THIRD], &type);
840             CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (type == napi_function),
841                 "callback type invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
842             context->callback_ = argv[ARGV_THIRD];
843         }
844     };
845 
846     context->GetCbInfo(env, info, input, true);
847     if (context->status != napi_ok) {
848         NapiUtils::ThrowError(env, context->errMessage.c_str(), context->errCode);
849         return NapiUtils::GetUndefinedValue(env);
850     }
851 
852     auto it = distributedControllerEventHandlers_.find(context->sessionType_);
853     if (it == distributedControllerEventHandlers_.end()) {
854         NapiUtils::ThrowError(env, "session type invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
855         return NapiUtils::GetUndefinedValue(env);
856     }
857 
858     if (it->second.second(env, context->callback_) != napi_ok) {
859         NapiUtils::ThrowError(env, "remove event callback failed", NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
860     }
861 
862     return NapiUtils::GetUndefinedValue(env);
863 }
864 
SendSystemAVKeyEvent(napi_env env,napi_callback_info info)865 napi_value NapiAVSessionManager::SendSystemAVKeyEvent(napi_env env, napi_callback_info info)
866 {
867     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::SendSystemAVKeyEvent");
868     struct ConcreteContext : public ContextBase {
869         std::shared_ptr<MMI::KeyEvent> keyEvent_;
870     };
871     auto context = std::make_shared<ConcreteContext>();
872     auto input = [env, context](size_t argc, napi_value* argv) {
873         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE, "invalid arguments",
874             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
875         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->keyEvent_);
876         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (context->keyEvent_ != nullptr),
877                                "invalid keyEvent", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
878     };
879     context->GetCbInfo(env, info, input);
880     context->taskId = NAPI_SEND_SYSTEM_AV_KEY_EVENT_TASK_ID;
881 
882     auto executor = [context]() {
883         int32_t ret = AVSessionManager::GetInstance().SendSystemAVKeyEvent(*context->keyEvent_);
884         if (ret != AVSESSION_SUCCESS) {
885             if (ret == ERR_COMMAND_NOT_SUPPORT) {
886                 context->errMessage = "SendSystemAVKeyEvent failed : native invalid keyEvent";
887             } else if (ret == ERR_NO_PERMISSION) {
888                 context->errMessage = "SendSystemAVKeyEvent failed : native no permission";
889             } else if (ret == ERR_PERMISSION_DENIED) {
890                 context->errMessage = "SendSystemAVKeyEvent failed : native permission denied";
891             } else {
892                 context->errMessage = "SendSystemAVKeyEvent failed : native server exception";
893             }
894             context->status = napi_generic_failure;
895             context->errCode = NapiAVSessionManager::errcode_[ret];
896         }
897     };
898 
899     return NapiAsyncWork::Enqueue(env, context, "SendSystemAVKeyEvent", executor);
900 }
901 
SendSystemControlCommand(napi_env env,napi_callback_info info)902 napi_value NapiAVSessionManager::SendSystemControlCommand(napi_env env, napi_callback_info info)
903 {
904     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::SendSystemControlCommand");
905     struct ConcrentContext : public ContextBase {
906         AVControlCommand command;
907     };
908     auto context = std::make_shared<ConcrentContext>();
909     auto input = [env, context](size_t argc, napi_value* argv) {
910         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE, "invalid arguments",
911             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
912         context->status = NapiControlCommand::GetValue(env, argv[ARGV_FIRST], context->command);
913         CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok), "invalid command",
914             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
915     };
916     context->GetCbInfo(env, info, input);
917     context->taskId = NAPI_SEND_SYSTEM_CONTROL_COMMAND_TASK_ID;
918 
919     auto executor = [context]() {
920         int32_t ret = AVSessionManager::GetInstance().SendSystemControlCommand(context->command);
921 #ifdef ENABLE_AVSESSION_SYSEVENT_CONTROL
922             double speed;
923             int64_t time;
924             int32_t mode;
925             std::string assetId;
926             context->command.GetSpeed(speed);
927             context->command.GetSeekTime(time);
928             context->command.GetLoopMode(mode);
929             context->command.GetAssetId(assetId);
930             HISYSEVENT_FAULT("CONTROL_COMMAND_FAILED", "ERROR_TYPE", "SEND_CMD_FAILED",
931                 "CMD", context->command.GetCommand(), "TIME", time, "SPEED", speed, "MODE", mode, "ASSETID", assetId,
932                 "ERROR_CODE", ret, "ERROR_INFO", "native send control command failed");
933 #endif
934         if (ret != AVSESSION_SUCCESS) {
935             if (ret == ERR_COMMAND_NOT_SUPPORT) {
936                 context->errMessage = "SendSystemControlCommand failed : native invalid command";
937             } else if (ret == ERR_NO_PERMISSION) {
938                 context->errMessage = "SendSystemControlCommand failed : native send control command no permission";
939                 HISYSEVENT_SECURITY("CONTROL_PERMISSION_DENIED", "ERROR_CODE", ret,
940                                     "ERROR_INFO", "SendSystemControlCommand failed : native no permission");
941             } else if (ret == ERR_PERMISSION_DENIED) {
942                 context->errMessage = "SendSystemControlCommand failed : native send control command permission denied";
943             } else if (ret == ERR_COMMAND_SEND_EXCEED_MAX) {
944                 context->errMessage = "SendSystemControlCommand failed : native send command overload";
945             } else {
946                 context->errMessage = "SendSystemControlCommand failed : native server exception";
947             }
948             context->status = napi_generic_failure;
949             context->errCode = NapiAVSessionManager::errcode_[ret];
950         }
951     };
952 
953     return NapiAsyncWork::Enqueue(env, context, "SendSystemControlCommand", executor);
954 }
955 
StartCastDiscovery(napi_env env,napi_callback_info info)956 napi_value NapiAVSessionManager::StartCastDiscovery(napi_env env, napi_callback_info info)
957 {
958 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
959     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::StartCastDiscovery");
960     struct ConcreteContext : public ContextBase {
961         int32_t castDeviceCapability_;
962         std::vector<std::string> drmSchemes_;
963     };
964     auto context = std::make_shared<ConcreteContext>();
965     auto input = [env, context](size_t argc, napi_value* argv) {
966         context->status = ProcessCastDiscoveryParams(env, argc, argv,
967             context->castDeviceCapability_, context->drmSchemes_);
968         CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "invalid params",
969             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
970     };
971     context->GetCbInfo(env, info, input);
972     context->taskId = NAPI_START_CAST_DISCOVERY_TASK_ID;
973 
974     auto executor = [context]() {
975         int32_t ret = AVSessionManager::GetInstance().StartCastDiscovery(context->castDeviceCapability_,
976             context->drmSchemes_);
977         if (ret != AVSESSION_SUCCESS) {
978             if (ret == ERR_NO_PERMISSION) {
979                 context->errMessage = "StartCastDiscovery failed : native no permission";
980             } else if (ret == ERR_PERMISSION_DENIED) {
981                 context->errMessage = "StartCastDiscovery failed : native permission denied";
982             } else if (ret == ERR_INVALID_PARAM) {
983                 context->errMessage = "StartCastDiscovery failed : native invalid parameters";
984             } else if (ret == ERR_SESSION_NOT_EXIST) {
985                 context->errMessage = "StartCastDiscovery failed : native session not exist";
986             } else {
987                 context->errMessage = "StartCastDiscovery failed : native server exception";
988             }
989             context->status = napi_generic_failure;
990             context->errCode = NapiAVSessionManager::errcode_[ret];
991             ReportStartCastDiscoveryFailInfo("NapiAVSessionManager::StartCastDiscovery", ret);
992         }
993     };
994     return NapiAsyncWork::Enqueue(env, context, "StartCastDiscovery", executor);
995 #else
996     return nullptr;
997 #endif
998 }
999 
ProcessCastDiscoveryParams(napi_env env,size_t argc,napi_value * argv,int32_t & castDeviceCapability,std::vector<std::string> & drmSchemes)1000 napi_status NapiAVSessionManager::ProcessCastDiscoveryParams(
1001     napi_env env, size_t argc, napi_value* argv, int32_t& castDeviceCapability, std::vector<std::string>& drmSchemes)
1002 {
1003     napi_status status = napi_ok;
1004     if (argc == ARGC_ONE && !NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_undefined)
1005         && !NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_null)) {
1006         status = NapiUtils::GetValue(env, argv[ARGV_FIRST], castDeviceCapability);
1007     } else if (argc == ARGC_TWO) {
1008         SLOGD("get in argc two process");
1009         if (!NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_undefined) &&
1010             !NapiUtils::TypeCheck(env, argv[ARGV_FIRST], napi_null)) {
1011             status = NapiUtils::GetValue(env, argv[ARGV_FIRST], castDeviceCapability);
1012             if (status != napi_ok) {
1013                 ReportStartCastDiscoveryFailInfo("NapiAVSessionManager::StartCastDiscovery", ERR_INVALID_PARAM);
1014             }
1015         } else {
1016             castDeviceCapability = ProtocolType::TYPE_CAST_PLUS_STREAM;
1017         }
1018         if (!NapiUtils::TypeCheck(env, argv[ARGV_SECOND], napi_undefined) &&
1019             !NapiUtils::TypeCheck(env, argv[ARGV_SECOND], napi_null)) {
1020             status = NapiUtils::GetValue(env, argv[ARGV_SECOND], drmSchemes);
1021             if (status != napi_ok) {
1022                 ReportStartCastDiscoveryFailInfo("NapiAVSessionManager::StartCastDiscovery", ERR_INVALID_PARAM);
1023             }
1024         }
1025     } else {
1026         castDeviceCapability = ProtocolType::TYPE_CAST_PLUS_STREAM;
1027     }
1028     return status;
1029 }
1030 
StopCastDiscovery(napi_env env,napi_callback_info info)1031 napi_value NapiAVSessionManager::StopCastDiscovery(napi_env env, napi_callback_info info)
1032 {
1033 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
1034     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::StopCastDiscovery");
1035     auto context = std::make_shared<ContextBase>();
1036     if (context == nullptr) {
1037         SLOGE("Activate failed : no memory");
1038         ReportStopCastDiscoveryFailInfo("NapiAVSessionManager::StopCastDiscovery", ERR_NO_MEMORY);
1039         NapiUtils::ThrowError(env, "Activate failed : no memory", NapiAVSessionManager::errcode_[ERR_NO_MEMORY]);
1040         return NapiUtils::GetUndefinedValue(env);
1041     }
1042 
1043     context->GetCbInfo(env, info);
1044     context->taskId = NAPI_STOP_CAST_DISCOVERY_TASK_ID;
1045 
1046     auto executor = [context]() {
1047         int32_t ret = AVSESSION_ERROR;
1048         ret = AVSessionManager::GetInstance().StopCastDiscovery();
1049         if (ret != AVSESSION_SUCCESS) {
1050             if (ret == ERR_NO_PERMISSION) {
1051                 context->errMessage = "StopCastDiscovery failed : native no permission";
1052             } else if (ret == ERR_PERMISSION_DENIED) {
1053                 context->errMessage = "StopCastDiscovery failed : native permission denied";
1054             } else if (ret == ERR_INVALID_PARAM) {
1055                 context->errMessage = "StopCastDiscovery failed : native invalid parameters";
1056             } else if (ret == ERR_SESSION_NOT_EXIST) {
1057                 context->errMessage = "StopCastDiscovery failed : native session not exist";
1058             } else {
1059                 context->errMessage = "StopCastDiscovery failed : native server exception";
1060             }
1061             context->status = napi_generic_failure;
1062             context->errCode = NapiAVSessionManager::errcode_[ret];
1063             ReportStopCastDiscoveryFailInfo("NapiAVSessionManager::StopCastDiscovery", ret);
1064         }
1065     };
1066     auto complete = [env](napi_value& output) {
1067         output = NapiUtils::GetUndefinedValue(env);
1068     };
1069     return NapiAsyncWork::Enqueue(env, context, "StopCastDiscovery", executor, complete);
1070 #else
1071     return nullptr;
1072 #endif
1073 }
1074 
SetDiscoverable(napi_env env,napi_callback_info info)1075 napi_value NapiAVSessionManager::SetDiscoverable(napi_env env, napi_callback_info info)
1076 {
1077 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
1078     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::SetDiscoverable");
1079     struct ConcreteContext : public ContextBase {
1080         bool enable_;
1081     };
1082     auto context = std::make_shared<ConcreteContext>();
1083     auto input = [env, context](size_t argc, napi_value* argv) {
1084         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE, "invalid arguments",
1085             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
1086         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->enable_);
1087         CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "get streamIds_ failed",
1088             NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
1089     };
1090     context->GetCbInfo(env, info, input);
1091     context->taskId = NAPI_SET_DISCOVERABLE_TASK_ID;
1092 
1093     auto executor = [context]() {
1094         int32_t ret = AVSessionManager::GetInstance().SetDiscoverable(context->enable_);
1095         if (ret != AVSESSION_SUCCESS) {
1096             if (ret == ERR_NO_PERMISSION) {
1097                 context->errMessage = "SetDiscoverable failed : native no permission";
1098             } else if (ret == ERR_INVALID_PARAM) {
1099                 context->errMessage = "SetDiscoverable failed : native invalid parameters";
1100             } else if (ret == ERR_SESSION_NOT_EXIST) {
1101                 context->errMessage = "SetDiscoverable failed : native session not exist";
1102             } else {
1103                 context->errMessage = "SetDiscoverable failed : native server exception";
1104             }
1105             context->status = napi_generic_failure;
1106             context->errCode = NapiAVSessionManager::errcode_[ret];
1107         }
1108     };
1109     return NapiAsyncWork::Enqueue(env, context, "SetDiscoverable", executor);
1110 #else
1111     return nullptr;
1112 #endif
1113 }
1114 
GetStartCastErrMsg(int32_t error)1115 std::string NapiAVSessionManager::GetStartCastErrMsg(int32_t error)
1116 {
1117     std::string err;
1118     if (error == ERR_NO_PERMISSION) {
1119         err = "StartCast failed : native no permission";
1120     } else if (error == ERR_PERMISSION_DENIED) {
1121         err = "StartCast failed : native permission denied";
1122     } else if (error == ERR_INVALID_PARAM) {
1123         err = "StartCast failed : native invalid parameters";
1124     } else if (error == ERR_SESSION_NOT_EXIST) {
1125         err = "StartCast failed : native session not exist";
1126     } else {
1127         err = "StartCast failed : native server exception";
1128     }
1129     return err;
1130 }
1131 
JudgeNumString(std::string str)1132 bool NapiAVSessionManager::JudgeNumString(std::string str)
1133 {
1134     SLOGI("enter JudgeNumString");
1135     if (str.empty()) {
1136         return false;
1137     }
1138 
1139     int minNumChar = 48;
1140     int maxNumChar = 57;
1141     for (int i = 0; i < static_cast<int>(str.size()); i++) {
1142         if (str[i] < minNumChar || str[i] > maxNumChar) {
1143             return false;
1144         }
1145     }
1146     return true;
1147 }
1148 
StartDeviceLogging(napi_env env,napi_callback_info info)1149 napi_value NapiAVSessionManager::StartDeviceLogging(napi_env env, napi_callback_info info)
1150 {
1151 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
1152     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::StartDeviceLogging");
1153     struct ConcreteContext : public ContextBase {
1154         std::string fd_;
1155         uint32_t maxSize_;
1156     };
1157     auto context = std::make_shared<ConcreteContext>();
1158     if (context == nullptr) {
1159         SLOGE("Activate failed : no memory");
1160         NapiUtils::ThrowError(env, "Activate failed : no memory", NapiAVSessionManager::errcode_[ERR_NO_MEMORY]);
1161         return NapiUtils::GetUndefinedValue(env);
1162     }
1163     auto input = [env, context](size_t argc, napi_value* argv) {
1164         int32_t napiInvalidParamErr = NapiAVSessionManager::errcode_[ERR_INVALID_PARAM];
1165         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_TWO, "invalid arguments", napiInvalidParamErr);
1166 
1167         napi_valuetype type = napi_undefined;
1168         context->status = napi_typeof(env, argv[ARGV_FIRST], &type);
1169         bool condition = (context->status == napi_ok) && (type == napi_string);
1170         CHECK_ARGS_RETURN_VOID(context, condition, "invalid type invalid", napiInvalidParamErr);
1171         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->fd_);
1172         condition = (context->status == napi_ok);
1173         CHECK_ARGS_RETURN_VOID(context, condition, "fd getvalue fail", napiInvalidParamErr);
1174         CHECK_ARGS_RETURN_VOID(context, JudgeNumString(context->fd_),
1175             "fd is not a num string", napiInvalidParamErr);
1176 
1177         context->status = napi_typeof(env, argv[ARGV_SECOND], &type);
1178         condition = (context->status == napi_ok) && (type == napi_number);
1179         CHECK_ARGS_RETURN_VOID(context, condition, "invalid type invalid", napiInvalidParamErr);
1180         context->status = NapiUtils::GetValue(env, argv[ARGV_SECOND], context->maxSize_);
1181         condition = (context->status == napi_ok);
1182         CHECK_ARGS_RETURN_VOID(context, condition, "maxSize getvalue fail", napiInvalidParamErr);
1183     };
1184     context->GetCbInfo(env, info, input);
1185     context->taskId = NAPI_START_DEVICE_LOGGING_TASK_ID;
1186 
1187     auto executor = [context]() {
1188         int32_t ret = AVSessionManager::GetInstance().StartDeviceLogging(
1189             std::stoi(context->fd_), context->maxSize_);
1190         if (ret != AVSESSION_SUCCESS) {
1191             context->status = napi_generic_failure;
1192             context->errCode = NapiAVSessionManager::errcode_[ret];
1193             SLOGE("StartDeviceLogging return error code = %{public}d", ret);
1194         }
1195     };
1196     return NapiAsyncWork::Enqueue(env, context, "StartDeviceLogging", executor);
1197 #else
1198     return nullptr;
1199 #endif
1200 }
1201 
StopDeviceLogging(napi_env env,napi_callback_info info)1202 napi_value NapiAVSessionManager::StopDeviceLogging(napi_env env, napi_callback_info info)
1203 {
1204 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
1205     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::StopCast");
1206     auto context = std::make_shared<ContextBase>();
1207     if (context == nullptr) {
1208         SLOGE("Activate failed : no memory");
1209         NapiUtils::ThrowError(env, "Activate failed : no memory", NapiAVSessionManager::errcode_[ERR_NO_MEMORY]);
1210         return NapiUtils::GetUndefinedValue(env);
1211     }
1212     context->GetCbInfo(env, info);
1213     context->taskId = NAPI_STOP_DEVICE_LOGGING_TASK_ID;
1214 
1215     auto executor = [context]() {
1216         int32_t ret = AVSESSION_ERROR;
1217         ret = AVSessionManager::GetInstance().StopDeviceLogging();
1218         if (ret != AVSESSION_SUCCESS) {
1219             context->status = napi_generic_failure;
1220             context->errCode = NapiAVSessionManager::errcode_[ret];
1221             SLOGE("StopDeviceLogging return error code = %{public}d", ret);
1222         }
1223     };
1224     auto complete = [env](napi_value& output) {
1225         output = NapiUtils::GetUndefinedValue(env);
1226     };
1227     return NapiAsyncWork::Enqueue(env, context, "StopDeviceLogging", executor, complete);
1228 #else
1229     return nullptr;
1230 #endif
1231 }
1232 
StartCast(napi_env env,napi_callback_info info)1233 napi_value NapiAVSessionManager::StartCast(napi_env env, napi_callback_info info)
1234 {
1235 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
1236     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::StartCast");
1237     struct ConcreteContext : public ContextBase {
1238         SessionToken sessionToken_ {};
1239         OutputDeviceInfo outputdeviceInfo_;
1240     };
1241     auto context = std::make_shared<ConcreteContext>();
1242     auto input = [env, context](size_t argc, napi_value* argv) {
1243         int32_t napiInvalidParamErr = NapiAVSessionManager::errcode_[ERR_INVALID_PARAM];
1244         CheckStartCastReportRadar(argc == ARGC_TWO, ERR_INVALID_PARAM);
1245         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_TWO, "invalid arguments", napiInvalidParamErr);
1246 
1247         napi_valuetype type = napi_undefined;
1248         context->status = napi_typeof(env, argv[ARGV_FIRST], &type);
1249         bool condition = (context->status == napi_ok) && (type == napi_object);
1250         CheckStartCastReportRadar(condition, ERR_INVALID_PARAM);
1251         CHECK_ARGS_RETURN_VOID(context, condition, "invalid type invalid", napiInvalidParamErr);
1252 
1253         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->sessionToken_);
1254         condition = (context->status == napi_ok) && (!context->sessionToken_.sessionId.empty());
1255         CheckStartCastReportRadar(condition, ERR_INVALID_PARAM);
1256         CHECK_ARGS_RETURN_VOID(context, condition, "invalid session token", napiInvalidParamErr);
1257 
1258         context->status = NapiUtils::GetValue(env, argv[ARGV_SECOND], context->outputdeviceInfo_);
1259         condition = (context->status == napi_ok) && (context->outputdeviceInfo_.deviceInfos_.size() > 0);
1260         CheckStartCastReportRadar(condition, ERR_INVALID_PARAM);
1261         CHECK_ARGS_RETURN_VOID(context, condition, "invalid outputdeviceInfo", napiInvalidParamErr);
1262     };
1263     context->GetCbInfo(env, info, input);
1264     context->taskId = NAPI_START_CAST_TASK_ID;
1265 
1266     auto executor = [context]() {
1267         int32_t ret = AVSESSION_ERROR;
1268         ret = AVSessionManager::GetInstance().StartCast(context->sessionToken_, context->outputdeviceInfo_);
1269         if (ret != AVSESSION_SUCCESS) {
1270             context->errMessage = GetStartCastErrMsg(ret);
1271             context->status = napi_generic_failure;
1272             context->errCode = NapiAVSessionManager::errcode_[ret];
1273             ReportStartCastFailInfo(ret, context->outputdeviceInfo_);
1274         }
1275     };
1276 
1277     auto complete = [env](napi_value& output) { output = NapiUtils::GetUndefinedValue(env); };
1278 
1279     return NapiAsyncWork::Enqueue(env, context, "StartCast", executor, complete);
1280 #else
1281     return nullptr;
1282 #endif
1283 }
1284 
StopCast(napi_env env,napi_callback_info info)1285 napi_value NapiAVSessionManager::StopCast(napi_env env, napi_callback_info info)
1286 {
1287 #ifdef CASTPLUS_CAST_ENGINE_ENABLE
1288     AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::StopCast");
1289     struct ConcreteContext : public ContextBase {
1290         SessionToken sessionToken_ {};
1291     };
1292     auto context = std::make_shared<ConcreteContext>();
1293     auto input = [env, context](size_t argc, napi_value* argv) {
1294         int32_t napiInvalidParamErr = NapiAVSessionManager::errcode_[ERR_INVALID_PARAM];
1295         CheckStopCastReportRadar(argc == ARGC_ONE, ERR_INVALID_PARAM);
1296         CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE, "invalid arguments", napiInvalidParamErr);
1297 
1298         napi_valuetype type = napi_undefined;
1299         context->status = napi_typeof(env, argv[ARGV_FIRST], &type);
1300         bool condition = (context->status == napi_ok) && (type == napi_object);
1301         CheckStopCastReportRadar(condition, ERR_INVALID_PARAM);
1302         CHECK_ARGS_RETURN_VOID(context, condition, "invalid type invalid", napiInvalidParamErr);
1303 
1304         context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->sessionToken_);
1305         condition = (context->status == napi_ok) && (!context->sessionToken_.sessionId.empty());
1306         CheckStopCastReportRadar(condition, ERR_INVALID_PARAM);
1307         CHECK_ARGS_RETURN_VOID(context, condition, "invalid session token", napiInvalidParamErr);
1308     };
1309     context->GetCbInfo(env, info, input);
1310     context->taskId = NAPI_STOP_CAST_TASK_ID;
1311 
1312     auto executor = [context]() {
1313         int32_t ret = AVSESSION_ERROR;
1314         ret = AVSessionManager::GetInstance().StopCast(context->sessionToken_);
1315         if (ret != AVSESSION_SUCCESS) {
1316             if (ret == ERR_NO_PERMISSION) {
1317                 context->errMessage = "StopCast failed : native no permission";
1318             } else if (ret == ERR_INVALID_PARAM) {
1319                 context->errMessage = "StopCast failed : native invalid parameters";
1320             } else if (ret == ERR_SESSION_NOT_EXIST) {
1321                 context->errMessage = "StopCast failed : native session not exist";
1322             } else {
1323                 context->errMessage = "StopCast failed : native server exception";
1324             }
1325             context->status = napi_generic_failure;
1326             context->errCode = NapiAVSessionManager::errcode_[ret];
1327             ReportStopCastFailInfo(ret);
1328         }
1329     };
1330 
1331     auto complete = [env](napi_value& output) { output = NapiUtils::GetUndefinedValue(env); };
1332 
1333     return NapiAsyncWork::Enqueue(env, context, "StopCast", executor, complete);
1334 #else
1335     return nullptr;
1336 #endif
1337 }
1338 
OnSessionCreate(napi_env env,napi_value callback)1339 napi_status NapiAVSessionManager::OnSessionCreate(napi_env env, napi_value callback)
1340 {
1341     std::lock_guard lockGuard(listenerMutex_);
1342     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
1343     return listener_->AddCallback(env, NapiSessionListener::EVENT_SESSION_CREATED, callback);
1344 }
1345 
OnSessionDestroy(napi_env env,napi_value callback)1346 napi_status NapiAVSessionManager::OnSessionDestroy(napi_env env, napi_value callback)
1347 {
1348     std::lock_guard lockGuard(listenerMutex_);
1349     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
1350     return listener_->AddCallback(env, NapiSessionListener::EVENT_SESSION_DESTROYED, callback);
1351 }
1352 
OnTopSessionChange(napi_env env,napi_value callback)1353 napi_status NapiAVSessionManager::OnTopSessionChange(napi_env env, napi_value callback)
1354 {
1355     std::lock_guard lockGuard(listenerMutex_);
1356     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
1357     return listener_->AddCallback(env, NapiSessionListener::EVENT_TOP_SESSION_CHANGED, callback);
1358 }
1359 
OnAudioSessionChecked(napi_env env,napi_value callback)1360 napi_status NapiAVSessionManager::OnAudioSessionChecked(napi_env env, napi_value callback)
1361 {
1362     std::lock_guard lockGuard(listenerMutex_);
1363     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
1364     return listener_->AddCallback(env, NapiSessionListener::EVENT_AUDIO_SESSION_CHECKED, callback);
1365 }
1366 
OnDeviceAvailable(napi_env env,napi_value callback)1367 napi_status NapiAVSessionManager::OnDeviceAvailable(napi_env env, napi_value callback)
1368 {
1369     std::lock_guard lockGuard(listenerMutex_);
1370     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
1371     return listener_->AddCallback(env, NapiSessionListener::EVENT_DEVICE_AVAILABLE, callback);
1372 }
1373 
OnDeviceLogEvent(napi_env env,napi_value callback)1374 napi_status NapiAVSessionManager::OnDeviceLogEvent(napi_env env, napi_value callback)
1375 {
1376     return listener_->AddCallback(env, NapiSessionListener::EVENT_DEVICE_LOG_EVENT, callback);
1377 }
1378 
OnDeviceOffline(napi_env env,napi_value callback)1379 napi_status NapiAVSessionManager::OnDeviceOffline(napi_env env, napi_value callback)
1380 {
1381     std::lock_guard lockGuard(listenerMutex_);
1382     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
1383     return listener_->AddCallback(env, NapiSessionListener::EVENT_DEVICE_OFFLINE, callback);
1384 }
1385 
OnServiceDie(napi_env env,napi_value callback)1386 napi_status NapiAVSessionManager::OnServiceDie(napi_env env, napi_value callback)
1387 {
1388     napi_ref ref = nullptr;
1389     CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, serviceDiedCallbacks_, callback, ref),
1390                              napi_generic_failure, "get callback reference failed");
1391     CHECK_AND_RETURN_RET_LOG(ref == nullptr, napi_ok, "callback has been registered");
1392     napi_status status = napi_create_reference(env, callback, ARGC_ONE, &ref);
1393     if (status != napi_ok) {
1394         SLOGE("napi_create_reference failed");
1395         return status;
1396     }
1397     if (asyncCallback_ == nullptr) {
1398         asyncCallback_ = std::make_shared<NapiAsyncCallback>(env);
1399         if (asyncCallback_ == nullptr) {
1400             SLOGE("no memory");
1401             return napi_generic_failure;
1402         }
1403     }
1404     serviceDiedCallbacks_.push_back(ref);
1405     SLOGI("do service die register when listener setup");
1406     return napi_ok;
1407 }
1408 
OnRemoteDistributedSessionChange(napi_env env,napi_value callback)1409 napi_status NapiAVSessionManager::OnRemoteDistributedSessionChange(napi_env env, napi_value callback)
1410 {
1411     SLOGI("OnRemoteDistributedSessionChange AddCallback");
1412     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
1413     return listener_->AddCallback(env, NapiSessionListener::EVENT_REMOTE_DISTRIBUTED_SESSION_CHANGED, callback);
1414 }
1415 
HandleServiceDied()1416 void NapiAVSessionManager::HandleServiceDied()
1417 {
1418     if (!serviceDiedCallbacks_.empty() && asyncCallback_ != nullptr) {
1419         for (auto callbackRef = serviceDiedCallbacks_.begin(); callbackRef != serviceDiedCallbacks_.end();
1420              ++callbackRef) {
1421             asyncCallback_->Call(*callbackRef);
1422         }
1423     }
1424     std::lock_guard lockGuard(listenerMutex_);
1425     if (listener_ != nullptr) {
1426         SLOGI("clear listener for service die");
1427         listener_ = nullptr;
1428     }
1429 }
1430 
HandleServiceStart()1431 void NapiAVSessionManager::HandleServiceStart()
1432 {
1433     SLOGI("HandleServiceStart enter");
1434     if (napiSession) {
1435         std::shared_ptr<AVSession> session;
1436         int32_t ret = AVSessionManager::GetInstance().CreateSession(napiSession->GetSessionTag(),
1437             NapiUtils::ConvertSessionType(napiSession->GetSessionType()),
1438             napiSession->GetSessionElement(), session);
1439         SLOGI("HandleServiceStart CreateSession ret=%{public}d", ret);
1440         if (ret == AVSESSION_SUCCESS) {
1441             auto res = NapiAVSession::ReCreateInstance(session);
1442             SLOGI("HandleServiceStart ReCreateInstance ret=%{public}d", res);
1443         }
1444     }
1445 }
1446 
OffSessionCreate(napi_env env,napi_value callback)1447 napi_status NapiAVSessionManager::OffSessionCreate(napi_env env, napi_value callback)
1448 {
1449     std::lock_guard lockGuard(listenerMutex_);
1450     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
1451     return listener_->RemoveCallback(env, NapiSessionListener::EVENT_SESSION_CREATED, callback);
1452 }
1453 
OffSessionDestroy(napi_env env,napi_value callback)1454 napi_status NapiAVSessionManager::OffSessionDestroy(napi_env env, napi_value callback)
1455 {
1456     std::lock_guard lockGuard(listenerMutex_);
1457     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
1458     return listener_->RemoveCallback(env, NapiSessionListener::EVENT_SESSION_DESTROYED, callback);
1459 }
1460 
OffTopSessionChange(napi_env env,napi_value callback)1461 napi_status NapiAVSessionManager::OffTopSessionChange(napi_env env, napi_value callback)
1462 {
1463     std::lock_guard lockGuard(listenerMutex_);
1464     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
1465     return listener_->RemoveCallback(env, NapiSessionListener::EVENT_TOP_SESSION_CHANGED, callback);
1466 }
1467 
OffAudioSessionChecked(napi_env env,napi_value callback)1468 napi_status NapiAVSessionManager::OffAudioSessionChecked(napi_env env, napi_value callback)
1469 {
1470     std::lock_guard lockGuard(listenerMutex_);
1471     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
1472     return listener_->RemoveCallback(env, NapiSessionListener::EVENT_AUDIO_SESSION_CHECKED, callback);
1473 }
1474 
OffDeviceAvailable(napi_env env,napi_value callback)1475 napi_status NapiAVSessionManager::OffDeviceAvailable(napi_env env, napi_value callback)
1476 {
1477     std::lock_guard lockGuard(listenerMutex_);
1478     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
1479     return listener_->RemoveCallback(env, NapiSessionListener::EVENT_DEVICE_AVAILABLE, callback);
1480 }
1481 
OffDeviceLogEvent(napi_env env,napi_value callback)1482 napi_status NapiAVSessionManager::OffDeviceLogEvent(napi_env env, napi_value callback)
1483 {
1484     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
1485     return listener_->RemoveCallback(env, NapiSessionListener::EVENT_DEVICE_LOG_EVENT, callback);
1486 }
1487 
OffDeviceOffline(napi_env env,napi_value callback)1488 napi_status NapiAVSessionManager::OffDeviceOffline(napi_env env, napi_value callback)
1489 {
1490     std::lock_guard lockGuard(listenerMutex_);
1491     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
1492     return listener_->RemoveCallback(env, NapiSessionListener::EVENT_DEVICE_OFFLINE, callback);
1493 }
1494 
OffRemoteDistributedSessionChange(napi_env env,napi_value callback)1495 napi_status NapiAVSessionManager::OffRemoteDistributedSessionChange(napi_env env, napi_value callback)
1496 {
1497     SLOGI("OffRemoteDistributedSessionChange RemoveCallback");
1498     CHECK_AND_RETURN_RET_LOG(listener_ != nullptr, napi_generic_failure, "callback has not been registered");
1499     return listener_->RemoveCallback(env, NapiSessionListener::EVENT_REMOTE_DISTRIBUTED_SESSION_CHANGED, callback);
1500 }
1501 
OffServiceDie(napi_env env,napi_value callback)1502 napi_status NapiAVSessionManager::OffServiceDie(napi_env env, napi_value callback)
1503 {
1504     SLOGI("OffServiceDie but no longer UnregisterServiceDeathCallback");
1505     if (callback == nullptr) {
1506         for (auto callbackRef = serviceDiedCallbacks_.begin(); callbackRef != serviceDiedCallbacks_.end();
1507              ++callbackRef) {
1508             napi_status ret = napi_delete_reference(env, *callbackRef);
1509             CHECK_AND_RETURN_RET_LOG(napi_ok == ret, ret, "delete callback reference failed");
1510             *callbackRef = nullptr;
1511         }
1512         serviceDiedCallbacks_.clear();
1513         return napi_ok;
1514     }
1515     napi_ref ref = nullptr;
1516     CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, serviceDiedCallbacks_, callback, ref),
1517                              napi_generic_failure, "get callback reference failed");
1518     CHECK_AND_RETURN_RET_LOG(ref != nullptr, napi_ok, "callback has been remove");
1519     serviceDiedCallbacks_.remove(ref);
1520     return napi_delete_reference(env, ref);
1521 }
1522 
ReportStartCastDiscoveryFailInfo(std::string func,int32_t error)1523 void NapiAVSessionManager::ReportStartCastDiscoveryFailInfo(std::string func, int32_t error)
1524 {
1525     AVSessionRadarInfo info(func);
1526     info.errorCode_ = AVSessionRadar::GetRadarErrorCode(error);
1527     AVSessionRadar::GetInstance().FailToStartCastDiscovery(info);
1528 }
1529 
ReportStopCastDiscoveryFailInfo(std::string func,int32_t error)1530 void NapiAVSessionManager::ReportStopCastDiscoveryFailInfo(std::string func, int32_t error)
1531 {
1532     AVSessionRadarInfo info(func);
1533     info.errorCode_ = AVSessionRadar::GetRadarErrorCode(error);
1534     AVSessionRadar::GetInstance().FailToStopCastDiscovery(info);
1535 }
1536 
ReportStartCastFailInfo(int32_t error)1537 void NapiAVSessionManager::ReportStartCastFailInfo(int32_t error)
1538 {
1539     AVSessionRadarInfo info("NapiAVSessionManager::StartCast");
1540     info.errorCode_ = AVSessionRadar::GetRadarErrorCode(error);
1541     AVSessionRadar::GetInstance().FailToStartCast(info);
1542 }
1543 
ReportStartCastFailInfo(int32_t error,const OutputDeviceInfo & outputDeviceInfo)1544 void NapiAVSessionManager::ReportStartCastFailInfo(int32_t error, const OutputDeviceInfo &outputDeviceInfo)
1545 {
1546     AVSessionRadarInfo info("NapiAVSessionManager::StartCast");
1547     info.errorCode_ = AVSessionRadar::GetRadarErrorCode(error);
1548     AVSessionRadar::GetInstance().FailToStartCast(outputDeviceInfo, info);
1549 }
1550 
ReportStopCastFailInfo(int32_t error)1551 void NapiAVSessionManager::ReportStopCastFailInfo(int32_t error)
1552 {
1553     AVSessionRadarInfo info("NapiAVSessionManager::StopCast");
1554     info.errorCode_ = AVSessionRadar::GetRadarErrorCode(error);
1555     AVSessionRadar::GetInstance().FailToStopCast(info);
1556 }
1557 
CheckStartCastReportRadar(bool condition,int32_t error)1558 void NapiAVSessionManager::CheckStartCastReportRadar(bool condition, int32_t error)
1559 {
1560     if (!condition) {
1561         ReportStartCastFailInfo(error);
1562     }
1563 }
1564 
CheckStopCastReportRadar(bool condition,int32_t error)1565 void NapiAVSessionManager::CheckStopCastReportRadar(bool condition, int32_t error)
1566 {
1567     if (!condition) {
1568         ReportStopCastFailInfo(error);
1569     }
1570 }
1571 } // namespace OHOS::AVSession
1572