• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }