• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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_avcast_controller_callback.h"
17 #include "avsession_log.h"
18 #include "avsession_trace.h"
19 #include "napi_control_command.h"
20 #include "napi_meta_data.h"
21 #include "napi_playback_state.h"
22 #include "napi_media_description.h"
23 #include "napi_queue_item.h"
24 #include "napi_utils.h"
25 #include "napi_cast_control_command.h"
26 
27 namespace OHOS::AVSession {
NapiAVCastControllerCallback()28 NapiAVCastControllerCallback::NapiAVCastControllerCallback()
29 {
30     SLOGI("construct");
31 }
32 
~NapiAVCastControllerCallback()33 NapiAVCastControllerCallback::~NapiAVCastControllerCallback()
34 {
35     if (dataSrcRef_ != nullptr) {
36         napi_ref ref = dataSrcRef_;
37         dataSrcRef_ = nullptr;
38         napi_delete_reference(env_, ref);
39     }
40     SLOGI("destroy");
41 }
42 
HandleEvent(int32_t event)43 void NapiAVCastControllerCallback::HandleEvent(int32_t event)
44 {
45     std::lock_guard<std::mutex> lockGuard(lock_);
46     if (callbacks_[event].empty()) {
47         SLOGE("not register callback event=%{public}d", event);
48         return;
49     }
50     for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
51         asyncCallback_->Call(*ref);
52     }
53 }
54 
CheckCallbackValid(int32_t event,const std::list<napi_ref>::iterator & ref)55 std::function<bool()> NapiAVCastControllerCallback::CheckCallbackValid(int32_t event,
56     const std::list<napi_ref>::iterator& ref)
57 {
58     return [this, event, ref]() {
59         std::lock_guard<std::mutex> lockGuard(lock_);
60         if (callbacks_[event].empty()) {
61             SLOGE("checkCallbackValid with empty list for event %{public}d", event);
62             return false;
63         }
64         bool hasFunc = false;
65         for (auto it = callbacks_[event].begin(); it != callbacks_[event].end(); ++it) {
66             hasFunc = (ref == it ? true : hasFunc);
67         }
68         SLOGD("checkCallbackValid return hasFunc %{public}d, %{public}d", hasFunc, event);
69         return hasFunc;
70     };
71 }
72 
73 template<typename T>
HandleEvent(int32_t event,const T & param)74 void NapiAVCastControllerCallback::HandleEvent(int32_t event, const T& param)
75 {
76     std::lock_guard<std::mutex> lockGuard(lock_);
77     if (callbacks_[event].empty()) {
78         SLOGE("not register callback event=%{public}d", event);
79         return;
80     }
81     for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
82         SLOGI("call with flag for event %{public}d", event);
83         asyncCallback_->CallWithFunc(*ref, isValid_, CheckCallbackValid(event, ref),
84             [param](napi_env env, int& argc, napi_value *argv) {
85                 argc = NapiUtils::ARGC_ONE;
86                 auto status = NapiUtils::SetValue(env, param, *argv);
87                 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
88             });
89     }
90 }
91 
92 template<typename T>
HandleEvent(int32_t event,const std::string & firstParam,const T & secondParam)93 void NapiAVCastControllerCallback::HandleEvent(int32_t event, const std::string& firstParam, const T& secondParam)
94 {
95     std::lock_guard<std::mutex> lockGuard(lock_);
96     if (callbacks_[event].empty()) {
97         SLOGE("not register callback event=%{public}d", event);
98         return;
99     }
100     for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
101         asyncCallback_->CallWithFunc(*ref, isValid_, CheckCallbackValid(event, ref),
102             [firstParam, secondParam](napi_env env, int& argc, napi_value *argv) {
103                 argc = NapiUtils::ARGC_TWO;
104                 auto status = NapiUtils::SetValue(env, firstParam, argv[0]);
105                 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
106                 status = NapiUtils::SetValue(env, secondParam, argv[1]);
107                 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
108             });
109     }
110 }
111 
112 template<typename T>
HandleEvent(int32_t event,const int32_t firstParam,const T & secondParam)113 void NapiAVCastControllerCallback::HandleEvent(int32_t event, const int32_t firstParam, const T& secondParam)
114 {
115     std::lock_guard<std::mutex> lockGuard(lock_);
116     if (callbacks_[event].empty()) {
117         SLOGE("not register callback event=%{public}d", event);
118         return;
119     }
120     for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
121         asyncCallback_->CallWithFunc(*ref, isValid_, CheckCallbackValid(event, ref),
122             [firstParam, secondParam](napi_env env, int& argc, napi_value *argv) {
123                 argc = NapiUtils::ARGC_TWO;
124                 auto status = NapiUtils::SetValue(env, firstParam, argv[0]);
125                 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
126                 status = NapiUtils::SetValue(env, secondParam, argv[1]);
127                 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
128             });
129     }
130 }
131 
HandleEvent(int32_t event,const int32_t firstParam,const int32_t secondParam,const int32_t thirdParam)132 void NapiAVCastControllerCallback::HandleEvent(int32_t event,
133     const int32_t firstParam, const int32_t secondParam, const int32_t thirdParam)
134 {
135     std::lock_guard<std::mutex> lockGuard(lock_);
136     if (callbacks_[event].empty()) {
137         SLOGE("not register callback event=%{public}d", event);
138         return;
139     }
140     for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
141         asyncCallback_->CallWithFunc(*ref, isValid_, CheckCallbackValid(event, ref),
142             [firstParam, secondParam, thirdParam](napi_env env, int& argc, napi_value *argv) {
143                 argc = NapiUtils::ARGC_THREE;
144                 auto status = NapiUtils::SetValue(env, firstParam, argv[NapiUtils::ARGV_FIRST]);
145                 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
146                 status = NapiUtils::SetValue(env, secondParam, argv[NapiUtils::ARGV_SECOND]);
147                 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
148                 status = NapiUtils::SetValue(env, thirdParam, argv[NapiUtils::ARGV_THIRD]);
149                 CHECK_RETURN_VOID(status == napi_ok, "ControllerCallback SetValue invalid");
150             });
151     }
152 }
153 
HandleErrorEvent(int32_t event,const int32_t errorCode,const std::string & errorMsg)154 void NapiAVCastControllerCallback::HandleErrorEvent(int32_t event, const int32_t errorCode,
155     const std::string& errorMsg)
156 {
157     std::lock_guard<std::mutex> lockGuard(lock_);
158     if (callbacks_[event].empty()) {
159         SLOGE("not register callback event=%{public}d", event);
160         return;
161     }
162     for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
163         asyncCallback_->CallWithFunc(*ref, isValid_, CheckCallbackValid(event, ref),
164             [errorCode, errorMsg](napi_env env, int& argc, napi_value *argv) {
165                 napi_status status = napi_create_object(env, argv);
166                 CHECK_RETURN_VOID((status == napi_ok) && (argv != nullptr), "create object failed");
167 
168                 napi_value property = nullptr;
169                 status = NapiUtils::SetValue(env, errorCode, property);
170                 CHECK_RETURN_VOID((status == napi_ok) && (property != nullptr), "create property failed");
171                 status = napi_set_named_property(env, *argv, "code", property);
172                 CHECK_RETURN_VOID(status == napi_ok, "napi_set_named_property failed");
173 
174                 status = NapiUtils::SetValue(env, errorMsg, property);
175                 CHECK_RETURN_VOID((status == napi_ok) && (property != nullptr), "create property failed");
176                 status = napi_set_named_property(env, *argv, "message", property);
177                 CHECK_RETURN_VOID(status == napi_ok, "napi_set_named_property failed");
178             });
179     }
180 }
181 
OnCastPlaybackStateChange(const AVPlaybackState & state)182 void NapiAVCastControllerCallback::OnCastPlaybackStateChange(const AVPlaybackState& state)
183 {
184     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnCastPlaybackStateChange");
185     SLOGI("Start handle OnCastPlaybackStateChange event with state: %{public}d", state.GetState());
186     HandleEvent(EVENT_CAST_PLAYBACK_STATE_CHANGE, state);
187 }
188 
OnMediaItemChange(const AVQueueItem & avQueueItem)189 void NapiAVCastControllerCallback::OnMediaItemChange(const AVQueueItem& avQueueItem)
190 {
191     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnMediaItemChange");
192     SLOGI("Start handle OnMediaItemChange event");
193     HandleEvent(EVENT_CAST_MEDIA_ITEM_CHANGE, avQueueItem);
194 }
195 
OnPlayNext()196 void NapiAVCastControllerCallback::OnPlayNext()
197 {
198     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnPlayNext");
199     SLOGI("Start handle OnPlayNext event");
200     HandleEvent(EVENT_CAST_PLAY_NEXT);
201 }
202 
OnPlayPrevious()203 void NapiAVCastControllerCallback::OnPlayPrevious()
204 {
205     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnPlayPrevious");
206     SLOGI("Start handle OnPlayPrevious event");
207     HandleEvent(EVENT_CAST_PLAY_PREVIOUS);
208 }
209 
OnSeekDone(const int32_t seekNumber)210 void NapiAVCastControllerCallback::OnSeekDone(const int32_t seekNumber)
211 {
212     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnSeekDone");
213     SLOGI("Start handle OnSeekDone event");
214     HandleEvent(EVENT_CAST_SEEK_DONE, seekNumber);
215 }
216 
OnVideoSizeChange(const int32_t width,const int32_t height)217 void NapiAVCastControllerCallback::OnVideoSizeChange(const int32_t width, const int32_t height)
218 {
219     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnVideoSizeChange");
220     SLOGI("Start handle OnVideoSizeChange event");
221     HandleEvent(EVENT_CAST_VIDEO_SIZE_CHANGE, width, height);
222 }
223 
HandlePlayerErrorAPI13(const int32_t errorCode,const std::string & errorMsg)224 void NapiAVCastControllerCallback::HandlePlayerErrorAPI13(const int32_t errorCode, const std::string& errorMsg)
225 {
226     CastExtErrCodeAPI13 jsErr;
227     if (CAST_GENERIC_ERRCODE_INFOS.count(static_cast<CastErrCode>(errorCode)) != 0 &&
228         CASTERRCODE_TO_EXTERRORCODEAPI13.count(static_cast<CastErrCode>(errorCode)) != 0) {
229         // Generic error
230         jsErr = CASTERRCODE_TO_EXTERRORCODEAPI13.at(static_cast<CastErrCode>(errorCode));
231         SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
232         HandleErrorEvent(EVENT_CAST_GENERIC_ERR, static_cast<int32_t>(jsErr), errorMsg);
233     } else if (CAST_IO_ERRCODE_INFOS.count(static_cast<CastErrCode>(errorCode)) != 0 &&
234         CASTERRCODE_TO_EXTERRORCODEAPI13.count(static_cast<CastErrCode>(errorCode)) != 0) {
235         // Input/Output errors
236         jsErr = CASTERRCODE_TO_EXTERRORCODEAPI13.at(static_cast<CastErrCode>(errorCode));
237         SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
238         HandleErrorEvent(EVENT_CAST_IO_ERR, static_cast<int32_t>(jsErr), errorMsg);
239     } else if (CAST_PARSING_ERRCODE_INFOS.count(static_cast<CastErrCode>(errorCode)) != 0 &&
240         CASTERRCODE_TO_EXTERRORCODEAPI13.count(static_cast<CastErrCode>(errorCode)) != 0) {
241         // Content parsing errors
242         jsErr = CASTERRCODE_TO_EXTERRORCODEAPI13.at(static_cast<CastErrCode>(errorCode));
243         SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
244         HandleErrorEvent(EVENT_CAST_PARSING_ERR, static_cast<int32_t>(jsErr), errorMsg);
245     } else if (CAST_DECODE_ERRCODE_INFOS.count(static_cast<CastErrCode>(errorCode)) != 0 &&
246         CASTERRCODE_TO_EXTERRORCODEAPI13.count(static_cast<CastErrCode>(errorCode)) != 0) {
247         // Decoding errors
248         jsErr = CASTERRCODE_TO_EXTERRORCODEAPI13.at(static_cast<CastErrCode>(errorCode));
249         SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
250         HandleErrorEvent(EVENT_CAST_DECOD_EERR, static_cast<int32_t>(jsErr), errorMsg);
251     } else if (CAST_RENDER_ERRCODE_INFOS.count(static_cast<CastErrCode>(errorCode)) != 0 &&
252         CASTERRCODE_TO_EXTERRORCODEAPI13.count(static_cast<CastErrCode>(errorCode)) != 0) {
253         // AudioRender errors
254         jsErr = CASTERRCODE_TO_EXTERRORCODEAPI13.at(static_cast<CastErrCode>(errorCode));
255         SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
256         HandleErrorEvent(EVENT_CAST_RENDER_ERR, static_cast<int32_t>(jsErr), errorMsg);
257     } else if (CAST_DRM_ERRCODE_INFOS.count(static_cast<CastErrCode>(errorCode)) != 0 &&
258         CASTERRCODE_TO_EXTERRORCODEAPI13.count(static_cast<CastErrCode>(errorCode)) != 0) {
259         // DRM errors
260         jsErr = CASTERRCODE_TO_EXTERRORCODEAPI13.at(static_cast<CastErrCode>(errorCode));
261         SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
262         HandleErrorEvent(EVENT_CAST_DRM_ERR, static_cast<int32_t>(jsErr), errorMsg);
263     } else {
264         SLOGW("Can not match error code, use default");
265         // If error not in map, need add error and should not return default ERROR_CODE_UNSPECIFIED.
266         jsErr = CAST_GENERICERR_EXT_API13_UNSPECIFIED;
267         SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
268         HandleErrorEvent(EVENT_CAST_GENERIC_ERR, static_cast<int32_t>(jsErr), errorMsg);
269     }
270 }
271 
OnPlayerError(const int32_t errorCode,const std::string & errorMsg)272 void NapiAVCastControllerCallback::OnPlayerError(const int32_t errorCode, const std::string& errorMsg)
273 {
274     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnPlayerError");
275     SLOGI("Start handle OnPlayerError event");
276     if (static_cast<MediaServiceErrCode>(errorCode) >= MSERR_NO_MEMORY &&
277         static_cast<MediaServiceErrCode>(errorCode) <= MSERR_EXTEND_START) {
278         MediaServiceExtErrCodeAPI9 jsErr;
279         if (MSERRCODE_INFOS.count(static_cast<MediaServiceErrCode>(errorCode)) != 0 &&
280             MSERRCODE_TO_EXTERRORCODEAPI9.count(static_cast<MediaServiceErrCode>(errorCode)) != 0) {
281             jsErr = MSERRCODE_TO_EXTERRORCODEAPI9.at(static_cast<MediaServiceErrCode>(errorCode));
282         } else {
283             SLOGW("Can not match error code, use default");
284             // If error not in map, need add error and should not return default MSERR_EXT_API9_IO.
285             jsErr = MSERR_EXT_API9_IO;
286         }
287         SLOGI("Native errCode: %{public}d, JS errCode: %{public}d", errorCode, static_cast<int32_t>(jsErr));
288         HandleErrorEvent(EVENT_CAST_ERROR, static_cast<int32_t>(jsErr), errorMsg);
289     } else {
290         HandlePlayerErrorAPI13(errorCode, errorMsg);
291     }
292 }
293 
OnEndOfStream(const int32_t isLooping)294 void NapiAVCastControllerCallback::OnEndOfStream(const int32_t isLooping)
295 {
296     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnEndOfStream");
297     SLOGI("Start handle OnEndOfStream event");
298     HandleEvent(EVENT_CAST_END_OF_STREAM, isLooping);
299 }
300 
OnPlayRequest(const AVQueueItem & avQueueItem)301 void NapiAVCastControllerCallback::OnPlayRequest(const AVQueueItem& avQueueItem)
302 {
303     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnPlayRequest");
304     SLOGI("Start handle OnPlayRequest event");
305     HandleEvent(EVENT_CAST_PLAY_REQUEST, avQueueItem);
306 }
307 
OnKeyRequest(const std::string & assetId,const std::vector<uint8_t> & keyRequestData)308 void NapiAVCastControllerCallback::OnKeyRequest(const std::string &assetId, const std::vector<uint8_t> &keyRequestData)
309 {
310     AVSESSION_TRACE_SYNC_START("NapiAVCastControllerCallback::OnKeyRequest");
311     SLOGI("Start handle OnKeyRequest event");
312     HandleEvent(EVENT_CAST_KEY_REQUEST, assetId, keyRequestData);
313 }
314 
OnCastValidCommandChanged(const std::vector<int32_t> & cmds)315 void NapiAVCastControllerCallback::OnCastValidCommandChanged(const std::vector<int32_t>& cmds)
316 {
317     SLOGI("Start handle OnValidCommandChanged event. cmd size:%{public}zd", cmds.size());
318     std::vector<std::string> stringCmds = NapiCastControlCommand::ConvertCommands(cmds);
319     HandleEvent(EVENT_CAST_VALID_COMMAND_CHANGED, stringCmds);
320 }
321 
onDataSrcRead(std::shared_ptr<AVSharedMemory> mem,uint32_t length,int64_t pos)322 int32_t NapiAVCastControllerCallback::onDataSrcRead(std::shared_ptr<AVSharedMemory> mem, uint32_t length, int64_t pos)
323 {
324     SLOGI("napi onDataSrcRead length %{public}d", length);
325     return readDataSrc(env_, mem, length, pos);
326 }
327 
saveDataSrc(napi_env env,napi_value avQueueItem)328 napi_status NapiAVCastControllerCallback::saveDataSrc(napi_env env, napi_value avQueueItem)
329 {
330     napi_value fileSize;
331     napi_value callback {};
332     napi_status status = NapiQueueItem::GetDataSrc(env, avQueueItem, &fileSize, &callback);
333     CHECK_RETURN(status == napi_ok, "GetDataSrc value failed", status);
334     if (status != napi_ok) {
335         SLOGI("no saveDataSrc, reset");
336         return status;
337     }
338 
339     napi_env preEnv = env_;
340     env_ = env;
341     if (dataSrcRef_ != nullptr) {
342         napi_ref ref = dataSrcRef_;
343         dataSrcRef_ = nullptr;
344         napi_delete_reference(preEnv, ref);
345     }
346     status = napi_create_reference(env, callback, 1, &dataSrcRef_);
347     CHECK_RETURN(status == napi_ok, "napi_create_reference failed", status);
348 
349     if (threadSafeReadDataSrcFunc_ == nullptr) {
350         napi_value resourceName = nullptr;
351         napi_create_string_utf8(env, "ThreadSafeFunction in NapiAVCastControllerCallback",
352             NAPI_AUTO_LENGTH, &resourceName);
353         napi_create_threadsafe_function(env, nullptr, nullptr, resourceName, 0, 1, nullptr, nullptr,
354             nullptr, threadSafeReadDataSrcCb, &threadSafeReadDataSrcFunc_);
355     }
356     return napi_ok;
357 }
358 
threadSafeReadDataSrcCb(napi_env env,napi_value js_cb,void * context,void * data)359 void NapiAVCastControllerCallback::threadSafeReadDataSrcCb(napi_env env, napi_value js_cb, void* context, void* data)
360 {
361     std::shared_ptr<DataContextForThreadSafe> appData(static_cast<DataContextForThreadSafe*>(data),
362         [](DataContextForThreadSafe* ptr) {
363         delete ptr;
364         ptr = nullptr;
365     });
366 
367     napi_status status;
368     napi_value global {};
369     napi_get_global(env, &global);
370 
371     napi_value callback {};
372     napi_get_reference_value(env, appData->callback, &callback);
373 
374     napi_value argv[3] = { nullptr };
375 
376     status = napi_create_external_arraybuffer(env, appData->buffer, appData->length,
377         [](napi_env env, void *data, void *hint) {}, nullptr, &argv[NapiUtils::ARGV_FIRST]);
378     CHECK_RETURN_VOID(status == napi_ok, "get napi_create_external_arraybuffer value failed");
379 
380     status = napi_create_uint32(env, appData->length, &argv[NapiUtils::ARGV_SECOND]);
381     CHECK_RETURN_VOID(status == napi_ok, "get napi_create_uint32 value failed");
382 
383     status = napi_create_int64(env, appData->pos, &argv[NapiUtils::ARGV_THIRD]);
384     CHECK_RETURN_VOID(status == napi_ok, "get napi_create_int64 value failed");
385 
386     napi_value result;
387     status = napi_call_function(env, global, callback, NapiUtils::ARGC_THREE, argv, &result);
388     if (status != napi_ok) {
389         SLOGE("call function failed status=%{public}d.", status);
390     }
391     napi_get_value_int32(env, result, appData->result);
392 
393     appData->dataSrcSyncCond.notify_one();
394     return;
395 }
396 
readDataSrc(napi_env env,std::shared_ptr<AVSharedMemory> mem,uint32_t length,int64_t pos)397 int32_t NapiAVCastControllerCallback::readDataSrc(napi_env env, std::shared_ptr<AVSharedMemory> mem,
398     uint32_t length, int64_t pos)
399 {
400     if (dataSrcRef_ == nullptr) {
401         SLOGE("dataSrcRef_ nullptr");
402         return 0;
403     }
404     int32_t result;
405     DataContextForThreadSafe* data =
406         new DataContextForThreadSafe { dataSrcRef_, mem->GetBase(), length, pos, &result, dataSrcSyncCond_ };
407     napi_status status = napi_call_threadsafe_function(threadSafeReadDataSrcFunc_, data, napi_tsfn_blocking);
408     CHECK_RETURN(status == napi_ok, "get callback value failed", 0);
409 
410     std::unique_lock<std::mutex> lock(dataSrcSyncLock_);
411     auto waitStatus = dataSrcSyncCond_.wait_for(lock, std::chrono::milliseconds(500));
412     if (waitStatus == std::cv_status::timeout) {
413         SLOGE("readDataSrc dataSrcSyncCond_ timeout");
414     }
415     SLOGI("readDataSrc result %{public}d", result);
416     return result;
417 }
418 
AddCallback(napi_env env,int32_t event,napi_value callback)419 napi_status NapiAVCastControllerCallback::AddCallback(napi_env env, int32_t event, napi_value callback)
420 {
421     std::lock_guard<std::mutex> lockGuard(lock_);
422     napi_ref ref = nullptr;
423 
424     CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, callbacks_[event], callback, ref),
425         napi_generic_failure, "get callback reference failed");
426     CHECK_AND_RETURN_RET_LOG(ref == nullptr, napi_ok, "callback has been registered");
427     napi_status status = napi_create_reference(env, callback, NapiUtils::ARGC_ONE, &ref);
428     if (status != napi_ok) {
429         SLOGE("napi_create_reference failed");
430         return status;
431     }
432     if (asyncCallback_ == nullptr) {
433         asyncCallback_ = std::make_shared<NapiAsyncCallback>(env);
434         if (asyncCallback_ == nullptr) {
435             SLOGE("no memory");
436             return napi_generic_failure;
437         }
438     }
439     SLOGI("addCallback isValidSet to prevent off, with ref %{public}d", event);
440     callbacks_[event].push_back(ref);
441     if (isValid_ == nullptr) {
442         SLOGI("addCallback with no isValid_ init");
443         isValid_ = std::make_shared<bool>(true);
444     } else {
445         SLOGI("addCallback with isValid_ set true");
446         *isValid_ = true;
447     }
448     return napi_ok;
449 }
450 
RemoveCallback(napi_env env,int32_t event,napi_value callback)451 napi_status NapiAVCastControllerCallback::RemoveCallback(napi_env env, int32_t event, napi_value callback)
452 {
453     std::lock_guard<std::mutex> lockGuard(lock_);
454     SLOGI("try remove callback for event %{public}d", event);
455     if (callback == nullptr) {
456         SLOGD("Remove callback, the callback is nullptr");
457         for (auto callbackRef = callbacks_[event].begin(); callbackRef != callbacks_[event].end(); ++callbackRef) {
458             napi_status ret = napi_delete_reference(env, *callbackRef);
459             CHECK_AND_RETURN_RET_LOG(ret == napi_ok, ret, "delete callback reference failed");
460             *callbackRef = nullptr;
461         }
462         callbacks_[event].clear();
463         // not remove this logic for play button will not valid when stopcast at media control second page
464         SLOGE("RemoveCallback with isvalid set false when playbackstatechange off");
465         if (event == EVENT_CAST_PLAYBACK_STATE_CHANGE) {
466             if (isValid_ == nullptr) {
467                 SLOGE("remove callback with no isValid_ init");
468                 return napi_ok;
469             }
470             SLOGI("removeCallback with isValid_ set false");
471             *isValid_ = false;
472         }
473         return napi_ok;
474     }
475     napi_ref ref = nullptr;
476     CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, callbacks_[event], callback, ref),
477         napi_generic_failure, "get callback reference failed");
478     SLOGI("remove single callback with ref %{public}d", event);
479     CHECK_AND_RETURN_RET_LOG(ref != nullptr, napi_ok, "callback has been remove");
480     callbacks_[event].remove(ref);
481     return napi_delete_reference(env, ref);
482 }
483 
IsCallbacksEmpty(int32_t event)484 bool NapiAVCastControllerCallback::IsCallbacksEmpty(int32_t event)
485 {
486     return callbacks_[event].empty();
487 }
488 } // namespace OHOS::AVSession
489