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