• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 "player_callback_napi.h"
17 #include <uv.h>
18 #include "media_errors.h"
19 #include "media_log.h"
20 #include "scope_guard.h"
21 
22 namespace {
23 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_PLAYER, "PlayerCallbackNapi"};
24 const std::string PLAY_CALLBACK_NAME = "play";
25 const std::string PAUSE_CALLBACK_NAME = "pause";
26 const std::string STOP_CALLBACK_NAME = "stop";
27 const std::string RESET_CALLBACK_NAME = "reset";
28 const std::string DATA_LOAD_CALLBACK_NAME = "dataLoad";
29 const std::string FINISH_CALLBACK_NAME = "finish";
30 const std::string TIME_UPDATE_CALLBACK_NAME = "timeUpdate";
31 const std::string ERROR_CALLBACK_NAME = "error";
32 const std::string VOL_CHANGE_CALLBACK_NAME = "volumeChange";
33 const std::string BUFFERING_UPDATE_CALLBACK_NAME = "bufferingUpdate";
34 const std::string AUDIO_INTERRUPT_CALLBACK_NAME = "audioInterrupt";
35 }
36 
37 namespace OHOS {
38 namespace Media {
PlayerCallbackNapi(napi_env env)39 PlayerCallbackNapi::PlayerCallbackNapi(napi_env env)
40     : env_(env)
41 {
42     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
43 }
44 
~PlayerCallbackNapi()45 PlayerCallbackNapi::~PlayerCallbackNapi()
46 {
47     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
48 }
49 
SaveCallbackReference(const std::string & name,std::weak_ptr<AutoRef> ref)50 void PlayerCallbackNapi::SaveCallbackReference(const std::string &name, std::weak_ptr<AutoRef> ref)
51 {
52     std::lock_guard<std::mutex> lock(mutex_);
53     refMap_[name] = ref;
54 }
55 
ClearCallbackReference()56 void PlayerCallbackNapi::ClearCallbackReference()
57 {
58     std::lock_guard<std::mutex> lock(mutex_);
59     refMap_.clear();
60 }
61 
SendErrorCallback(MediaServiceExtErrCode errCode,const std::string & info)62 void PlayerCallbackNapi::SendErrorCallback(MediaServiceExtErrCode errCode, const std::string &info)
63 {
64     MEDIA_LOGE("in ErrorCallback: %{public}s", info.c_str());
65     std::lock_guard<std::mutex> lock(mutex_);
66     if (refMap_.find(ERROR_CALLBACK_NAME) == refMap_.end()) {
67         MEDIA_LOGW("can not find error callback!");
68         return;
69     }
70 
71     PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
72     CHECK_AND_RETURN_LOG(cb != nullptr, "cb is nullptr");
73 
74     cb->callback = refMap_.at(ERROR_CALLBACK_NAME);
75     cb->callbackName = ERROR_CALLBACK_NAME;
76     cb->errorMsg = info;
77     cb->errorCode = errCode;
78     return OnJsCallBackError(cb);
79 }
80 
GetCurrentState() const81 PlayerStates PlayerCallbackNapi::GetCurrentState() const
82 {
83     return currentState_;
84 }
85 
OnError(int32_t errorCode,const std::string & errorMsg)86 void PlayerCallbackNapi::OnError(int32_t errorCode, const std::string &errorMsg)
87 {
88     MEDIA_LOGE("OnErrorCb:errorCode %{public}d, errorMsg %{public}s", errorCode, errorMsg.c_str());
89     MediaServiceExtErrCode err = MSErrorToExtError(static_cast<MediaServiceErrCode>(errorCode));
90     return SendErrorCallback(err, errorMsg);
91 }
92 
OnInfo(PlayerOnInfoType type,int32_t extra,const Format & infoBody)93 void PlayerCallbackNapi::OnInfo(PlayerOnInfoType type, int32_t extra, const Format &infoBody)
94 {
95     std::lock_guard<std::mutex> lock(mutex_);
96     MEDIA_LOGI("OnInfo is called, PlayerOnInfoType: %{public}d", type);
97     switch (type) {
98         case INFO_TYPE_SEEKDONE:
99             OnSeekDoneCb(extra);
100             break;
101         case INFO_TYPE_EOS:
102             OnEosCb(extra);
103             break;
104         case INFO_TYPE_STATE_CHANGE:
105             OnStateChangeCb(static_cast<PlayerStates>(extra));
106             break;
107         case INFO_TYPE_POSITION_UPDATE:
108             OnPositionUpdateCb(extra);
109             break;
110         case INFO_TYPE_MESSAGE:
111             OnMessageCb(extra);
112             break;
113         case INFO_TYPE_VOLUME_CHANGE:
114             OnVolumeChangeCb();
115             break;
116         case INFO_TYPE_BUFFERING_UPDATE:
117             OnBufferingUpdateCb(infoBody);
118             break;
119         case INFO_TYPE_INTERRUPT_EVENT:
120             OnAudioInterruptCb(infoBody);
121             break;
122         default:
123             break;
124     }
125     MEDIA_LOGD("send OnInfo callback success");
126 }
127 
OnSeekDoneCb(int32_t currentPositon) const128 void PlayerCallbackNapi::OnSeekDoneCb(int32_t currentPositon) const
129 {
130     MEDIA_LOGD("OnSeekDone is called, currentPositon: %{public}d", currentPositon);
131 }
132 
OnBufferingUpdateCb(const Format & infoBody) const133 void PlayerCallbackNapi::OnBufferingUpdateCb(const Format &infoBody) const
134 {
135     if (refMap_.find(BUFFERING_UPDATE_CALLBACK_NAME) == refMap_.end()) {
136         MEDIA_LOGW("can not find buffering update callback!");
137         return;
138     }
139 
140     PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
141     CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
142     cb->callback = refMap_.at(BUFFERING_UPDATE_CALLBACK_NAME);
143     cb->callbackName = BUFFERING_UPDATE_CALLBACK_NAME;
144 
145     int32_t value = 0;
146     int32_t bufferingType = -1;
147     if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_BUFFERING_START))) {
148         bufferingType = BUFFERING_START;
149         (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_START), value);
150     } else if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_BUFFERING_END))) {
151         bufferingType = BUFFERING_END;
152         (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_END), value);
153     } else if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_BUFFERING_PERCENT))) {
154         bufferingType = BUFFERING_PERCENT;
155         (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_BUFFERING_PERCENT), value);
156     } else if (infoBody.ContainKey(std::string(PlayerKeys::PLAYER_CACHED_DURATION))) {
157         bufferingType = CACHED_DURATION;
158         (void)infoBody.GetIntValue(std::string(PlayerKeys::PLAYER_CACHED_DURATION), value);
159     } else {
160         delete cb;
161         return;
162     }
163 
164     MEDIA_LOGD("OnBufferingUpdateCb is called, buffering type: %{public}d value: %{public}d", bufferingType, value);
165 
166     cb->valueVec.push_back(bufferingType);
167     cb->valueVec.push_back(value);
168     return OnJsCallBackIntVec(cb);
169 }
170 
OnEosCb(int32_t isLooping) const171 void PlayerCallbackNapi::OnEosCb(int32_t isLooping) const
172 {
173     MEDIA_LOGD("OnEndOfStream is called, isloop: %{public}d", isLooping);
174 }
175 
OnStateChangeCb(PlayerStates state)176 void PlayerCallbackNapi::OnStateChangeCb(PlayerStates state)
177 {
178     MEDIA_LOGD("OnStateChanged is called, current state: %{public}d", state);
179     currentState_ = state;
180 
181     std::string callbackName = "unknown";
182     switch (state) {
183         case PLAYER_PREPARED:
184             callbackName = DATA_LOAD_CALLBACK_NAME;
185             break;
186         case PLAYER_STARTED:
187             callbackName = PLAY_CALLBACK_NAME;
188             break;
189         case PLAYER_PAUSED:
190             callbackName = PAUSE_CALLBACK_NAME;
191             break;
192         case PLAYER_STOPPED:
193             callbackName = STOP_CALLBACK_NAME;
194             break;
195         case PLAYER_IDLE:
196             callbackName = RESET_CALLBACK_NAME;
197             break;
198         case PLAYER_PLAYBACK_COMPLETE:
199             callbackName = FINISH_CALLBACK_NAME;
200             break;
201         default:
202             callbackName = "unknown";
203             break;
204     }
205 
206     if (refMap_.find(callbackName) == refMap_.end()) {
207         MEDIA_LOGW("can not find %{public}s callback!", callbackName.c_str());
208         return;
209     }
210 
211     PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
212     CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
213     cb->callback = refMap_.at(callbackName);
214     cb->callbackName = callbackName;
215     return OnJsCallBack(cb);
216 }
217 
OnPositionUpdateCb(int32_t position) const218 void PlayerCallbackNapi::OnPositionUpdateCb(int32_t position) const
219 {
220     MEDIA_LOGD("OnPositionUpdateCb is called, position: %{public}d", position);
221     if (refMap_.find(TIME_UPDATE_CALLBACK_NAME) == refMap_.end()) {
222         MEDIA_LOGW("can not find timeupdate callback!");
223         return;
224     }
225 
226     PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
227     CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
228     cb->callback = refMap_.at(TIME_UPDATE_CALLBACK_NAME);
229     cb->callbackName = TIME_UPDATE_CALLBACK_NAME;
230     cb->valueVec.push_back(position);
231     return OnJsCallBackInt(cb);
232 }
233 
OnMessageCb(int32_t type) const234 void PlayerCallbackNapi::OnMessageCb(int32_t type) const
235 {
236     MEDIA_LOGD("OnMessageCb is called, type: %{public}d", type);
237 }
238 
OnVolumeChangeCb()239 void PlayerCallbackNapi::OnVolumeChangeCb()
240 {
241     MEDIA_LOGD("OnVolumeChangeCb in");
242     if (refMap_.find(VOL_CHANGE_CALLBACK_NAME) == refMap_.end()) {
243         MEDIA_LOGW("can not find vol change callback!");
244         return;
245     }
246     PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
247     CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
248     cb->callback = refMap_.at(VOL_CHANGE_CALLBACK_NAME);
249     cb->callbackName = VOL_CHANGE_CALLBACK_NAME;
250     return OnJsCallBack(cb);
251 }
252 
OnAudioInterruptCb(const Format & infoBody) const253 void PlayerCallbackNapi::OnAudioInterruptCb(const Format &infoBody) const
254 {
255     MEDIA_LOGD("OnAudioInterruptCb in");
256     if (refMap_.find(AUDIO_INTERRUPT_CALLBACK_NAME) == refMap_.end()) {
257         MEDIA_LOGW("can not find audio interrupt callback!");
258         return;
259     }
260 
261     PlayerJsCallback *cb = new(std::nothrow) PlayerJsCallback();
262     CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
263     cb->callback = refMap_.at(AUDIO_INTERRUPT_CALLBACK_NAME);
264     cb->callbackName = AUDIO_INTERRUPT_CALLBACK_NAME;
265     int32_t eventType = 0;
266     int32_t forceType = 0;
267     int32_t hintType = 0;
268     (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_TYPE, eventType);
269     (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_FORCE, forceType);
270     (void)infoBody.GetIntValue(PlayerKeys::AUDIO_INTERRUPT_HINT, hintType);
271     cb->interruptEvent.eventType = AudioStandard::InterruptType(eventType);
272     cb->interruptEvent.forceType = AudioStandard::InterruptForceType(forceType);
273     cb->interruptEvent.hintType = AudioStandard::InterruptHint(hintType);
274     return OnJsCallBackInterrupt(cb);
275 }
276 
OnJsCallBack(PlayerJsCallback * jsCb) const277 void PlayerCallbackNapi::OnJsCallBack(PlayerJsCallback *jsCb) const
278 {
279     auto task = [event = jsCb]() {
280                 // Js Thread
281         std::string request = event->callbackName;
282         MEDIA_LOGD("JsCallBack %{public}s, uv_queue_work start", request.c_str());
283         do {
284             std::shared_ptr<AutoRef> ref = event->callback.lock();
285             CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
286 
287             napi_handle_scope scope = nullptr;
288             napi_open_handle_scope(ref->env_, &scope);
289             CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
290             ON_SCOPE_EXIT(0) {
291                 napi_close_handle_scope(ref->env_, scope);
292             };
293 
294             napi_value jsCallback = nullptr;
295             napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
296             CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr,
297                 "%{public}s get reference value fail", request.c_str());
298 
299             // Call back function
300             napi_value result = nullptr;
301             nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 0, nullptr, &result);
302             CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to napi call function", request.c_str());
303         } while (0);
304         delete event;
305     };
306 
307     auto ret = napi_send_event(env_, task, napi_eprio_high);
308     if (ret != napi_status::napi_ok) {
309         MEDIA_LOGE("Failed to SendEvent, ret = %{public}d", ret);
310         delete jsCb;
311     }
312 }
313 
OnJsCallBackError(PlayerJsCallback * jsCb) const314 void PlayerCallbackNapi::OnJsCallBackError(PlayerJsCallback *jsCb) const
315 {
316     ON_SCOPE_EXIT(0) {
317         delete jsCb;
318     };
319 
320     auto task = [event = jsCb]() {
321         // Js Thread
322         std::string request = event->callbackName;
323         MEDIA_LOGD("JsCallBack %{public}s, uv_queue_work start", request.c_str());
324         do {
325             std::shared_ptr<AutoRef> ref = event->callback.lock();
326             CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
327 
328             napi_handle_scope scope = nullptr;
329             napi_open_handle_scope(ref->env_, &scope);
330             CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
331             ON_SCOPE_EXIT(0) {
332                 napi_close_handle_scope(ref->env_, scope);
333             };
334 
335             napi_value jsCallback = nullptr;
336             napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
337             CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
338                 request.c_str());
339 
340             napi_value msgValStr = nullptr;
341             nstatus = napi_create_string_utf8(ref->env_, event->errorMsg.c_str(), NAPI_AUTO_LENGTH, &msgValStr);
342             CHECK_AND_BREAK_LOG(nstatus == napi_ok && msgValStr != nullptr, "create error message str fail");
343 
344             napi_value args[1] = { nullptr };
345             nstatus = napi_create_error(ref->env_, nullptr, msgValStr, &args[0]);
346             CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[0] != nullptr, "create error callback fail");
347 
348             nstatus = CommonNapi::FillErrorArgs(ref->env_, static_cast<int32_t>(event->errorCode), args[0]);
349             CHECK_AND_BREAK_LOG(nstatus == napi_ok, "create error callback fail");
350 
351             // Call back function
352             napi_value result = nullptr;
353             nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
354             CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to napi call function", request.c_str());
355         } while (0);
356         delete event;
357     };
358 
359     auto ret = napi_send_event(env_, task, napi_eprio_high);
360     if (ret != napi_status::napi_ok) {
361         MEDIA_LOGE("Failed to SendEvent, ret = %{public}d", ret);
362         delete jsCb;
363     }
364     CANCEL_SCOPE_EXIT_GUARD(0);
365 }
366 
OnJsCallBackInt(PlayerJsCallback * jsCb) const367 void PlayerCallbackNapi::OnJsCallBackInt(PlayerJsCallback *jsCb) const
368 {
369     auto task = [event = jsCb]() {
370         // Js Thread
371         std::string request = event->callbackName;
372         MEDIA_LOGD("JsCallBack %{public}s, uv_queue_work start", request.c_str());
373         do {
374             std::shared_ptr<AutoRef> ref = event->callback.lock();
375             CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
376 
377             napi_handle_scope scope = nullptr;
378             napi_open_handle_scope(ref->env_, &scope);
379             CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
380             ON_SCOPE_EXIT(0) {
381                 napi_close_handle_scope(ref->env_, scope);
382             };
383 
384             napi_value jsCallback = nullptr;
385             napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
386             CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
387                 request.c_str());
388 
389             CHECK_AND_BREAK_LOG(event->valueVec.size() == 1, "%{public}s get reference value fail", request.c_str());
390             // Call back function
391             napi_value args[1] = { nullptr };
392             nstatus = napi_create_int32(ref->env_, event->valueVec[0], &args[0]);
393             CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[0] != nullptr,
394                 "%{public}s fail to create callback", request.c_str());
395 
396             napi_value result = nullptr;
397             nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
398             CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call seekDone callback", request.c_str());
399         } while (0);
400         delete event;
401     };
402 
403     auto ret = napi_send_event(env_, task, napi_eprio_high);
404     if (ret != napi_status::napi_ok) {
405         MEDIA_LOGE("Failed to SendEvent, ret = %{public}d", ret);
406         delete jsCb;
407     }
408 }
409 
OnJsCallBackIntVec(PlayerJsCallback * jsCb) const410 void PlayerCallbackNapi::OnJsCallBackIntVec(PlayerJsCallback *jsCb) const
411 {
412     ON_SCOPE_EXIT(0) {
413         delete jsCb;
414     };
415 
416     auto task = [event = jsCb]() {
417         // Js Thread
418         std::string request = event->callbackName;
419         MEDIA_LOGD("JsCallBack %{public}s, uv_queue_work start", request.c_str());
420         do {
421             std::shared_ptr<AutoRef> ref = event->callback.lock();
422             CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
423 
424             napi_handle_scope scope = nullptr;
425             napi_open_handle_scope(ref->env_, &scope);
426             CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
427             ON_SCOPE_EXIT(0) {
428                 napi_close_handle_scope(ref->env_, scope);
429             };
430 
431             napi_value jsCallback = nullptr;
432             napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
433             CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
434                 request.c_str());
435 
436             CHECK_AND_BREAK_LOG(event->valueVec.size() == 2, "%{public}s get reference value fail", request.c_str());
437             // Call back function
438             napi_value args[2] = { nullptr };
439             nstatus = napi_create_int32(ref->env_, event->valueVec[0], &args[0]);
440             CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[0] != nullptr,
441                 "%{public}s fail to create callback", request.c_str());
442 
443             nstatus = napi_create_int32(ref->env_, event->valueVec[1], &args[1]);
444             CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[1] != nullptr,
445                 "%{public}s fail to create callback", request.c_str());
446 
447             const size_t argCount = 2;
448             napi_value result = nullptr;
449             nstatus = napi_call_function(ref->env_, nullptr, jsCallback, argCount, args, &result);
450             CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call callback", request.c_str());
451         } while (0);
452         delete event;
453     };
454 
455     auto ret = napi_send_event(env_, task, napi_eprio_high);
456     if (ret != napi_status::napi_ok) {
457         MEDIA_LOGE("Failed to SendEvent, ret = %{public}d", ret);
458         delete jsCb;
459     }
460     CANCEL_SCOPE_EXIT_GUARD(0);
461 }
462 
OnJsCallBackIntArray(PlayerJsCallback * jsCb) const463 void PlayerCallbackNapi::OnJsCallBackIntArray(PlayerJsCallback *jsCb) const
464 {
465     auto task = [event = jsCb]() {
466         // Js Thread
467         std::string request = event->callbackName;
468         MEDIA_LOGD("JsCallBack %{public}s, size = %{public}zu", request.c_str(), event->valueVec.size());
469 
470         do {
471             std::shared_ptr<AutoRef> ref = event->callback.lock();
472             CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
473 
474             napi_handle_scope scope = nullptr;
475             napi_open_handle_scope(ref->env_, &scope);
476             CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
477             ON_SCOPE_EXIT(0) {
478                 napi_close_handle_scope(ref->env_, scope);
479             };
480 
481             napi_value jsCallback = nullptr;
482             napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
483             CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr,
484                 "%{public}s failed call callback", request.c_str());
485 
486             napi_value array = nullptr;
487             bool ret = CommonNapi::AddArrayInt(ref->env_, array, event->valueVec);
488             CHECK_AND_BREAK_LOG(ret == true, "%{public}s failed call callback", request.c_str());
489 
490             napi_value result = nullptr;
491             napi_value args[1] = {array};
492             nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
493             CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call callback", request.c_str());
494         } while (0);
495         delete event;
496     };
497 
498     auto ret = napi_send_event(env_, task, napi_eprio_high);
499     if (ret != napi_status::napi_ok) {
500         MEDIA_LOGE("Failed to SendEvent, ret = %{public}d", ret);
501         delete jsCb;
502     }
503 }
504 
OnJsCallBackInterrupt(PlayerJsCallback * jsCb) const505 void PlayerCallbackNapi::OnJsCallBackInterrupt(PlayerJsCallback *jsCb) const
506 {
507     ON_SCOPE_EXIT(0) {
508         delete jsCb;
509     };
510 
511     auto task = [event = jsCb]() {
512         std::string request = event->callbackName;
513         MEDIA_LOGD("JsCallBack %{public}s", request.c_str());
514 
515         do {
516             std::shared_ptr<AutoRef> ref = event->callback.lock();
517             CHECK_AND_BREAK_LOG(ref != nullptr, "%{public}s AutoRef is nullptr", request.c_str());
518 
519             napi_handle_scope scope = nullptr;
520             napi_open_handle_scope(ref->env_, &scope);
521             CHECK_AND_BREAK_LOG(scope != nullptr, "%{public}s scope is nullptr", request.c_str());
522             ON_SCOPE_EXIT(0) {
523                 napi_close_handle_scope(ref->env_, scope);
524             };
525 
526             napi_value jsCallback = nullptr;
527             napi_status nstatus = napi_get_reference_value(ref->env_, ref->cb_, &jsCallback);
528             CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr,
529                 "%{public}s failed call callback", request.c_str());
530 
531             napi_value args[1] = {nullptr};
532             napi_create_object(ref->env_, &args[0]);
533             CommonNapi::SetPropertyInt32(ref->env_, args[0], "eventType",
534                 static_cast<int32_t>(event->interruptEvent.eventType));
535             CommonNapi::SetPropertyInt32(ref->env_, args[0], "forceType",
536                 static_cast<int32_t>(event->interruptEvent.forceType));
537             CommonNapi::SetPropertyInt32(ref->env_, args[0], "hintType",
538                 static_cast<int32_t>(event->interruptEvent.hintType));
539 
540             napi_value result = nullptr;
541             nstatus = napi_call_function(ref->env_, nullptr, jsCallback, 1, args, &result);
542             CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call callback", request.c_str());
543         } while (0);
544         delete event;
545     };
546 
547     auto ret = napi_send_event(env_, task, napi_eprio_high);
548     if (ret != napi_status::napi_ok) {
549         MEDIA_LOGE("Failed to SendEvent, ret = %{public}d", ret);
550         delete jsCb;
551     }
552     CANCEL_SCOPE_EXIT_GUARD(0);
553 }
554 } // namespace Media
555 } // namespace OHOS
556