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