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