1 /*
2 * Copyright (c) 2022 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
31 namespace OHOS::AVSession {
32 std::map<std::string, std::pair<NapiAVSessionManager::OnEventHandlerType, NapiAVSessionManager::OffEventHandlerType>>
33 NapiAVSessionManager::eventHandlers_ = {
34 { "sessionCreate", { OnSessionCreate, OffSessionCreate } },
35 { "sessionDestroy", { OnSessionDestroy, OffSessionDestroy } },
36 { "topSessionChange", { OnTopSessionChange, OffTopSessionChange } },
37 { "sessionServiceDie", { OnServiceDie, OffServiceDie } },
38 };
39
40 std::shared_ptr<NapiSessionListener> NapiAVSessionManager::listener_;
41 std::shared_ptr<NapiAsyncCallback> NapiAVSessionManager::asyncCallback_;
42 std::list<napi_ref> NapiAVSessionManager::serviceDiedCallbacks_;
43
44 std::map<int32_t, int32_t> NapiAVSessionManager::errcode_ = {
45 {AVSESSION_ERROR, 6600101},
46 {ERR_NO_MEMORY, 6600101},
47 {ERR_SERVICE_NOT_EXIST, 6600101},
48 {ERR_SESSION_LISTENER_EXIST, 6600101},
49 {ERR_MARSHALLING, 6600101},
50 {ERR_UNMARSHALLING, 6600101},
51 {ERR_IPC_SEND_REQUEST, 6600101},
52 {ERR_CONTROLLER_IS_EXIST, 6600101},
53 {ERR_START_ABILITY_IS_RUNNING, 6600101},
54 {ERR_ABILITY_NOT_AVAILABLE, 6600101},
55 {ERR_START_ABILITY_TIMEOUT, 6600101},
56 {ERR_SESSION_NOT_EXIST, 6600102},
57 {ERR_CONTROLLER_NOT_EXIST, 6600103},
58 {ERR_RPC_SEND_REQUEST, 6600104},
59 {ERR_COMMAND_NOT_SUPPORT, 6600105},
60 {ERR_SESSION_DEACTIVE, 6600106},
61 {ERR_COMMAND_SEND_EXCEED_MAX, 6600107},
62 {ERR_NO_PERMISSION, 201},
63 {ERR_INVALID_PARAM, 401},
64 };
Init(napi_env env,napi_value exports)65 napi_value NapiAVSessionManager::Init(napi_env env, napi_value exports)
66 {
67 napi_property_descriptor descriptors[] = {
68 DECLARE_NAPI_STATIC_FUNCTION("createAVSession", CreateAVSession),
69 DECLARE_NAPI_STATIC_FUNCTION("getAllSessionDescriptors", GetAllSessionDescriptors),
70 DECLARE_NAPI_STATIC_FUNCTION("createController", CreateController),
71 DECLARE_NAPI_STATIC_FUNCTION("castAudio", CastAudio),
72 DECLARE_NAPI_STATIC_FUNCTION("on", OnEvent),
73 DECLARE_NAPI_STATIC_FUNCTION("off", OffEvent),
74 DECLARE_NAPI_STATIC_FUNCTION("sendSystemAVKeyEvent", SendSystemAVKeyEvent),
75 DECLARE_NAPI_STATIC_FUNCTION("sendSystemControlCommand", SendSystemControlCommand),
76 };
77
78 napi_status status = napi_define_properties(env, exports, sizeof(descriptors) / sizeof(napi_property_descriptor),
79 descriptors);
80 if (status != napi_ok) {
81 SLOGE("define manager properties failed");
82 return NapiUtils::GetUndefinedValue(env);
83 }
84 return exports;
85 }
86
CreateAVSession(napi_env env,napi_callback_info info)87 napi_value NapiAVSessionManager::CreateAVSession(napi_env env, napi_callback_info info)
88 {
89 AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::CreateAVSession");
90 struct ConcreteContext : public ContextBase {
91 std::string tag_;
92 int32_t type_{};
93 AppExecFwk::ElementName elementName_;
94 std::shared_ptr<AVSession> session_;
95 };
96 auto context = std::make_shared<ConcreteContext>();
97 context->taskId = NAPI_CREATE_AVSESSION_TASK_ID;
98
99 auto inputParser = [env, context](size_t argc, napi_value* argv) {
100 // require 3 arguments <context> <tag> <type>
101 CHECK_ARGS_RETURN_VOID(context, argc == ARGC_THERE, "invalid arguments",
102 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
103 context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->elementName_);
104 CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok, "invalid context",
105 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
106 context->status = NapiUtils::GetValue(env, argv[ARGV_SECOND], context->tag_);
107 CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok && !context->tag_.empty(), "invalid tag",
108 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
109 std::string typeString;
110 context->status = NapiUtils::GetValue(env, argv[ARGV_THIRD], typeString);
111 CHECK_ARGS_RETURN_VOID(context, context->status == napi_ok && !typeString.empty(), "invalid type",
112 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
113 context->type_ = NapiUtils::ConvertSessionType(typeString);
114 CHECK_ARGS_RETURN_VOID(context, context->type_ >= 0, "wrong session type",
115 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
116 context->status = napi_ok;
117 };
118 context->GetCbInfo(env, info, inputParser);
119
120 auto executor = [context]() {
121 context->session_ = AVSessionManager::GetInstance().CreateSession(context->tag_, context->type_,
122 context->elementName_);
123 if (context->session_ == nullptr) {
124 context->status = napi_generic_failure;
125 context->errMessage = "CreateAVSession failed : native create session failed";
126 context->errCode = NapiAVSessionManager::errcode_[AVSESSION_ERROR];
127 }
128 };
129
130 auto complete = [context](napi_value& output) {
131 context->status = NapiAVSession::NewInstance(context->env, context->session_, output);
132 CHECK_STATUS_RETURN_VOID(context, "convert native object to javascript object failed",
133 NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
134 };
135
136 return NapiAsyncWork::Enqueue(env, context, "CreateAVSession", executor, complete);
137 }
138
GetAllSessionDescriptors(napi_env env,napi_callback_info info)139 napi_value NapiAVSessionManager::GetAllSessionDescriptors(napi_env env, napi_callback_info info)
140 {
141 struct ConcreteContext : public ContextBase {
142 std::vector<AVSessionDescriptor> descriptors_;
143 };
144 auto context = std::make_shared<ConcreteContext>();
145 context->GetCbInfo(env, info);
146
147 auto executor = [context]() {
148 int32_t ret = AVSessionManager::GetInstance().GetAllSessionDescriptors(context->descriptors_);
149 if (ret != AVSESSION_SUCCESS) {
150 if (ret == ERR_NO_PERMISSION) {
151 context->errMessage = "GetAllSessionDescriptors failed : native no permission";
152 } else {
153 context->errMessage = "GetAllSessionDescriptors failed : native server exception";
154 }
155 context->status = napi_generic_failure;
156 context->errCode = NapiAVSessionManager::errcode_[ret];
157 }
158 };
159
160 auto complete = [env, context](napi_value& output) {
161 context->status = NapiUtils::SetValue(env, context->descriptors_, output);
162 CHECK_STATUS_RETURN_VOID(context, "convert native object to javascript object failed",
163 NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
164 };
165
166 return NapiAsyncWork::Enqueue(env, context, "GetAllSessionDescriptors", executor, complete);
167 }
168
CreateController(napi_env env,napi_callback_info info)169 napi_value NapiAVSessionManager::CreateController(napi_env env, napi_callback_info info)
170 {
171 AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::CreateController");
172 struct ConcreteContext : public ContextBase {
173 std::string sessionId_ {};
174 std::shared_ptr<AVSessionController> controller_;
175 };
176 auto context = std::make_shared<ConcreteContext>();
177 auto input = [env, context](size_t argc, napi_value* argv) {
178 CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE, "invalid arguments",
179 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
180 context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->sessionId_);
181 CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (!context->sessionId_.empty()),
182 "invalid sessionId", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
183 };
184 context->GetCbInfo(env, info, input);
185 context->taskId = NAPI_CREATE_CONTROLLER_TASK_ID;
186
187 auto executor = [context]() {
188 int32_t ret = AVSessionManager::GetInstance().CreateController(context->sessionId_, context->controller_);
189 if (ret != AVSESSION_SUCCESS) {
190 if (ret == ERR_NO_PERMISSION) {
191 context->errMessage = "CreateController failed : native no permission";
192 } else if (ret == ERR_INVALID_PARAM) {
193 context->errMessage = "CreateController failed : native invalid parameters";
194 } else if (ret == ERR_SESSION_NOT_EXIST) {
195 context->errMessage = "CreateController failed : native session not exist";
196 } else {
197 context->errMessage = "CreateController failed : native server exception";
198 }
199 context->status = napi_generic_failure;
200 context->errCode = NapiAVSessionManager::errcode_[ret];
201 }
202 };
203
204 auto complete = [env, context](napi_value& output) {
205 context->status = NapiAVSessionController::NewInstance(env, context->controller_, output);
206 CHECK_STATUS_RETURN_VOID(context, "convert native object to javascript object failed",
207 NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
208 };
209
210 return NapiAsyncWork::Enqueue(env, context, "CreateController", executor, complete);
211 }
212
CastAudio(napi_env env,napi_callback_info info)213 napi_value NapiAVSessionManager::CastAudio(napi_env env, napi_callback_info info)
214 {
215 AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::CastAudio");
216 struct ConcreteContext : public ContextBase {
217 SessionToken sessionToken_ {};
218 bool isAll_ = false;
219 std::vector<AudioStandard::AudioDeviceDescriptor> audioDeviceDescriptors_;
220 };
221 auto context = std::make_shared<ConcreteContext>();
222 auto input = [env, context](size_t argc, napi_value* argv) {
223 CHECK_ARGS_RETURN_VOID(context, argc == ARGC_TWO, "invalid arguments",
224 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
225
226 napi_valuetype type = napi_undefined;
227 context->status = napi_typeof(env, argv[ARGV_FIRST], &type);
228 CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (type == napi_string || type == napi_object),
229 "invalid type invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
230 if (type == napi_string) {
231 std::string flag;
232 context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], flag);
233 CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (flag == "all"),
234 "invalid argument", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
235 context->isAll_ = true;
236 }
237 if (type == napi_object) {
238 context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->sessionToken_);
239 CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (!context->sessionToken_.sessionId.empty()),
240 "invalid session token", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
241 }
242 context->status = NapiUtils::GetValue(env, argv[ARGV_SECOND], context->audioDeviceDescriptors_);
243 CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (context->audioDeviceDescriptors_.size() > 0),
244 "invalid AudioDeviceDescriptor", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
245 };
246 context->GetCbInfo(env, info, input);
247 context->taskId = NAPI_CAST_AUDIO_TASK_ID;
248
249 auto executor = [context]() {
250 int32_t ret = AVSESSION_ERROR;
251 if (context->isAll_) {
252 ret = AVSessionManager::GetInstance().CastAudioForAll(context->audioDeviceDescriptors_);
253 } else {
254 ret = AVSessionManager::GetInstance().CastAudio(context->sessionToken_, context->audioDeviceDescriptors_);
255 }
256 if (ret != AVSESSION_SUCCESS) {
257 if (ret == ERR_NO_PERMISSION) {
258 context->errMessage = "CastAudio failed : native no permission";
259 } else if (ret == ERR_INVALID_PARAM) {
260 context->errMessage = "CastAudio failed : native invalid parameters";
261 } else if (ret == ERR_SESSION_NOT_EXIST) {
262 context->errMessage = "CastAudio failed : native session not exist";
263 } else {
264 context->errMessage = "CastAudio failed : native server exception";
265 }
266 context->status = napi_generic_failure;
267 context->errCode = NapiAVSessionManager::errcode_[ret];
268 }
269 };
270
271 auto complete = [env](napi_value& output) { output = NapiUtils::GetUndefinedValue(env); };
272
273 return NapiAsyncWork::Enqueue(env, context, "CastAudio", executor, complete);
274 }
RegisterNativeSessionListener(napi_env env)275 napi_status NapiAVSessionManager::RegisterNativeSessionListener(napi_env env)
276 {
277 if (listener_ != nullptr) {
278 return napi_ok;
279 }
280
281 listener_ = std::make_shared<NapiSessionListener>();
282 if (listener_ == nullptr) {
283 SLOGE("OnEvent failed : no memory");
284 NapiUtils::ThrowError(env, "OnEvent failed : no memory", NapiAVSessionManager::errcode_[ERR_NO_MEMORY]);
285 return napi_generic_failure;
286 }
287 int32_t ret = AVSessionManager::GetInstance().RegisterSessionListener(listener_);
288 if (ret != AVSESSION_SUCCESS) {
289 SLOGE("native register session listener failed");
290 if (ret == ERR_INVALID_PARAM) {
291 NapiUtils::ThrowError(env, "OnEvent failed : native invalid parameters",
292 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
293 } else if (ret == ERR_NO_PERMISSION) {
294 NapiUtils::ThrowError(env, "OnEvent failed : native no permission",
295 NapiAVSessionManager::errcode_[ERR_NO_PERMISSION]);
296 } else {
297 NapiUtils::ThrowError(env, "OnEvent failed : native server exception",
298 NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
299 }
300 return napi_generic_failure;
301 }
302
303 return napi_ok;
304 }
305
OnEvent(napi_env env,napi_callback_info info)306 napi_value NapiAVSessionManager::OnEvent(napi_env env, napi_callback_info info)
307 {
308 auto context = std::make_shared<ContextBase>();
309 if (context == nullptr) {
310 SLOGE("OnEvent failed : no memory");
311 NapiUtils::ThrowError(env, "OnEvent failed : no memory", NapiAVSessionManager::errcode_[ERR_NO_MEMORY]);
312 return NapiUtils::GetUndefinedValue(env);
313 }
314
315 std::string eventName;
316 napi_value callback = nullptr;
317 auto input = [&eventName, &callback, env, &context](size_t argc, napi_value* argv) {
318 /* require 2 arguments <event, callback> */
319 CHECK_ARGS_RETURN_VOID(context, argc == ARGC_TWO, "invalid argument number",
320 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
321 context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], eventName);
322 CHECK_STATUS_RETURN_VOID(context, "get event name failed", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
323 napi_valuetype type = napi_undefined;
324 context->status = napi_typeof(env, argv[ARGV_SECOND], &type);
325 CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (type == napi_function),
326 "callback type invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
327 callback = argv[ARGV_SECOND];
328 };
329
330 context->GetCbInfo(env, info, input, true);
331 if (context->status != napi_ok) {
332 NapiUtils::ThrowError(env, context->errMessage.c_str(), context->errCode);
333 return NapiUtils::GetUndefinedValue(env);
334 }
335
336 auto it = eventHandlers_.find(eventName);
337 if (it == eventHandlers_.end()) {
338 SLOGE("event name invalid");
339 NapiUtils::ThrowError(env, "event name invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
340 return NapiUtils::GetUndefinedValue(env);
341 }
342
343 if (RegisterNativeSessionListener(env) == napi_generic_failure) {
344 return NapiUtils::GetUndefinedValue(env);
345 }
346
347 if (it->second.first(env, callback) != napi_ok) {
348 NapiUtils::ThrowError(env, "add event callback failed", NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
349 }
350
351 return NapiUtils::GetUndefinedValue(env);
352 }
353
OffEvent(napi_env env,napi_callback_info info)354 napi_value NapiAVSessionManager::OffEvent(napi_env env, napi_callback_info info)
355 {
356 auto context = std::make_shared<ContextBase>();
357 if (context == nullptr) {
358 SLOGE("OnEvent failed : no memory");
359 NapiUtils::ThrowError(env, "OnEvent failed : no memory", NapiAVSessionManager::errcode_[ERR_NO_MEMORY]);
360 return NapiUtils::GetUndefinedValue(env);
361 }
362
363 std::string eventName;
364 napi_value callback = nullptr;
365 auto input = [&eventName, env, &context, &callback](size_t argc, napi_value* argv) {
366 CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE || argc == ARGC_TWO, "invalid argument number",
367 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
368 context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], eventName);
369 CHECK_STATUS_RETURN_VOID(context, "get event name failed",
370 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
371 if (argc == ARGC_TWO) {
372 callback = argv[ARGV_SECOND];
373 }
374 };
375
376 context->GetCbInfo(env, info, input, true);
377 if (context->status != napi_ok) {
378 NapiUtils::ThrowError(env, context->errMessage.c_str(), context->errCode);
379 return NapiUtils::GetUndefinedValue(env);
380 }
381
382 auto it = eventHandlers_.find(eventName);
383 if (it == eventHandlers_.end()) {
384 SLOGE("event name invalid");
385 NapiUtils::ThrowError(env, "event name invalid", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
386 return NapiUtils::GetUndefinedValue(env);
387 }
388
389 if (it->second.second(env, callback) != napi_ok) {
390 NapiUtils::ThrowError(env, "remove event callback failed", NapiAVSessionManager::errcode_[AVSESSION_ERROR]);
391 }
392
393 return NapiUtils::GetUndefinedValue(env);
394 }
395
SendSystemAVKeyEvent(napi_env env,napi_callback_info info)396 napi_value NapiAVSessionManager::SendSystemAVKeyEvent(napi_env env, napi_callback_info info)
397 {
398 AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::SendSystemAVKeyEvent");
399 struct ConcreteContext : public ContextBase {
400 std::shared_ptr<MMI::KeyEvent> keyEvent_;
401 };
402 auto context = std::make_shared<ConcreteContext>();
403 auto input = [env, context](size_t argc, napi_value* argv) {
404 CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE, "invalid arguments",
405 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
406 context->status = NapiUtils::GetValue(env, argv[ARGV_FIRST], context->keyEvent_);
407 CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok) && (context->keyEvent_ != nullptr),
408 "invalid keyEvent", NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
409 };
410 context->GetCbInfo(env, info, input);
411 context->taskId = NAPI_SEND_SYSTEM_AV_KEY_EVENT_TASK_ID;
412
413 auto executor = [context]() {
414 int32_t ret = AVSessionManager::GetInstance().SendSystemAVKeyEvent(*context->keyEvent_);
415 if (ret != AVSESSION_SUCCESS) {
416 if (ret == ERR_COMMAND_NOT_SUPPORT) {
417 context->errMessage = "SendSystemAVKeyEvent failed : native invalid keyEvent";
418 } else if (ret == ERR_NO_PERMISSION) {
419 context->errMessage = "SendSystemAVKeyEvent failed : native no permission";
420 } else {
421 context->errMessage = "SendSystemAVKeyEvent failed : native server exception";
422 }
423 context->status = napi_generic_failure;
424 context->errCode = NapiAVSessionManager::errcode_[ret];
425 }
426 };
427
428 return NapiAsyncWork::Enqueue(env, context, "SendSystemAVKeyEvent", executor);
429 }
430
SendSystemControlCommand(napi_env env,napi_callback_info info)431 napi_value NapiAVSessionManager::SendSystemControlCommand(napi_env env, napi_callback_info info)
432 {
433 AVSESSION_TRACE_SYNC_START("NapiAVSessionManager::SendSystemControlCommand");
434 struct ConcrentContext : public ContextBase {
435 AVControlCommand command;
436 };
437 auto context = std::make_shared<ConcrentContext>();
438 auto input = [env, context](size_t argc, napi_value* argv) {
439 CHECK_ARGS_RETURN_VOID(context, argc == ARGC_ONE, "invalid arguments",
440 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
441 context->status = NapiControlCommand::GetValue(env, argv[ARGV_FIRST], context->command);
442 CHECK_ARGS_RETURN_VOID(context, (context->status == napi_ok), "invalid command",
443 NapiAVSessionManager::errcode_[ERR_INVALID_PARAM]);
444 };
445 context->GetCbInfo(env, info, input);
446 context->taskId = NAPI_SEND_SYSTEM_CONTROL_COMMAND_TASK_ID;
447
448 auto executor = [context]() {
449 int32_t ret = AVSessionManager::GetInstance().SendSystemControlCommand(context->command);
450 #ifdef ENABLE_AVSESSION_SYSEVENT_CONTROL
451 double speed;
452 int64_t time;
453 int32_t mode;
454 std::string assetId;
455 context->command.GetSpeed(speed);
456 context->command.GetSeekTime(time);
457 context->command.GetLoopMode(mode);
458 context->command.GetAssetId(assetId);
459 HISYSEVENT_FAULT("CONTROL_COMMAND_FAILED", "ERROR_TYPE", "SEND_CMD_FAILED",
460 "CMD", context->command.GetCommand(), "TIME", time, "SPEED", speed, "MODE", mode, "ASSETID", assetId,
461 "ERROR_CODE", ret, "ERROR_INFO", "native send control command failed");
462 #endif
463 if (ret != AVSESSION_SUCCESS) {
464 if (ret == ERR_COMMAND_NOT_SUPPORT) {
465 context->errMessage = "SendSystemControlCommand failed : native invalid command";
466 } else if (ret == ERR_NO_PERMISSION) {
467 context->errMessage = "SendSystemControlCommand failed : native send control command no permission";
468 HISYSEVENT_SECURITY("CONTROL_PERMISSION_DENIED", "ERROR_CODE", ret,
469 "ERROR_INFO", "SendSystemControlCommand failed : native no permission");
470 } else if (ret == ERR_COMMAND_SEND_EXCEED_MAX) {
471 context->errMessage = "SendSystemControlCommand failed : native send command overload";
472 } else {
473 context->errMessage = "SendSystemControlCommand failed : native server exception";
474 }
475 context->status = napi_generic_failure;
476 context->errCode = NapiAVSessionManager::errcode_[ret];
477 }
478 };
479
480 return NapiAsyncWork::Enqueue(env, context, "SendSystemControlCommand", executor);
481 }
482
OnSessionCreate(napi_env env,napi_value callback)483 napi_status NapiAVSessionManager::OnSessionCreate(napi_env env, napi_value callback)
484 {
485 return listener_->AddCallback(env, NapiSessionListener::EVENT_SESSION_CREATED, callback);
486 }
487
OnSessionDestroy(napi_env env,napi_value callback)488 napi_status NapiAVSessionManager::OnSessionDestroy(napi_env env, napi_value callback)
489 {
490 return listener_->AddCallback(env, NapiSessionListener::EVENT_SESSION_DESTROYED, callback);
491 }
492
OnTopSessionChange(napi_env env,napi_value callback)493 napi_status NapiAVSessionManager::OnTopSessionChange(napi_env env, napi_value callback)
494 {
495 return listener_->AddCallback(env, NapiSessionListener::EVENT_TOP_SESSION_CHANGED, callback);
496 }
497
OnServiceDie(napi_env env,napi_value callback)498 napi_status NapiAVSessionManager::OnServiceDie(napi_env env, napi_value callback)
499 {
500 napi_ref ref = nullptr;
501 CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, serviceDiedCallbacks_, callback, ref),
502 napi_generic_failure, "get callback reference failed");
503 CHECK_AND_RETURN_RET_LOG(ref == nullptr, napi_ok, "callback has been registered");
504 napi_status status = napi_create_reference(env, callback, ARGC_ONE, &ref);
505 if (status != napi_ok) {
506 SLOGE("napi_create_reference failed");
507 return status;
508 }
509 if (asyncCallback_ == nullptr) {
510 asyncCallback_ = std::make_shared<NapiAsyncCallback>(env);
511 if (asyncCallback_ == nullptr) {
512 SLOGE("no memory");
513 return napi_generic_failure;
514 }
515 }
516 serviceDiedCallbacks_.push_back(ref);
517 if (AVSessionManager::GetInstance().RegisterServiceDeathCallback(HandleServiceDied) != AVSESSION_SUCCESS) {
518 return napi_generic_failure;
519 }
520 return napi_ok;
521 }
522
HandleServiceDied()523 void NapiAVSessionManager::HandleServiceDied()
524 {
525 if (!serviceDiedCallbacks_.empty() && asyncCallback_ != nullptr) {
526 for (auto callbackRef = serviceDiedCallbacks_.begin(); callbackRef != serviceDiedCallbacks_.end();
527 ++callbackRef) {
528 asyncCallback_->Call(*callbackRef);
529 }
530 }
531 }
532
OffSessionCreate(napi_env env,napi_value callback)533 napi_status NapiAVSessionManager::OffSessionCreate(napi_env env, napi_value callback)
534 {
535 return listener_->RemoveCallback(env, NapiSessionListener::EVENT_SESSION_CREATED, callback);
536 }
537
OffSessionDestroy(napi_env env,napi_value callback)538 napi_status NapiAVSessionManager::OffSessionDestroy(napi_env env, napi_value callback)
539 {
540 return listener_->RemoveCallback(env, NapiSessionListener::EVENT_SESSION_DESTROYED, callback);
541 }
542
OffTopSessionChange(napi_env env,napi_value callback)543 napi_status NapiAVSessionManager::OffTopSessionChange(napi_env env, napi_value callback)
544 {
545 return listener_->RemoveCallback(env, NapiSessionListener::EVENT_TOP_SESSION_CHANGED, callback);
546 }
547
OffServiceDie(napi_env env,napi_value callback)548 napi_status NapiAVSessionManager::OffServiceDie(napi_env env, napi_value callback)
549 {
550 AVSessionManager::GetInstance().UnregisterServiceDeathCallback();
551 if (callback == nullptr) {
552 for (auto callbackRef = serviceDiedCallbacks_.begin(); callbackRef != serviceDiedCallbacks_.end();
553 ++callbackRef) {
554 napi_status ret = napi_delete_reference(env, *callbackRef);
555 CHECK_AND_RETURN_RET_LOG(napi_ok == ret, ret, "delete callback reference failed");
556 }
557 serviceDiedCallbacks_.clear();
558 return napi_ok;
559 }
560 napi_ref ref = nullptr;
561 CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, serviceDiedCallbacks_, callback, ref),
562 napi_generic_failure, "get callback reference failed");
563 CHECK_AND_RETURN_RET_LOG(ref != nullptr, napi_ok, "callback has been remove");
564 serviceDiedCallbacks_.remove(ref);
565 return napi_delete_reference(env, ref);
566 }
567 }