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 "js_event_cooperate_target.h"
17 
18 #include "devicestatus_define.h"
19 #include "devicestatus_errors.h"
20 #include "interaction_manager.h"
21 #include "napi_constants.h"
22 #include "util_napi_error.h"
23 
24 #undef LOG_TAG
25 #define LOG_TAG "JsEventCooperateTarget"
26 
27 namespace OHOS {
28 namespace Msdp {
29 namespace DeviceStatus {
30 namespace {
31 inline constexpr std::string_view COORDINATION { "cooperation" };
32 inline constexpr std::string_view CREATE_PROMISE { "napi_create_promise" };
33 inline constexpr std::string_view GET_UNDEFINED { "napi_get_undefined" };
34 inline constexpr std::string_view RESOLVE_DEFERRED { "napi_resolve_deferred" };
35 inline constexpr std::string_view REJECT_DEFERRED { "napi_reject_deferred" };
36 inline constexpr std::string_view CLOSE_SCOPE { "napi_close_handle_scope" };
37 std::mutex mutex_;
38 } // namespace
39 
JsEventCooperateTarget()40 JsEventCooperateTarget::JsEventCooperateTarget()
41 {
42     CALL_DEBUG_ENTER;
43     auto ret = coordinationListeners_.insert({ COORDINATION,
44         std::vector<sptr<JsUtilCooperate::CallbackInfo>>()});
45     if (!ret.second) {
46         FI_HILOGW("Failed to add listener, errCode:%{public}d", static_cast<int32_t>(DeviceStatus::VAL_NOT_EXP));
47     }
48 }
49 
EmitJsEnable(sptr<JsUtilCooperate::CallbackInfo> cb,const std::string & networkId,const CoordinationMsgInfo & msgInfo)50 void JsEventCooperateTarget::EmitJsEnable(sptr<JsUtilCooperate::CallbackInfo> cb,
51     const std::string &networkId, const CoordinationMsgInfo &msgInfo)
52 {
53     CALL_INFO_TRACE;
54     CHKPV(cb);
55     CHKPV(cb->env);
56     cb->data.enableResult = (msgInfo.msg == CoordinationMessage::PREPARE ||
57         msgInfo.msg == CoordinationMessage::UNPREPARE);
58     cb->data.msgInfo = msgInfo;
59     uv_loop_s *loop = nullptr;
60     CHKRV(napi_get_uv_event_loop(cb->env, &loop), GET_UV_EVENT_LOOP);
61     uv_work_s *work = new (std::nothrow) uv_work_t;
62     CHKPV(work);
63     cb->IncStrongRef(nullptr);
64     work->data = cb.GetRefPtr();
65     int32_t ret = 0;
66     if (cb->ref == nullptr) {
67         ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, CallEnablePromiseWork, uv_qos_default);
68     } else {
69         ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, CallEnableAsyncWork, uv_qos_default);
70     }
71 
72     if (ret != 0) {
73         FI_HILOGE("Failed to execute uv_queue_work_with_qos");
74         JsUtilCooperate::DeletePtr<uv_work_t*>(work);
75         cb->DecStrongRef(nullptr);
76     }
77 }
78 
EmitJsStart(sptr<JsUtilCooperate::CallbackInfo> cb,const std::string & remoteNetworkId,const CoordinationMsgInfo & msgInfo)79 void JsEventCooperateTarget::EmitJsStart(sptr<JsUtilCooperate::CallbackInfo> cb,
80     const std::string &remoteNetworkId, const CoordinationMsgInfo &msgInfo)
81 {
82     CALL_INFO_TRACE;
83     CHKPV(cb);
84     CHKPV(cb->env);
85     cb->data.startResult = (msgInfo.msg == CoordinationMessage::ACTIVATE_SUCCESS);
86     cb->data.msgInfo = msgInfo;
87     uv_loop_s *loop = nullptr;
88     CHKRV(napi_get_uv_event_loop(cb->env, &loop), GET_UV_EVENT_LOOP);
89     uv_work_s *work = new (std::nothrow) uv_work_t;
90     CHKPV(work);
91     cb->IncStrongRef(nullptr);
92     work->data = cb.GetRefPtr();
93     int32_t ret = 0;
94     if (cb->ref == nullptr) {
95         ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, CallStartPromiseWork, uv_qos_default);
96     } else {
97         ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, CallStartAsyncWork, uv_qos_default);
98     }
99 
100     if (ret != 0) {
101         FI_HILOGE("Failed to execute uv_queue_work_with_qos");
102         JsUtilCooperate::DeletePtr<uv_work_t*>(work);
103         cb->DecStrongRef(nullptr);
104     }
105 }
106 
EmitJsStop(sptr<JsUtilCooperate::CallbackInfo> cb,const std::string & networkId,const CoordinationMsgInfo & msgInfo)107 void JsEventCooperateTarget::EmitJsStop(sptr<JsUtilCooperate::CallbackInfo> cb,
108     const std::string &networkId, const CoordinationMsgInfo &msgInfo)
109 {
110     CALL_INFO_TRACE;
111     CHKPV(cb);
112     CHKPV(cb->env);
113     cb->data.stopResult = (msgInfo.msg == CoordinationMessage::DEACTIVATE_SUCCESS);
114     cb->data.msgInfo = msgInfo;
115     uv_loop_s *loop = nullptr;
116     CHKRV(napi_get_uv_event_loop(cb->env, &loop), GET_UV_EVENT_LOOP);
117     uv_work_s *work = new (std::nothrow) uv_work_t;
118     CHKPV(work);
119     cb->IncStrongRef(nullptr);
120     work->data = cb.GetRefPtr();
121     int32_t ret = 0;
122     if (cb->ref == nullptr) {
123         ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, CallStopPromiseWork, uv_qos_default);
124     } else {
125         ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, CallStopAsyncWork, uv_qos_default);
126     }
127 
128     if (ret != 0) {
129         FI_HILOGE("Failed to execute uv_queue_work_with_qos");
130         JsUtilCooperate::DeletePtr<uv_work_t*>(work);
131         cb->DecStrongRef(nullptr);
132     }
133 }
134 
EmitJsGetState(sptr<JsUtilCooperate::CallbackInfo> cb,bool state)135 void JsEventCooperateTarget::EmitJsGetState(sptr<JsUtilCooperate::CallbackInfo> cb, bool state)
136 {
137     CALL_INFO_TRACE;
138     CHKPV(cb);
139     CHKPV(cb->env);
140     cb->data.coordinationOpened = state;
141     uv_loop_s *loop = nullptr;
142     CHKRV(napi_get_uv_event_loop(cb->env, &loop), GET_UV_EVENT_LOOP);
143     uv_work_s *work = new (std::nothrow) uv_work_t;
144     CHKPV(work);
145     cb->IncStrongRef(nullptr);
146     work->data = cb.GetRefPtr();
147     int32_t ret = 0;
148     if (cb->ref == nullptr) {
149         ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, CallGetStatePromiseWork, uv_qos_default);
150     } else {
151         ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, CallGetStateAsyncWork, uv_qos_default);
152     }
153 
154     if (ret != 0) {
155         FI_HILOGE("Failed to execute uv_queue_work_with_qos");
156         JsUtilCooperate::DeletePtr<uv_work_t*>(work);
157         cb->DecStrongRef(nullptr);
158     }
159 }
160 
AddListener(napi_env env,const std::string & type,napi_value handle)161 void JsEventCooperateTarget::AddListener(napi_env env, const std::string &type, napi_value handle)
162 {
163     CALL_INFO_TRACE;
164     std::lock_guard<std::mutex> guard(mutex_);
165     auto iter = coordinationListeners_.find(type);
166     if (iter == coordinationListeners_.end()) {
167         FI_HILOGE("Failed to add listener, type:%{public}s", type.c_str());
168         return;
169     }
170 
171     for (const auto &item : iter->second) {
172         CHKPC(item);
173         if (JsUtilCooperate::IsSameHandle(env, handle, item->ref)) {
174             FI_HILOGE("The handle already exists");
175             return;
176         }
177     }
178     napi_ref ref = nullptr;
179     CHKRV(napi_create_reference(env, handle, 1, &ref), CREATE_REFERENCE);
180     sptr<JsUtilCooperate::CallbackInfo> monitor = new (std::nothrow) JsUtilCooperate::CallbackInfo();
181     CHKPV(monitor);
182     monitor->env = env;
183     monitor->ref = ref;
184     iter->second.push_back(std::move(monitor));
185     if (!isListeningProcess_) {
186         isListeningProcess_ = true;
187         INTERACTION_MGR->RegisterCoordinationListener(shared_from_this());
188     }
189 }
190 
RemoveListener(napi_env env,const std::string & type,napi_value handle)191 void JsEventCooperateTarget::RemoveListener(napi_env env, const std::string &type, napi_value handle)
192 {
193     CALL_INFO_TRACE;
194     std::lock_guard<std::mutex> guard(mutex_);
195     auto iter = coordinationListeners_.find(type);
196     if (iter == coordinationListeners_.end()) {
197         FI_HILOGE("Failed to remove listener, type:%{public}s", type.c_str());
198         return;
199     }
200     if (handle == nullptr) {
201         iter->second.clear();
202         goto monitorTag;
203     }
204     for (auto it = iter->second.begin(); it != iter->second.end(); ++it) {
205         if (JsUtilCooperate::IsSameHandle(env, handle, (*it)->ref)) {
206             FI_HILOGE("Successfully removed the listener");
207             iter->second.erase(it);
208             goto monitorTag;
209         }
210     }
211 
212 monitorTag:
213     if (isListeningProcess_ && iter->second.empty()) {
214         isListeningProcess_ = false;
215         INTERACTION_MGR->UnregisterCoordinationListener(shared_from_this());
216     }
217 }
218 
CreateCallbackInfo(napi_env env,napi_value handle,sptr<JsUtilCooperate::CallbackInfo> callback)219 napi_value JsEventCooperateTarget::CreateCallbackInfo(napi_env env,
220     napi_value handle, sptr<JsUtilCooperate::CallbackInfo> callback)
221 {
222     CALL_INFO_TRACE;
223     CHKPP(callback);
224     callback->env = env;
225     napi_value promise = nullptr;
226     if (handle == nullptr) {
227         CHKRP(napi_create_promise(env, &callback->deferred, &promise), CREATE_PROMISE);
228     } else {
229         CHKRP(napi_create_reference(env, handle, 1, &callback->ref), CREATE_REFERENCE);
230     }
231     return promise;
232 }
233 
ResetEnv()234 void JsEventCooperateTarget::ResetEnv()
235 {
236     CALL_INFO_TRACE;
237     std::lock_guard<std::mutex> guard(mutex_);
238     INTERACTION_MGR->UnregisterCoordinationListener(shared_from_this());
239 }
240 
OnCoordinationMessage(const std::string & networkId,CoordinationMessage msg)241 void JsEventCooperateTarget::OnCoordinationMessage(const std::string &networkId, CoordinationMessage msg)
242 {
243     CALL_INFO_TRACE;
244     std::lock_guard<std::mutex> guard(mutex_);
245     auto changeEvent = coordinationListeners_.find(COORDINATION);
246     if (changeEvent == coordinationListeners_.end()) {
247         FI_HILOGE("Failed to find the %{public}s", std::string(COORDINATION).c_str());
248         return;
249     }
250 
251     for (auto &item : changeEvent->second) {
252         CHKPC(item);
253         CHKPC(item->env);
254         uv_loop_s *loop = nullptr;
255         CHKRV(napi_get_uv_event_loop(item->env, &loop), GET_UV_EVENT_LOOP);
256         uv_work_t *uvWork = new (std::nothrow) uv_work_t;
257         CHKPV(uvWork);
258         item->data.msgInfo.msg = msg;
259         item->data.deviceDescriptor = networkId;
260         item->IncStrongRef(nullptr);
261         uvWork->data = item.GetRefPtr();
262         int32_t ret = uv_queue_work_with_qos(loop, uvWork, [](uv_work_t *uvWork) {},
263             EmitCoordinationMessageEvent, uv_qos_default);
264         if (ret != 0) {
265             FI_HILOGE("Failed to execute uv_queue_work_with_qos");
266             item->DecStrongRef(nullptr);
267             JsUtilCooperate::DeletePtr<uv_work_t*>(uvWork);
268         }
269     }
270 }
271 
CallEnablePromiseWork(uv_work_t * work,int32_t status)272 void JsEventCooperateTarget::CallEnablePromiseWork(uv_work_t *work, int32_t status)
273 {
274     CALL_INFO_TRACE;
275     CHKPV(work);
276     if (work->data == nullptr) {
277         JsUtilCooperate::DeletePtr<uv_work_t*>(work);
278         FI_HILOGE("Enable promise, check data is nullptr");
279         return;
280     }
281     sptr<JsUtilCooperate::CallbackInfo> cb(static_cast<JsUtilCooperate::CallbackInfo *>(work->data));
282     JsUtilCooperate::DeletePtr<uv_work_t*>(work);
283     cb->DecStrongRef(nullptr);
284     CHKPV(cb->env);
285     napi_handle_scope scope = nullptr;
286     napi_open_handle_scope(cb->env, &scope);
287     if (scope == nullptr) {
288         FI_HILOGE("Enable promise, scope is nullptr");
289         RELEASE_CALLBACKINFO(cb->env, cb->ref);
290         return;
291     }
292     napi_value object = JsUtilCooperate::GetEnableInfo(cb);
293     if (object == nullptr) {
294         FI_HILOGE("Enable promise, object is nullptr");
295         RELEASE_CALLBACKINFO(cb->env, cb->ref);
296         napi_close_handle_scope(cb->env, scope);
297         return;
298     }
299     napi_valuetype valueType = napi_undefined;
300     if (napi_typeof(cb->env, object, &valueType) != napi_ok) {
301         FI_HILOGE("Enable promise, napi typeof failed");
302         RELEASE_CALLBACKINFO(cb->env, cb->ref);
303         napi_close_handle_scope(cb->env, scope);
304         return;
305     }
306     if (valueType != napi_undefined) {
307         CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, object), REJECT_DEFERRED, scope);
308     } else {
309         CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, object), RESOLVE_DEFERRED, scope);
310     }
311     RELEASE_CALLBACKINFO(cb->env, cb->ref);
312     napi_close_handle_scope(cb->env, scope);
313 }
314 
CallEnableAsyncWork(uv_work_t * work,int32_t status)315 void JsEventCooperateTarget::CallEnableAsyncWork(uv_work_t *work, int32_t status)
316 {
317     CALL_INFO_TRACE;
318     CHKPV(work);
319     if (work->data == nullptr) {
320         JsUtilCooperate::DeletePtr<uv_work_t*>(work);
321         FI_HILOGE("Enable async, check data is nullptr");
322         return;
323     }
324     sptr<JsUtilCooperate::CallbackInfo> cb(static_cast<JsUtilCooperate::CallbackInfo *>(work->data));
325     JsUtilCooperate::DeletePtr<uv_work_t*>(work);
326     cb->DecStrongRef(nullptr);
327     CHKPV(cb->env);
328     napi_handle_scope scope = nullptr;
329     napi_open_handle_scope(cb->env, &scope);
330     if (scope == nullptr) {
331         FI_HILOGE("Enable async, scope is nullptr");
332         RELEASE_CALLBACKINFO(cb->env, cb->ref);
333         return;
334     }
335     napi_value object = JsUtilCooperate::GetEnableInfo(cb);
336     if (object == nullptr) {
337         FI_HILOGE("Enable async, object is nullptr");
338         RELEASE_CALLBACKINFO(cb->env, cb->ref);
339         napi_close_handle_scope(cb->env, scope);
340         return;
341     }
342     napi_value processor = nullptr;
343     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &processor), GET_REFERENCE_VALUE, scope);
344     napi_value ret = nullptr;
345     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, processor, 1, &object, &ret), CALL_FUNCTION, scope);
346     RELEASE_CALLBACKINFO(cb->env, cb->ref);
347     napi_close_handle_scope(cb->env, scope);
348 }
349 
CallStartPromiseWork(uv_work_t * work,int32_t status)350 void JsEventCooperateTarget::CallStartPromiseWork(uv_work_t *work, int32_t status)
351 {
352     CALL_INFO_TRACE;
353     CHKPV(work);
354     if (work->data == nullptr) {
355         JsUtilCooperate::DeletePtr<uv_work_t*>(work);
356         FI_HILOGE("Start promise, check data is nullptr");
357         return;
358     }
359     sptr<JsUtilCooperate::CallbackInfo> cb(static_cast<JsUtilCooperate::CallbackInfo *>(work->data));
360     JsUtilCooperate::DeletePtr<uv_work_t*>(work);
361     cb->DecStrongRef(nullptr);
362     CHKPV(cb->env);
363     napi_handle_scope scope = nullptr;
364     napi_open_handle_scope(cb->env, &scope);
365     if (scope == nullptr) {
366         FI_HILOGE("Start promise, scope is nullptr");
367         RELEASE_CALLBACKINFO(cb->env, cb->ref);
368         return;
369     }
370     napi_value object = JsUtilCooperate::GetStartInfo(cb);
371     if (object == nullptr) {
372         FI_HILOGE("Start promise, object is nullptr");
373         RELEASE_CALLBACKINFO(cb->env, cb->ref);
374         napi_close_handle_scope(cb->env, scope);
375         return;
376     }
377     napi_valuetype napiValueType = napi_undefined;
378     if (napi_typeof(cb->env, object, &napiValueType) != napi_ok) {
379         FI_HILOGE("Start promise, napi typeof failed");
380         RELEASE_CALLBACKINFO(cb->env, cb->ref);
381         napi_close_handle_scope(cb->env, scope);
382         return;
383     }
384     if (napiValueType != napi_undefined) {
385         CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, object), REJECT_DEFERRED, scope);
386     } else {
387         CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, object), RESOLVE_DEFERRED, scope);
388     }
389     RELEASE_CALLBACKINFO(cb->env, cb->ref);
390     napi_close_handle_scope(cb->env, scope);
391 }
392 
CallStartAsyncWork(uv_work_t * work,int32_t status)393 void JsEventCooperateTarget::CallStartAsyncWork(uv_work_t *work, int32_t status)
394 {
395     CALL_INFO_TRACE;
396     CHKPV(work);
397     if (work->data == nullptr) {
398         JsUtilCooperate::DeletePtr<uv_work_t*>(work);
399         FI_HILOGE("Start async, check data is nullptr");
400         return;
401     }
402     sptr<JsUtilCooperate::CallbackInfo> cb(static_cast<JsUtilCooperate::CallbackInfo *>(work->data));
403     JsUtilCooperate::DeletePtr<uv_work_t*>(work);
404     cb->DecStrongRef(nullptr);
405     CHKPV(cb->env);
406     napi_handle_scope scope = nullptr;
407     napi_open_handle_scope(cb->env, &scope);
408     if (scope == nullptr) {
409         FI_HILOGE("Start async, scope is nullptr");
410         RELEASE_CALLBACKINFO(cb->env, cb->ref);
411         return;
412     }
413     napi_value object = JsUtilCooperate::GetStartInfo(cb);
414     if (object == nullptr) {
415         FI_HILOGE("Start async, object is nullptr");
416         RELEASE_CALLBACKINFO(cb->env, cb->ref);
417         napi_close_handle_scope(cb->env, scope);
418         return;
419     }
420     napi_value napiHandler = nullptr;
421     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &napiHandler), GET_REFERENCE_VALUE, scope);
422     napi_value ret = nullptr;
423     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, napiHandler, 1, &object, &ret), CALL_FUNCTION, scope);
424     RELEASE_CALLBACKINFO(cb->env, cb->ref);
425     napi_close_handle_scope(cb->env, scope);
426 }
427 
CallStopPromiseWork(uv_work_t * work,int32_t status)428 void JsEventCooperateTarget::CallStopPromiseWork(uv_work_t *work, int32_t status)
429 {
430     CALL_INFO_TRACE;
431     CHKPV(work);
432     if (work->data == nullptr) {
433         JsUtilCooperate::DeletePtr<uv_work_t*>(work);
434         FI_HILOGE("Stop promise, check data is nullptr");
435         return;
436     }
437     sptr<JsUtilCooperate::CallbackInfo> cb(static_cast<JsUtilCooperate::CallbackInfo *>(work->data));
438     JsUtilCooperate::DeletePtr<uv_work_t*>(work);
439     cb->DecStrongRef(nullptr);
440     CHKPV(cb->env);
441     napi_handle_scope napiHandleScope = nullptr;
442     napi_open_handle_scope(cb->env, &napiHandleScope);
443     if (napiHandleScope == nullptr) {
444         FI_HILOGE("Stop promise, napiHandleScope is nullptr");
445         RELEASE_CALLBACKINFO(cb->env, cb->ref);
446         return;
447     }
448     napi_value object = JsUtilCooperate::GetStopInfo(cb);
449     if (object == nullptr) {
450         FI_HILOGE("Stop promise, object is nullptr");
451         RELEASE_CALLBACKINFO(cb->env, cb->ref);
452         napi_close_handle_scope(cb->env, napiHandleScope);
453         return;
454     }
455 
456     napi_valuetype valueType = napi_undefined;
457     if (napi_typeof(cb->env, object, &valueType) != napi_ok) {
458         FI_HILOGE("Stop promise, napi typeof failed");
459         RELEASE_CALLBACKINFO(cb->env, cb->ref);
460         napi_close_handle_scope(cb->env, napiHandleScope);
461         return;
462     }
463     if (valueType != napi_undefined) {
464         CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, object), REJECT_DEFERRED, napiHandleScope);
465     } else {
466         CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, object), RESOLVE_DEFERRED, napiHandleScope);
467     }
468     RELEASE_CALLBACKINFO(cb->env, cb->ref);
469     napi_close_handle_scope(cb->env, napiHandleScope);
470 }
471 
CallStopAsyncWork(uv_work_t * work,int32_t status)472 void JsEventCooperateTarget::CallStopAsyncWork(uv_work_t *work, int32_t status)
473 {
474     CALL_INFO_TRACE;
475     CHKPV(work);
476     if (work->data == nullptr) {
477         JsUtilCooperate::DeletePtr<uv_work_t*>(work);
478         FI_HILOGE("Stop async, check data is nullptr");
479         return;
480     }
481     sptr<JsUtilCooperate::CallbackInfo> cb(static_cast<JsUtilCooperate::CallbackInfo *>(work->data));
482     JsUtilCooperate::DeletePtr<uv_work_t*>(work);
483     cb->DecStrongRef(nullptr);
484     CHKPV(cb->env);
485     napi_handle_scope scope = nullptr;
486     napi_open_handle_scope(cb->env, &scope);
487     if (scope == nullptr) {
488         FI_HILOGE("Stop async, scope is nullptr");
489         RELEASE_CALLBACKINFO(cb->env, cb->ref);
490         return;
491     }
492     napi_value object = JsUtilCooperate::GetStopInfo(cb);
493     if (object == nullptr) {
494         FI_HILOGE("Stop async, object is nullptr");
495         RELEASE_CALLBACKINFO(cb->env, cb->ref);
496         napi_close_handle_scope(cb->env, scope);
497         return;
498     }
499     napi_value napiHandler = nullptr;
500     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &napiHandler), GET_REFERENCE_VALUE, scope);
501     napi_value result = nullptr;
502     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, napiHandler, 1, &object, &result), CALL_FUNCTION, scope);
503     RELEASE_CALLBACKINFO(cb->env, cb->ref);
504     napi_close_handle_scope(cb->env, scope);
505 }
506 
CallGetStatePromiseWork(uv_work_t * work,int32_t status)507 void JsEventCooperateTarget::CallGetStatePromiseWork(uv_work_t *work, int32_t status)
508 {
509     CALL_INFO_TRACE;
510     CHKPV(work);
511     if (work->data == nullptr) {
512         JsUtilCooperate::DeletePtr<uv_work_t*>(work);
513         FI_HILOGE("Get start promise, check data is nullptr");
514         return;
515     }
516     sptr<JsUtilCooperate::CallbackInfo> cb(static_cast<JsUtilCooperate::CallbackInfo *>(work->data));
517     JsUtilCooperate::DeletePtr<uv_work_t*>(work);
518     cb->DecStrongRef(nullptr);
519     CHKPV(cb->env);
520     napi_handle_scope scope = nullptr;
521     napi_open_handle_scope(cb->env, &scope);
522     if (scope == nullptr) {
523         FI_HILOGE("Get start promise, scope is nullptr");
524         RELEASE_CALLBACKINFO(cb->env, cb->ref);
525         return;
526     }
527     napi_value object = JsUtilCooperate::GetStateInfo(cb);
528     if (object == nullptr) {
529         FI_HILOGE("Get start promise, object is nullptr");
530         RELEASE_CALLBACKINFO(cb->env, cb->ref);
531         napi_close_handle_scope(cb->env, scope);
532         return;
533     }
534     CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, object), RESOLVE_DEFERRED, scope);
535     RELEASE_CALLBACKINFO(cb->env, cb->ref);
536     napi_close_handle_scope(cb->env, scope);
537 }
538 
CallGetStateAsyncWork(uv_work_t * work,int32_t status)539 void JsEventCooperateTarget::CallGetStateAsyncWork(uv_work_t *work, int32_t status)
540 {
541     CALL_INFO_TRACE;
542     CHKPV(work);
543     if (work->data == nullptr) {
544         JsUtilCooperate::DeletePtr<uv_work_t*>(work);
545         FI_HILOGE("Get start async, check data is nullptr");
546         return;
547     }
548     sptr<JsUtilCooperate::CallbackInfo> cb(static_cast<JsUtilCooperate::CallbackInfo *>(work->data));
549     JsUtilCooperate::DeletePtr<uv_work_t*>(work);
550     cb->DecStrongRef(nullptr);
551     CHKPV(cb->env);
552     napi_handle_scope scope = nullptr;
553     napi_open_handle_scope(cb->env, &scope);
554     if (scope == nullptr) {
555         FI_HILOGE("Get start async, scope is nullptr");
556         RELEASE_CALLBACKINFO(cb->env, cb->ref);
557         return;
558     }
559     napi_value resultObj[2];
560     CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &resultObj[0]), GET_UNDEFINED, scope);
561     resultObj[1] = JsUtilCooperate::GetStateInfo(cb);
562     if (resultObj[1] == nullptr) {
563         FI_HILOGE("Get start async, object is nullptr");
564         napi_close_handle_scope(cb->env, scope);
565         return;
566     }
567     napi_value handlerInfo = nullptr;
568     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handlerInfo), GET_REFERENCE_VALUE, scope);
569     napi_value ret = nullptr;
570     size_t argc = TWO_PARAM;
571     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handlerInfo, argc, resultObj, &ret),
572         CALL_FUNCTION, scope);
573     RELEASE_CALLBACKINFO(cb->env, cb->ref);
574     napi_close_handle_scope(cb->env, scope);
575 }
576 
EmitCoordinationMessageEvent(uv_work_t * work,int32_t status)577 void JsEventCooperateTarget::EmitCoordinationMessageEvent(uv_work_t *work, int32_t status)
578 {
579     CALL_INFO_TRACE;
580     CHKPV(work);
581     if (work->data == nullptr) {
582         JsUtilCooperate::DeletePtr<uv_work_t*>(work);
583         FI_HILOGE("The data is nullptr");
584         return;
585     }
586     sptr<JsUtilCooperate::CallbackInfo> temp(static_cast<JsUtilCooperate::CallbackInfo*>(work->data));
587     JsUtilCooperate::DeletePtr<uv_work_t*>(work);
588     std::lock_guard<std::mutex> guard(mutex_);
589     temp->DecStrongRef(nullptr);
590     auto msgEvent = coordinationListeners_.find(COORDINATION);
591     if (msgEvent == coordinationListeners_.end()) {
592         FI_HILOGE("Failed to find the msgEvent");
593         return;
594     }
595     for (const auto &item : msgEvent->second) {
596         CHKPC(item->env);
597         if (item->ref != temp->ref) {
598             continue;
599         }
600         napi_handle_scope scope = nullptr;
601         napi_open_handle_scope(item->env, &scope);
602         napi_value deviceDescriptor = nullptr;
603         CHKRV_SCOPE(item->env, napi_create_string_utf8(item->env, item->data.deviceDescriptor.c_str(),
604             NAPI_AUTO_LENGTH, &deviceDescriptor), CREATE_STRING_UTF8, scope);
605         napi_value eventMsg = nullptr;
606         auto iter = messageTransform.find(item->data.msgInfo.msg);
607         if (iter == messageTransform.end()) {
608             FI_HILOGE("Failed to find the message code");
609             CHKRV(napi_close_handle_scope(item->env, scope), CLOSE_SCOPE);
610             return;
611         }
612         CHKRV_SCOPE(item->env, napi_create_int32(item->env, static_cast<int32_t>(iter->second), &eventMsg),
613             CREATE_INT32, scope);
614         napi_value object = nullptr;
615         CHKRV_SCOPE(item->env, napi_create_object(item->env, &object), CREATE_OBJECT, scope);
616         CHKRV_SCOPE(item->env, napi_set_named_property(item->env, object, "deviceDescriptor", deviceDescriptor),
617             SET_NAMED_PROPERTY, scope);
618         CHKRV_SCOPE(item->env, napi_set_named_property(item->env, object, "eventMsg", eventMsg),
619             SET_NAMED_PROPERTY, scope);
620         napi_value handler = nullptr;
621         CHKRV_SCOPE(item->env, napi_get_reference_value(item->env, item->ref, &handler), GET_REFERENCE_VALUE, scope);
622         napi_value ret = nullptr;
623         CHKRV_SCOPE(item->env, napi_call_function(item->env, nullptr, handler, 1, &object, &ret), CALL_FUNCTION, scope);
624         napi_close_handle_scope(item->env, scope);
625     }
626 }
627 } // namespace DeviceStatus
628 } // namespace Msdp
629 } // namespace OHOS
630