1 /*
2  * Copyright (c) 2021-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_target.h"
17 #include "js_util.h"
18 #include "napi_constants.h"
19 #include "util_napi_error.h"
20 #include "bytrace_adapter.h"
21 
22 #undef MMI_LOG_TAG
23 #define MMI_LOG_TAG "JsEventTarget"
24 
25 namespace OHOS {
26 namespace MMI {
27 namespace {
28 constexpr int32_t INPUT_PARAMETER_MIDDLE { 2 };
29 
30 std::mutex mutex_;
31 const std::string ADD_EVENT = "add";
32 const std::string REMOVE_EVENT = "remove";
33 
34 struct DeviceItem {
35     int32_t deviceId;
36     void *item;
37 };
38 
39 } // namespace
40 
JsEventTarget()41 JsEventTarget::JsEventTarget()
42 {
43     CALL_DEBUG_ENTER;
44     std::lock_guard<std::mutex> lock(mutex_);
45     auto ret = devListener_.insert({ CHANGED_TYPE, std::vector<std::unique_ptr<JsUtil::CallbackInfo>>() });
46     CK(ret.second, VAL_NOT_EXP);
47 }
48 
EmitAddedDeviceEvent(sptr<JsUtil::ReportData> reportData)49 void JsEventTarget::EmitAddedDeviceEvent(sptr<JsUtil::ReportData> reportData)
50 {
51     CALL_DEBUG_ENTER;
52     std::lock_guard<std::mutex> guard(mutex_);
53     reportData->DecStrongRef(nullptr);
54     auto addEvent = devListener_.find(CHANGED_TYPE);
55     if (addEvent == devListener_.end()) {
56         MMI_HILOGE("Find change event failed");
57         return;
58     }
59     for (const auto &item : addEvent->second) {
60         CHKPC(item->env);
61         if (item->ref != reportData->ref) {
62             continue;
63         }
64         napi_handle_scope scope = nullptr;
65         napi_open_handle_scope(item->env, &scope);
66         CHKPV(scope);
67         napi_value eventType = nullptr;
68         CHKRV_SCOPE_DEL(item->env, napi_create_string_utf8(item->env, ADD_EVENT.c_str(), NAPI_AUTO_LENGTH, &eventType),
69             CREATE_STRING_UTF8, scope);
70         napi_value object = nullptr;
71         CHKRV_SCOPE_DEL(item->env, napi_create_object(item->env, &object), CREATE_OBJECT, scope);
72         CHKRV_SCOPE_DEL(item->env, napi_set_named_property(item->env, object, "type", eventType), SET_NAMED_PROPERTY,
73             scope);
74         napi_value handler = nullptr;
75         CHKRV_SCOPE_DEL(item->env, napi_get_reference_value(item->env, item->ref, &handler), GET_REFERENCE_VALUE,
76             scope);
77         napi_value deviceId = nullptr;
78         CHKRV_SCOPE_DEL(item->env, napi_create_int32(item->env, reportData->deviceId, &deviceId), CREATE_INT32, scope);
79         CHKRV_SCOPE_DEL(item->env, napi_set_named_property(item->env, object, "deviceId", deviceId), SET_NAMED_PROPERTY,
80             scope);
81         napi_value ret = nullptr;
82         CHKRV_SCOPE_DEL(item->env, napi_call_function(item->env, nullptr, handler, 1, &object, &ret), CALL_FUNCTION,
83             scope);
84         napi_close_handle_scope(item->env, scope);
85         BytraceAdapter::StartDevListener(ADD_EVENT, reportData->deviceId);
86         MMI_HILOGI("Report device change task, event type:%{public}s, eventid:%{public}d",
87             ADD_EVENT.c_str(), reportData->deviceId);
88         BytraceAdapter::StopDevListener();
89     }
90 }
91 
EmitRemoveDeviceEvent(sptr<JsUtil::ReportData> reportData)92 void JsEventTarget::EmitRemoveDeviceEvent(sptr<JsUtil::ReportData> reportData)
93 {
94     CALL_DEBUG_ENTER;
95     std::lock_guard<std::mutex> guard(mutex_);
96     reportData->DecStrongRef(nullptr);
97     auto removeEvent = devListener_.find(CHANGED_TYPE);
98     if (removeEvent == devListener_.end()) {
99         MMI_HILOGE("Find change event failed");
100         return;
101     }
102     for (const auto &item : removeEvent->second) {
103         CHKPC(item->env);
104         if (item->ref != reportData->ref) {
105             continue;
106         }
107         napi_handle_scope scope = nullptr;
108         napi_open_handle_scope(item->env, &scope);
109         CHKPV(scope);
110         napi_value eventType = nullptr;
111         CHKRV_SCOPE_DEL(item->env, napi_create_string_utf8(item->env, REMOVE_EVENT.c_str(), NAPI_AUTO_LENGTH,
112             &eventType), CREATE_STRING_UTF8, scope);
113         napi_value deviceId = nullptr;
114         CHKRV_SCOPE_DEL(item->env, napi_create_int32(item->env, reportData->deviceId, &deviceId), CREATE_INT32, scope);
115         napi_value object = nullptr;
116         CHKRV_SCOPE_DEL(item->env, napi_create_object(item->env, &object), CREATE_OBJECT, scope);
117         CHKRV_SCOPE_DEL(item->env, napi_set_named_property(item->env, object, "type", eventType), SET_NAMED_PROPERTY,
118             scope);
119         CHKRV_SCOPE_DEL(item->env, napi_set_named_property(item->env, object, "deviceId", deviceId), SET_NAMED_PROPERTY,
120             scope);
121         napi_value handler = nullptr;
122         CHKRV_SCOPE_DEL(item->env, napi_get_reference_value(item->env, item->ref, &handler), GET_REFERENCE_VALUE,
123             scope);
124         napi_value ret = nullptr;
125         CHKRV_SCOPE_DEL(item->env, napi_call_function(item->env, nullptr, handler, 1, &object, &ret), CALL_FUNCTION,
126             scope);
127         napi_close_handle_scope(item->env, scope);
128         BytraceAdapter::StartDevListener(REMOVE_EVENT, reportData->deviceId);
129         MMI_HILOGI("Report device change task, event type:%{public}s, eventid:%{public}d",
130             REMOVE_EVENT.c_str(), reportData->deviceId);
131         BytraceAdapter::StopDevListener();
132     }
133 }
134 
OnDeviceAdded(int32_t deviceId,const std::string & type)135 void JsEventTarget::OnDeviceAdded(int32_t deviceId, const std::string &type)
136 {
137     CALL_DEBUG_ENTER;
138     std::lock_guard<std::mutex> guard(mutex_);
139     auto changeEvent = devListener_.find(CHANGED_TYPE);
140     if (changeEvent == devListener_.end()) {
141         MMI_HILOGE("Find %{public}s failed", CHANGED_TYPE.c_str());
142         return;
143     }
144 
145     for (auto &item : changeEvent->second) {
146         CHKPC(item);
147         CHKPC(item->env);
148         sptr<JsUtil::ReportData> reportData = new (std::nothrow) JsUtil::ReportData;
149         if (reportData == nullptr) {
150             MMI_HILOGE("Memory allocation failed");
151             return;
152         }
153         reportData->deviceId = deviceId;
154         reportData->ref = item->ref;
155         reportData->IncStrongRef(nullptr);
156         auto task = [reportData, this] () { EmitAddedDeviceEvent(reportData); };
157         int32_t ret = napi_send_event(item->env, task, napi_eprio_vip);
158         if (ret != 0) {
159             MMI_HILOGE("napi_send_event failed");
160             return;
161         }
162     }
163 }
164 
OnDeviceRemoved(int32_t deviceId,const std::string & type)165 void JsEventTarget::OnDeviceRemoved(int32_t deviceId, const std::string &type)
166 {
167     CALL_DEBUG_ENTER;
168     std::lock_guard<std::mutex> guard(mutex_);
169     auto changeEvent = devListener_.find(CHANGED_TYPE);
170     if (changeEvent == devListener_.end()) {
171         MMI_HILOGE("Find %{public}s failed", CHANGED_TYPE.c_str());
172         return;
173     }
174     for (auto &item : changeEvent->second) {
175         CHKPC(item);
176         CHKPC(item->env);
177         sptr<JsUtil::ReportData> reportData = new (std::nothrow) JsUtil::ReportData;
178         if (reportData == nullptr) {
179             MMI_HILOGE("Memory allocation failed");
180             return;
181         }
182         reportData->deviceId = deviceId;
183         reportData->ref = item->ref;
184         reportData->IncStrongRef(nullptr);
185         auto task = [reportData, this] () { EmitRemoveDeviceEvent(reportData); };
186         int32_t ret = napi_send_event(item->env, task, napi_eprio_vip);
187         if (ret != 0) {
188             MMI_HILOGE("napi_send_event failed");
189             return;
190         }
191     }
192 }
193 
CallIdsAsyncWork(uv_work_t * work,int32_t status)194 void JsEventTarget::CallIdsAsyncWork(uv_work_t *work, int32_t status)
195 {
196     CALL_DEBUG_ENTER;
197     CHKPV(work);
198     if (work->data == nullptr) {
199         JsUtil::DeletePtr<uv_work_t *>(work);
200         MMI_HILOGE("Check data is nullptr");
201         return;
202     }
203     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
204     JsUtil::DeletePtr<uv_work_t *>(work);
205     cb->DecStrongRef(nullptr);
206     CHKPV(cb->env);
207     napi_handle_scope scope = nullptr;
208     napi_open_handle_scope(cb->env, &scope);
209     CHKPV(scope);
210     napi_value arr[2];
211     CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &arr[0]), GET_UNDEFINED, scope);
212     CHKRV_SCOPE(cb->env, napi_create_array(cb->env, &arr[1]), CREATE_ARRAY, scope);
213     uint32_t index = 0;
214     napi_value value = nullptr;
215     for (const auto &item : cb->data.ids) {
216         CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, item, &value), CREATE_INT32, scope);
217         CHKRV_SCOPE(cb->env, napi_set_element(cb->env, arr[1], index, value), SET_ELEMENT, scope);
218         ++index;
219     }
220 
221     napi_value handler = nullptr;
222     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE_VALUE, scope);
223     napi_value result = nullptr;
224     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handler, INPUT_PARAMETER_MIDDLE, arr, &result),
225         CALL_FUNCTION, scope);
226     CHKRV_SCOPE(cb->env, napi_delete_reference(cb->env, cb->ref), DELETE_REFERENCE, scope);
227     napi_close_handle_scope(cb->env, scope);
228 }
229 
CallIdsPromiseWork(uv_work_t * work,int32_t status)230 void JsEventTarget::CallIdsPromiseWork(uv_work_t *work, int32_t status)
231 {
232     CALL_DEBUG_ENTER;
233     CHKPV(work);
234     if (work->data == nullptr) {
235         JsUtil::DeletePtr<uv_work_t *>(work);
236         MMI_HILOGE("Check data is nullptr");
237         return;
238     }
239     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
240     JsUtil::DeletePtr<uv_work_t *>(work);
241     cb->DecStrongRef(nullptr);
242     CHKPV(cb->env);
243     napi_handle_scope scope = nullptr;
244     napi_open_handle_scope(cb->env, &scope);
245     CHKPV(scope);
246     napi_value arr = nullptr;
247     CHKRV_SCOPE(cb->env, napi_create_array(cb->env, &arr), CREATE_ARRAY, scope);
248     uint32_t index = 0;
249     napi_value value = nullptr;
250     for (const auto &item : cb->data.ids) {
251         CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, item, &value), CREATE_INT32, scope);
252         CHKRV_SCOPE(cb->env, napi_set_element(cb->env, arr, index, value), SET_ELEMENT, scope);
253         ++index;
254     }
255     CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, arr), RESOLVE_DEFERRED, scope);
256     napi_close_handle_scope(cb->env, scope);
257 }
258 
EmitJsIds(sptr<JsUtil::CallbackInfo> cb,std::vector<int32_t> & ids)259 void JsEventTarget::EmitJsIds(sptr<JsUtil::CallbackInfo> cb, std::vector<int32_t> &ids)
260 {
261     CALL_DEBUG_ENTER;
262     CHKPV(cb);
263     CHKPV(cb->env);
264     cb->data.ids = ids;
265     cb->errCode = RET_OK;
266     uv_loop_s *loop = nullptr;
267     CHKRV(napi_get_uv_event_loop(cb->env, &loop), GET_UV_EVENT_LOOP);
268     uv_work_t *work = new (std::nothrow) uv_work_t;
269     CHKPV(work);
270     cb->IncStrongRef(nullptr);
271     work->data = cb.GetRefPtr();
272     int32_t ret = -1;
273     if (cb->isApi9) {
274         if (cb->ref == nullptr) {
275             ret = uv_queue_work_with_qos(
276                 loop, work,
277                 [](uv_work_t *work) {
278                     MMI_HILOGD("uv_queue_work callback function is called");
279                 }, CallDevListPromiseWork, uv_qos_user_initiated);
280         } else {
281             ret = uv_queue_work_with_qos(
282                 loop, work,
283                 [](uv_work_t *work) {
284                     MMI_HILOGD("uv_queue_work callback function is called");
285                 }, CallDevListAsyncWork, uv_qos_user_initiated);
286         }
287     } else {
288         if (cb->ref == nullptr) {
289             ret = uv_queue_work_with_qos(
290                 loop, work,
291                 [](uv_work_t *work) {
292                     MMI_HILOGD("uv_queue_work callback function is called");
293                 }, CallIdsPromiseWork, uv_qos_user_initiated);
294         } else {
295             ret = uv_queue_work_with_qos(
296                 loop, work,
297                 [](uv_work_t *work) {
298                     MMI_HILOGD("uv_queue_work callback function is called");
299                 }, CallIdsAsyncWork, uv_qos_user_initiated);
300         }
301     }
302     if (ret != 0) {
303         MMI_HILOGE("uv_queue_work_with_qos failed");
304         JsUtil::DeletePtr<uv_work_t *>(work);
305     }
306 }
307 
CallDevAsyncWork(uv_work_t * work,int32_t status)308 void JsEventTarget::CallDevAsyncWork(uv_work_t *work, int32_t status)
309 {
310     CALL_DEBUG_ENTER;
311     CHKPV(work);
312     if (work->data == nullptr) {
313         JsUtil::DeletePtr<uv_work_t *>(work);
314         MMI_HILOGE("Check data is nullptr");
315         return;
316     }
317     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
318     JsUtil::DeletePtr<uv_work_t *>(work);
319     cb->DecStrongRef(nullptr);
320     CHKPV(cb->env);
321     napi_handle_scope scope = nullptr;
322     napi_open_handle_scope(cb->env, &scope);
323     CHKPV(scope);
324     napi_value object[2];
325     CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &object[0]), GET_UNDEFINED, scope);
326     object[1] = JsUtil::GetDeviceInfo(cb);
327     napi_value handler = nullptr;
328     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE_VALUE, scope);
329     napi_value result = nullptr;
330     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handler, INPUT_PARAMETER_MIDDLE, object, &result),
331         CALL_FUNCTION, scope);
332     CHKRV_SCOPE(cb->env, napi_delete_reference(cb->env, cb->ref), DELETE_REFERENCE, scope);
333     napi_close_handle_scope(cb->env, scope);
334 }
335 
CallDevPromiseWork(uv_work_t * work,int32_t status)336 void JsEventTarget::CallDevPromiseWork(uv_work_t *work, int32_t status)
337 {
338     CALL_DEBUG_ENTER;
339     CHKPV(work);
340     if (work->data == nullptr) {
341         JsUtil::DeletePtr<uv_work_t *>(work);
342         MMI_HILOGE("Check data is nullptr");
343         return;
344     }
345     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
346     JsUtil::DeletePtr<uv_work_t *>(work);
347     cb->DecStrongRef(nullptr);
348     CHKPV(cb->env);
349     napi_handle_scope scope = nullptr;
350     napi_open_handle_scope(cb->env, &scope);
351     CHKPV(scope);
352     napi_value object = JsUtil::GetDeviceInfo(cb);
353     if (object == nullptr) {
354         MMI_HILOGE("Check object is nullptr");
355         napi_close_handle_scope(cb->env, scope);
356         return;
357     }
358     CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, object), RESOLVE_DEFERRED, scope);
359     napi_close_handle_scope(cb->env, scope);
360 }
361 
EmitJsDev(sptr<JsUtil::CallbackInfo> cb,std::shared_ptr<InputDevice> device)362 void JsEventTarget::EmitJsDev(sptr<JsUtil::CallbackInfo> cb, std::shared_ptr<InputDevice> device)
363 {
364     CALL_DEBUG_ENTER;
365     CHKPV(device);
366     CHKPV(cb);
367     CHKPV(cb->env);
368     cb->data.device = device;
369     cb->errCode = RET_OK;
370     uv_loop_s *loop = nullptr;
371     CHKRV(napi_get_uv_event_loop(cb->env, &loop), GET_UV_EVENT_LOOP);
372     uv_work_t *work = new (std::nothrow) uv_work_t;
373     CHKPV(work);
374     cb->IncStrongRef(nullptr);
375     work->data = cb.GetRefPtr();
376     int32_t ret = -1;
377     if (cb->isApi9) {
378         if (cb->ref == nullptr) {
379             ret = uv_queue_work_with_qos(
380                 loop, work,
381                 [](uv_work_t *work) {
382                     MMI_HILOGD("uv_queue_work callback function is called");
383                 }, CallDevInfoPromiseWork, uv_qos_user_initiated);
384         } else {
385             ret = uv_queue_work_with_qos(
386                 loop, work,
387                 [](uv_work_t *work) {
388                     MMI_HILOGD("uv_queue_work callback function is called");
389                 }, CallDevInfoAsyncWork, uv_qos_user_initiated);
390         }
391     } else {
392         if (cb->ref == nullptr) {
393             ret = uv_queue_work_with_qos(
394                 loop, work,
395                 [](uv_work_t *work) {
396                     MMI_HILOGD("uv_queue_work callback function is called");
397                 }, CallDevPromiseWork, uv_qos_user_initiated);
398         } else {
399             ret = uv_queue_work_with_qos(
400                 loop, work,
401                 [](uv_work_t *work) {
402                     MMI_HILOGD("uv_queue_work callback function is called");
403                 }, CallDevAsyncWork, uv_qos_user_initiated);
404         }
405     }
406     if (ret != 0) {
407         MMI_HILOGE("uv_queue_work_with_qos failed");
408         JsUtil::DeletePtr<uv_work_t *>(work);
409     }
410 }
411 
CallKeystrokeAbilityPromise(uv_work_t * work,int32_t status)412 void JsEventTarget::CallKeystrokeAbilityPromise(uv_work_t *work, int32_t status)
413 {
414     CALL_DEBUG_ENTER;
415     CHKPV(work);
416     if (work->data == nullptr) {
417         JsUtil::DeletePtr<uv_work_t *>(work);
418         MMI_HILOGE("Check data is nullptr");
419         return;
420     }
421     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
422     JsUtil::DeletePtr<uv_work_t *>(work);
423     cb->DecStrongRef(nullptr);
424     CHKPV(cb->env);
425     napi_handle_scope scope = nullptr;
426     napi_open_handle_scope(cb->env, &scope);
427     CHKPV(scope);
428     napi_value callResult = nullptr;
429     if (cb->errCode != RET_OK) {
430         if (cb->errCode == RET_ERR) {
431             napi_close_handle_scope(cb->env, scope);
432             MMI_HILOGE("Other errors");
433             return;
434         }
435         NapiError codeMsg;
436         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
437             napi_close_handle_scope(cb->env, scope);
438             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
439             return;
440         }
441         callResult = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
442         if (callResult == nullptr) {
443             MMI_HILOGE("callResult is nullptr");
444             napi_close_handle_scope(cb->env, scope);
445             return;
446         }
447         CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, callResult), REJECT_DEFERRED, scope);
448     } else {
449         CHKRV_SCOPE(cb->env, napi_create_array(cb->env, &callResult), CREATE_ARRAY, scope);
450         for (size_t i = 0; i < cb->data.keystrokeAbility.size(); ++i) {
451             napi_value ret = nullptr;
452             napi_value isSupport = nullptr;
453             CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, cb->data.keystrokeAbility[i] ? 1 : 0, &ret), CREATE_INT32,
454                 scope);
455             CHKRV_SCOPE(cb->env, napi_coerce_to_bool(cb->env, ret, &isSupport), COERCE_TO_BOOL, scope);
456             CHKRV_SCOPE(cb->env, napi_set_element(cb->env, callResult, static_cast<uint32_t>(i), isSupport),
457                 SET_ELEMENT, scope);
458         }
459         CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, callResult), RESOLVE_DEFERRED, scope);
460     }
461     napi_close_handle_scope(cb->env, scope);
462 }
463 
CallKeystrokeAbilityAsync(uv_work_t * work,int32_t status)464 void JsEventTarget::CallKeystrokeAbilityAsync(uv_work_t *work, int32_t status)
465 {
466     CALL_DEBUG_ENTER;
467     CHKPV(work);
468     if (work->data == nullptr) {
469         JsUtil::DeletePtr<uv_work_t *>(work);
470         MMI_HILOGE("Check data is nullptr");
471         return;
472     }
473     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
474     JsUtil::DeletePtr<uv_work_t *>(work);
475     cb->DecStrongRef(nullptr);
476     CHKPV(cb->env);
477     napi_handle_scope scope = nullptr;
478     napi_open_handle_scope(cb->env, &scope);
479     CHKPV(scope);
480     napi_value callResult[2] = { 0 };
481     if (cb->errCode != RET_OK) {
482         if (cb->errCode == RET_ERR) {
483             napi_close_handle_scope(cb->env, scope);
484             MMI_HILOGE("Other errors");
485             return;
486         }
487         NapiError codeMsg;
488         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
489             napi_close_handle_scope(cb->env, scope);
490             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
491             return;
492         }
493         callResult[0] = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
494         if (callResult[0] == nullptr) {
495             MMI_HILOGE("callResult[0] is nullptr");
496             napi_close_handle_scope(cb->env, scope);
497             return;
498         }
499         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[1]), GET_UNDEFINED, scope);
500     } else {
501         CHKRV_SCOPE(cb->env, napi_create_array(cb->env, &callResult[1]), CREATE_ARRAY, scope);
502         for (size_t i = 0; i < cb->data.keystrokeAbility.size(); ++i) {
503             napi_value ret = nullptr;
504             napi_value isSupport = nullptr;
505             CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, cb->data.keystrokeAbility[i] ? 1 : 0, &ret), CREATE_INT32,
506                 scope);
507             CHKRV_SCOPE(cb->env, napi_coerce_to_bool(cb->env, ret, &isSupport), COERCE_TO_BOOL, scope);
508             CHKRV_SCOPE(cb->env, napi_set_element(cb->env, callResult[1], static_cast<uint32_t>(i), isSupport),
509                 SET_ELEMENT, scope);
510         }
511         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[0]), GET_UNDEFINED, scope);
512     }
513     napi_value handler = nullptr;
514     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE_VALUE, scope);
515     napi_value result = nullptr;
516     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handler, INPUT_PARAMETER_MIDDLE, callResult, &result),
517         CALL_FUNCTION, scope);
518     napi_close_handle_scope(cb->env, scope);
519 }
520 
EmitSupportKeys(sptr<JsUtil::CallbackInfo> cb,std::vector<bool> & keystrokeAbility)521 void JsEventTarget::EmitSupportKeys(sptr<JsUtil::CallbackInfo> cb, std::vector<bool> &keystrokeAbility)
522 {
523     CALL_DEBUG_ENTER;
524     CHKPV(cb);
525     CHKPV(cb->env);
526     cb->data.keystrokeAbility = keystrokeAbility;
527     cb->errCode = RET_OK;
528     uv_loop_s *loop = nullptr;
529     CHKRV(napi_get_uv_event_loop(cb->env, &loop), GET_UV_EVENT_LOOP);
530     uv_work_t *work = new (std::nothrow) uv_work_t;
531     CHKPV(work);
532     cb->IncStrongRef(nullptr);
533     work->data = cb.GetRefPtr();
534     int32_t ret = -1;
535     if (cb->ref == nullptr) {
536         ret = uv_queue_work_with_qos(
537             loop, work,
538             [](uv_work_t *work) {
539                 MMI_HILOGD("uv_queue_work callback function is called");
540             },
541             CallKeystrokeAbilityPromise, uv_qos_user_initiated);
542     } else {
543         ret = uv_queue_work_with_qos(
544             loop, work,
545             [](uv_work_t *work) {
546                 MMI_HILOGD("uv_queue_work callback function is called");
547             },
548             CallKeystrokeAbilityAsync, uv_qos_user_initiated);
549     }
550     if (ret != 0) {
551         MMI_HILOGE("uv_queue_work_with_qos failed");
552         JsUtil::DeletePtr<uv_work_t *>(work);
553     }
554 }
555 
EmitJsKeyboardType(sptr<JsUtil::CallbackInfo> cb,int32_t keyboardType)556 void JsEventTarget::EmitJsKeyboardType(sptr<JsUtil::CallbackInfo> cb, int32_t keyboardType)
557 {
558     CALL_DEBUG_ENTER;
559     CHKPV(cb);
560     CHKPV(cb->env);
561     cb->data.keyboardType = keyboardType;
562     cb->errCode = RET_OK;
563     uv_loop_s *loop = nullptr;
564     CHKRV(napi_get_uv_event_loop(cb->env, &loop), GET_UV_EVENT_LOOP);
565 
566     uv_work_t *work = new (std::nothrow) uv_work_t;
567     CHKPV(work);
568     cb->IncStrongRef(nullptr);
569     work->data = cb.GetRefPtr();
570     int32_t ret = -1;
571     if (cb->ref == nullptr) {
572         ret = uv_queue_work_with_qos(
573             loop, work,
574             [](uv_work_t *work) {
575                 MMI_HILOGD("uv_queue_work callback function is called");
576             },
577             CallKeyboardTypePromise, uv_qos_user_initiated);
578     } else {
579         ret = uv_queue_work_with_qos(
580             loop, work,
581             [](uv_work_t *work) {
582                 MMI_HILOGD("uv_queue_work callback function is called");
583             },
584             CallKeyboardTypeAsync, uv_qos_user_initiated);
585     }
586     if (ret != 0) {
587         MMI_HILOGE("uv_queue_work_with_qos failed");
588         JsUtil::DeletePtr<uv_work_t *>(work);
589     }
590 }
591 
CallKeyboardTypeAsync(uv_work_t * work,int32_t status)592 void JsEventTarget::CallKeyboardTypeAsync(uv_work_t *work, int32_t status)
593 {
594     CALL_DEBUG_ENTER;
595     CHKPV(work);
596     if (work->data == nullptr) {
597         JsUtil::DeletePtr<uv_work_t *>(work);
598         MMI_HILOGE("Check data is nullptr");
599         return;
600     }
601     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
602     JsUtil::DeletePtr<uv_work_t *>(work);
603     cb->DecStrongRef(nullptr);
604     CHKPV(cb->env);
605 
606     napi_handle_scope scope = nullptr;
607     napi_open_handle_scope(cb->env, &scope);
608     CHKPV(scope);
609 
610     napi_value callResult[2] = { 0 };
611     if (cb->errCode != RET_OK) {
612         if (cb->errCode == RET_ERR) {
613             napi_close_handle_scope(cb->env, scope);
614             MMI_HILOGE("Other errors");
615             return;
616         }
617         NapiError codeMsg;
618         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
619             napi_close_handle_scope(cb->env, scope);
620             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
621             return;
622         }
623         callResult[0] = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
624         if (callResult[0] == nullptr) {
625             MMI_HILOGE("callResult[0] is nullptr");
626             napi_close_handle_scope(cb->env, scope);
627             return;
628         }
629         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[1]), GET_UNDEFINED, scope);
630     } else {
631         CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, cb->data.keyboardType, &callResult[1]), CREATE_INT32, scope);
632         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[0]), GET_UNDEFINED, scope);
633     }
634     napi_value handler = nullptr;
635     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE_VALUE, scope);
636     napi_value result = nullptr;
637     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handler, INPUT_PARAMETER_MIDDLE, callResult, &result),
638         CALL_FUNCTION, scope);
639     napi_close_handle_scope(cb->env, scope);
640 }
641 
CallKeyboardTypePromise(uv_work_t * work,int32_t status)642 void JsEventTarget::CallKeyboardTypePromise(uv_work_t *work, int32_t status)
643 {
644     CALL_DEBUG_ENTER;
645     CHKPV(work);
646     if (work->data == nullptr) {
647         JsUtil::DeletePtr<uv_work_t *>(work);
648         MMI_HILOGE("Check data is nullptr");
649         return;
650     }
651     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
652     JsUtil::DeletePtr<uv_work_t *>(work);
653     cb->DecStrongRef(nullptr);
654     CHKPV(cb->env);
655 
656     napi_handle_scope scope = nullptr;
657     napi_open_handle_scope(cb->env, &scope);
658     CHKPV(scope);
659 
660     napi_value callResult;
661     if (cb->errCode != RET_OK) {
662         if (cb->errCode == RET_ERR) {
663             napi_close_handle_scope(cb->env, scope);
664             MMI_HILOGE("Other errors");
665             return;
666         }
667         NapiError codeMsg;
668         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
669             napi_close_handle_scope(cb->env, scope);
670             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
671             return;
672         }
673         callResult = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
674         if (callResult == nullptr) {
675             MMI_HILOGE("callResult is nullptr");
676             napi_close_handle_scope(cb->env, scope);
677             return;
678         }
679         CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, callResult), REJECT_DEFERRED, scope);
680     } else {
681         CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, cb->data.keyboardType, &callResult), CREATE_INT32, scope);
682         CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, callResult), RESOLVE_DEFERRED, scope);
683     }
684     napi_close_handle_scope(cb->env, scope);
685 }
686 
CallDevListAsyncWork(uv_work_t * work,int32_t status)687 void JsEventTarget::CallDevListAsyncWork(uv_work_t *work, int32_t status)
688 {
689     CALL_DEBUG_ENTER;
690     CHKPV(work);
691     if (work->data == nullptr) {
692         JsUtil::DeletePtr<uv_work_t *>(work);
693         MMI_HILOGE("Check data is nullptr");
694         return;
695     }
696     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
697     JsUtil::DeletePtr<uv_work_t *>(work);
698     cb->DecStrongRef(nullptr);
699     CHKPV(cb->env);
700     napi_handle_scope scope = nullptr;
701     napi_open_handle_scope(cb->env, &scope);
702     CHKPV(scope);
703 
704     napi_value callResult[2] = { 0 };
705     if (cb->errCode != RET_OK) {
706         if (cb->errCode == RET_ERR) {
707             napi_close_handle_scope(cb->env, scope);
708             MMI_HILOGE("Other errors");
709             return;
710         }
711         NapiError codeMsg;
712         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
713             napi_close_handle_scope(cb->env, scope);
714             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
715             return;
716         }
717         callResult[0] = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
718         CHKNRV_SCOPE(cb->env, callResult[0], "callResult[0]", scope);
719         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[1]), GET_UNDEFINED, scope);
720     } else {
721         CHKRV_SCOPE(cb->env, napi_create_array(cb->env, &callResult[1]), CREATE_ARRAY, scope);
722         uint32_t index = 0;
723         napi_value value = nullptr;
724         for (const auto &item : cb->data.ids) {
725             CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, item, &value), CREATE_INT32, scope);
726             CHKRV_SCOPE(cb->env, napi_set_element(cb->env, callResult[1], index, value), SET_ELEMENT, scope);
727             ++index;
728         }
729         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[0]), GET_UNDEFINED, scope);
730     }
731     napi_value handler = nullptr;
732     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE_VALUE, scope);
733     napi_value result = nullptr;
734     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handler, INPUT_PARAMETER_MIDDLE, callResult, &result),
735         CALL_FUNCTION, scope);
736     CHKRV_SCOPE(cb->env, napi_delete_reference(cb->env, cb->ref), DELETE_REFERENCE, scope);
737     napi_close_handle_scope(cb->env, scope);
738 }
739 
CallDevListPromiseWork(uv_work_t * work,int32_t status)740 void JsEventTarget::CallDevListPromiseWork(uv_work_t *work, int32_t status)
741 {
742     CALL_DEBUG_ENTER;
743     CHKPV(work);
744     if (work->data == nullptr) {
745         JsUtil::DeletePtr<uv_work_t *>(work);
746         MMI_HILOGE("Check data is nullptr");
747         return;
748     }
749     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
750     JsUtil::DeletePtr<uv_work_t *>(work);
751     cb->DecStrongRef(nullptr);
752     CHKPV(cb->env);
753     napi_handle_scope scope = nullptr;
754     napi_open_handle_scope(cb->env, &scope);
755     CHKPV(scope);
756     napi_value callResult = nullptr;
757     if (cb->errCode != RET_OK) {
758         if (cb->errCode == RET_ERR) {
759             napi_close_handle_scope(cb->env, scope);
760             MMI_HILOGE("Other errors");
761             return;
762         }
763         NapiError codeMsg;
764         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
765             napi_close_handle_scope(cb->env, scope);
766             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
767             return;
768         }
769         callResult = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
770         if (callResult == nullptr) {
771             MMI_HILOGE("callResult is nullptr");
772             napi_close_handle_scope(cb->env, scope);
773             return;
774         }
775         CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, callResult), REJECT_DEFERRED, scope);
776     } else {
777         CHKRV_SCOPE(cb->env, napi_create_array(cb->env, &callResult), CREATE_ARRAY, scope);
778         uint32_t index = 0;
779         napi_value value = nullptr;
780         for (const auto &item : cb->data.ids) {
781             CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, item, &value), CREATE_INT32, scope);
782             CHKRV_SCOPE(cb->env, napi_set_element(cb->env, callResult, index, value), SET_ELEMENT, scope);
783             ++index;
784         }
785         CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, callResult), RESOLVE_DEFERRED, scope);
786     }
787     napi_close_handle_scope(cb->env, scope);
788 }
789 
CallDevInfoPromiseWork(uv_work_t * work,int32_t status)790 void JsEventTarget::CallDevInfoPromiseWork(uv_work_t *work, int32_t status)
791 {
792     CALL_DEBUG_ENTER;
793     CHKPV(work);
794     if (work->data == nullptr) {
795         JsUtil::DeletePtr<uv_work_t *>(work);
796         MMI_HILOGE("Check data is nullptr");
797         return;
798     }
799     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
800     JsUtil::DeletePtr<uv_work_t *>(work);
801     cb->DecStrongRef(nullptr);
802     CHKPV(cb->env);
803     napi_handle_scope scope = nullptr;
804     napi_open_handle_scope(cb->env, &scope);
805     CHKPV(scope);
806     napi_value callResult = nullptr;
807     if (cb->errCode != RET_OK) {
808         if (cb->errCode == RET_ERR) {
809             napi_close_handle_scope(cb->env, scope);
810             MMI_HILOGE("Other errors");
811             return;
812         }
813         NapiError codeMsg;
814         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
815             napi_close_handle_scope(cb->env, scope);
816             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
817             return;
818         }
819         callResult = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
820         if (callResult == nullptr) {
821             MMI_HILOGE("callResult is nullptr");
822             napi_close_handle_scope(cb->env, scope);
823             return;
824         }
825         CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, callResult), REJECT_DEFERRED, scope);
826     } else {
827         callResult = JsUtil::GetDeviceInfo(cb);
828         if (callResult == nullptr) {
829             MMI_HILOGE("Check callResult is nullptr");
830             napi_close_handle_scope(cb->env, scope);
831             return;
832         }
833         CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, callResult), RESOLVE_DEFERRED, scope);
834     }
835     napi_close_handle_scope(cb->env, scope);
836 }
837 
CallDevInfoAsyncWork(uv_work_t * work,int32_t status)838 void JsEventTarget::CallDevInfoAsyncWork(uv_work_t *work, int32_t status)
839 {
840     CALL_DEBUG_ENTER;
841     CHKPV(work);
842     if (work->data == nullptr) {
843         JsUtil::DeletePtr<uv_work_t *>(work);
844         MMI_HILOGE("Check data is nullptr");
845         return;
846     }
847     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
848     JsUtil::DeletePtr<uv_work_t *>(work);
849     cb->DecStrongRef(nullptr);
850     CHKPV(cb->env);
851     napi_handle_scope scope = nullptr;
852     napi_open_handle_scope(cb->env, &scope);
853     CHKPV(scope);
854     napi_value callResult[2] = { 0 };
855     if (cb->errCode != RET_OK) {
856         if (cb->errCode == RET_ERR) {
857             napi_close_handle_scope(cb->env, scope);
858             MMI_HILOGE("Other errors");
859             return;
860         }
861         NapiError codeMsg;
862         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
863             napi_close_handle_scope(cb->env, scope);
864             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
865             return;
866         }
867         callResult[0] = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
868         if (callResult[0] == nullptr) {
869             MMI_HILOGE("callResult[0] is nullptr");
870             napi_close_handle_scope(cb->env, scope);
871             return;
872         }
873         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[1]), GET_UNDEFINED, scope);
874     } else {
875         callResult[1] = JsUtil::GetDeviceInfo(cb);
876         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[0]), GET_UNDEFINED, scope);
877     }
878     napi_value handler = nullptr;
879     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE_VALUE, scope);
880     napi_value result = nullptr;
881     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handler, INPUT_PARAMETER_MIDDLE, callResult, &result),
882         CALL_FUNCTION, scope);
883     CHKRV_SCOPE(cb->env, napi_delete_reference(cb->env, cb->ref), DELETE_REFERENCE, scope);
884     napi_close_handle_scope(cb->env, scope);
885 }
886 
EmitJsSetKeyboardRepeatDelay(sptr<JsUtil::CallbackInfo> cb,int32_t errCode)887 void JsEventTarget::EmitJsSetKeyboardRepeatDelay(sptr<JsUtil::CallbackInfo> cb, int32_t errCode)
888 {
889     CALL_DEBUG_ENTER;
890     CHKPV(cb);
891     CHKPV(cb->env);
892     cb->data.keyboardRepeatDelay = 0;
893     cb->errCode = errCode;
894     uv_loop_s *loop = nullptr;
895     CHKRV(napi_get_uv_event_loop(cb->env, &loop), GET_UV_EVENT_LOOP);
896 
897     uv_work_t *work = new (std::nothrow) uv_work_t;
898     CHKPV(work);
899     cb->IncStrongRef(nullptr);
900     work->data = cb.GetRefPtr();
901     int32_t ret = -1;
902     if (cb->ref == nullptr) {
903         ret = uv_queue_work_with_qos(
904             loop, work,
905             [](uv_work_t *work) {
906                 MMI_HILOGD("uv_queue_work callback function is called");
907             },
908             CallKeyboardRepeatDelayPromise, uv_qos_user_initiated);
909     } else {
910         ret = uv_queue_work_with_qos(
911             loop, work,
912             [](uv_work_t *work) {
913                 MMI_HILOGD("uv_queue_work callback function is called");
914             },
915             CallKeyboardRepeatDelayAsync, uv_qos_user_initiated);
916     }
917     if (ret != 0) {
918         MMI_HILOGE("uv_queue_work_with_qos failed");
919         JsUtil::DeletePtr<uv_work_t *>(work);
920     }
921 }
922 
EmitJsKeyboardRepeatDelay(sptr<JsUtil::CallbackInfo> cb,int32_t delay)923 void JsEventTarget::EmitJsKeyboardRepeatDelay(sptr<JsUtil::CallbackInfo> cb, int32_t delay)
924 {
925     CALL_DEBUG_ENTER;
926     CHKPV(cb);
927     CHKPV(cb->env);
928     cb->data.keyboardRepeatDelay = delay;
929     cb->errCode = RET_OK;
930     uv_loop_s *loop = nullptr;
931     CHKRV(napi_get_uv_event_loop(cb->env, &loop), GET_UV_EVENT_LOOP);
932 
933     uv_work_t *work = new (std::nothrow) uv_work_t;
934     CHKPV(work);
935     cb->IncStrongRef(nullptr);
936     work->data = cb.GetRefPtr();
937     int32_t ret = -1;
938     if (cb->ref == nullptr) {
939         ret = uv_queue_work_with_qos(
940             loop, work,
941             [](uv_work_t *work) {
942                 MMI_HILOGD("uv_queue_work callback function is called");
943             },
944             CallKeyboardRepeatDelayPromise, uv_qos_user_initiated);
945     } else {
946         ret = uv_queue_work_with_qos(
947             loop, work,
948             [](uv_work_t *work) {
949                 MMI_HILOGD("uv_queue_work callback function is called");
950             },
951             CallKeyboardRepeatDelayAsync, uv_qos_user_initiated);
952     }
953     if (ret != 0) {
954         MMI_HILOGE("uv_queue_work_with_qos failed");
955         JsUtil::DeletePtr<uv_work_t *>(work);
956     }
957 }
958 
CallKeyboardRepeatDelayAsync(uv_work_t * work,int32_t status)959 void JsEventTarget::CallKeyboardRepeatDelayAsync(uv_work_t *work, int32_t status)
960 {
961     CALL_DEBUG_ENTER;
962     CHKPV(work);
963     if (work->data == nullptr) {
964         JsUtil::DeletePtr<uv_work_t *>(work);
965         MMI_HILOGE("Check data is nullptr");
966         return;
967     }
968     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
969     JsUtil::DeletePtr<uv_work_t *>(work);
970     cb->DecStrongRef(nullptr);
971     CHKPV(cb->env);
972 
973     napi_handle_scope scope = nullptr;
974     napi_open_handle_scope(cb->env, &scope);
975     CHKPV(scope);
976 
977     napi_value callResult[2] = {0};
978     if (cb->errCode != RET_OK) {
979         if (cb->errCode == RET_ERR) {
980             napi_close_handle_scope(cb->env, scope);
981             MMI_HILOGE("Other errors");
982             return;
983         }
984         NapiError codeMsg;
985         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
986             napi_close_handle_scope(cb->env, scope);
987             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
988             return;
989         }
990         callResult[0] = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
991         if (callResult[0] == nullptr) {
992             MMI_HILOGE("callResult[0] is nullptr");
993             napi_close_handle_scope(cb->env, scope);
994             return;
995         }
996         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[1]), GET_UNDEFINED, scope);
997     } else {
998         CHKRV_SCOPE(
999             cb->env, napi_create_int32(cb->env, cb->data.keyboardRepeatDelay, &callResult[1]), CREATE_INT32, scope);
1000         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[0]), GET_UNDEFINED, scope);
1001     }
1002     napi_value handler = nullptr;
1003     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE_VALUE, scope);
1004     napi_value result = nullptr;
1005     CHKRV_SCOPE(cb->env,
1006         napi_call_function(cb->env, nullptr, handler, INPUT_PARAMETER_MIDDLE, callResult, &result),
1007         CALL_FUNCTION,
1008         scope);
1009     napi_close_handle_scope(cb->env, scope);
1010 }
1011 
CallKeyboardRepeatDelayPromise(uv_work_t * work,int32_t status)1012 void JsEventTarget::CallKeyboardRepeatDelayPromise(uv_work_t *work, int32_t status)
1013 {
1014     CALL_DEBUG_ENTER;
1015     CHKPV(work);
1016     if (work->data == nullptr) {
1017         JsUtil::DeletePtr<uv_work_t *>(work);
1018         MMI_HILOGE("Check data is nullptr");
1019         return;
1020     }
1021     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
1022     JsUtil::DeletePtr<uv_work_t *>(work);
1023     cb->DecStrongRef(nullptr);
1024     CHKPV(cb->env);
1025 
1026     napi_handle_scope scope = nullptr;
1027     napi_open_handle_scope(cb->env, &scope);
1028     CHKPV(scope);
1029 
1030     napi_value callResult;
1031     if (cb->errCode != RET_OK) {
1032         if (cb->errCode == RET_ERR) {
1033             napi_close_handle_scope(cb->env, scope);
1034             MMI_HILOGE("Other errors");
1035             return;
1036         }
1037         NapiError codeMsg;
1038         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
1039             napi_close_handle_scope(cb->env, scope);
1040             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
1041             return;
1042         }
1043         callResult = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
1044         if (callResult == nullptr) {
1045             MMI_HILOGE("callResult is nullptr");
1046             napi_close_handle_scope(cb->env, scope);
1047             return;
1048         }
1049         CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, callResult), REJECT_DEFERRED, scope);
1050     } else {
1051         CHKRV_SCOPE(
1052             cb->env, napi_create_int32(cb->env, cb->data.keyboardRepeatDelay, &callResult), CREATE_INT32, scope);
1053         CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, callResult), RESOLVE_DEFERRED, scope);
1054     }
1055     napi_close_handle_scope(cb->env, scope);
1056 }
1057 
EmitJsSetKeyboardRepeatRate(sptr<JsUtil::CallbackInfo> cb,int32_t errCode)1058 void JsEventTarget::EmitJsSetKeyboardRepeatRate(sptr<JsUtil::CallbackInfo> cb, int32_t errCode)
1059 {
1060     CALL_DEBUG_ENTER;
1061     CHKPV(cb);
1062     CHKPV(cb->env);
1063     cb->data.keyboardRepeatRate = 0;
1064     cb->errCode = errCode;
1065     uv_loop_s *loop = nullptr;
1066     CHKRV(napi_get_uv_event_loop(cb->env, &loop), GET_UV_EVENT_LOOP);
1067 
1068     uv_work_t *work = new (std::nothrow) uv_work_t;
1069     CHKPV(work);
1070     cb->IncStrongRef(nullptr);
1071     work->data = cb.GetRefPtr();
1072     int32_t ret = -1;
1073     if (cb->ref == nullptr) {
1074         ret = uv_queue_work_with_qos(
1075             loop, work,
1076             [](uv_work_t *work) {
1077                 MMI_HILOGD("uv_queue_work callback function is called");
1078             },
1079             CallKeyboardRepeatRatePromise, uv_qos_user_initiated);
1080     } else {
1081         ret = uv_queue_work_with_qos(
1082             loop, work,
1083             [](uv_work_t *work) {
1084                 MMI_HILOGD("uv_queue_work callback function is called");
1085             },
1086             CallKeyboardRepeatRateAsync, uv_qos_user_initiated);
1087     }
1088     if (ret != 0) {
1089         MMI_HILOGE("uv_queue_work_with_qos failed");
1090         JsUtil::DeletePtr<uv_work_t *>(work);
1091     }
1092 }
1093 
EmitJsKeyboardRepeatRate(sptr<JsUtil::CallbackInfo> cb,int32_t rate)1094 void JsEventTarget::EmitJsKeyboardRepeatRate(sptr<JsUtil::CallbackInfo> cb, int32_t rate)
1095 {
1096     CALL_DEBUG_ENTER;
1097     CHKPV(cb);
1098     CHKPV(cb->env);
1099     cb->data.keyboardRepeatRate = rate;
1100     cb->errCode = RET_OK;
1101     uv_loop_s *loop = nullptr;
1102     CHKRV(napi_get_uv_event_loop(cb->env, &loop), GET_UV_EVENT_LOOP);
1103 
1104     uv_work_t *work = new (std::nothrow) uv_work_t;
1105     CHKPV(work);
1106     cb->IncStrongRef(nullptr);
1107     work->data = cb.GetRefPtr();
1108     int32_t ret = -1;
1109     if (cb->ref == nullptr) {
1110         ret = uv_queue_work_with_qos(
1111             loop, work,
1112             [](uv_work_t *work) {
1113                 MMI_HILOGD("uv_queue_work callback function is called");
1114             },
1115             CallKeyboardRepeatRatePromise, uv_qos_user_initiated);
1116     } else {
1117         ret = uv_queue_work_with_qos(
1118             loop, work,
1119             [](uv_work_t *work) {
1120                 MMI_HILOGD("uv_queue_work callback function is called");
1121             },
1122             CallKeyboardRepeatRateAsync, uv_qos_user_initiated);
1123     }
1124     if (ret != 0) {
1125         MMI_HILOGE("uv_queue_work_with_qos failed");
1126         JsUtil::DeletePtr<uv_work_t *>(work);
1127     }
1128 }
1129 
CallKeyboardRepeatRateAsync(uv_work_t * work,int32_t status)1130 void JsEventTarget::CallKeyboardRepeatRateAsync(uv_work_t *work, int32_t status)
1131 {
1132     CALL_DEBUG_ENTER;
1133     CHKPV(work);
1134     if (work->data == nullptr) {
1135         JsUtil::DeletePtr<uv_work_t *>(work);
1136         MMI_HILOGE("Check data is nullptr");
1137         return;
1138     }
1139     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
1140     JsUtil::DeletePtr<uv_work_t *>(work);
1141     cb->DecStrongRef(nullptr);
1142     CHKPV(cb->env);
1143 
1144     napi_handle_scope scope = nullptr;
1145     napi_open_handle_scope(cb->env, &scope);
1146     CHKPV(scope);
1147 
1148     napi_value callResult[2] = {0};
1149     if (cb->errCode != RET_OK) {
1150         if (cb->errCode == RET_ERR) {
1151             napi_close_handle_scope(cb->env, scope);
1152             MMI_HILOGE("Other errors");
1153             return;
1154         }
1155         NapiError codeMsg;
1156         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
1157             napi_close_handle_scope(cb->env, scope);
1158             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
1159             return;
1160         }
1161         callResult[0] = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
1162         if (callResult[0] == nullptr) {
1163             MMI_HILOGE("callResult[0] is nullptr");
1164             napi_close_handle_scope(cb->env, scope);
1165             return;
1166         }
1167         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[1]), GET_UNDEFINED, scope);
1168     } else {
1169         CHKRV_SCOPE(
1170             cb->env, napi_create_int32(cb->env, cb->data.keyboardRepeatRate, &callResult[1]), CREATE_INT32, scope);
1171         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[0]), GET_UNDEFINED, scope);
1172     }
1173     napi_value handler = nullptr;
1174     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE_VALUE, scope);
1175     napi_value result = nullptr;
1176     CHKRV_SCOPE(cb->env,
1177         napi_call_function(cb->env, nullptr, handler, INPUT_PARAMETER_MIDDLE, callResult, &result),
1178         CALL_FUNCTION,
1179         scope);
1180     napi_close_handle_scope(cb->env, scope);
1181 }
1182 
CallKeyboardRepeatRatePromise(uv_work_t * work,int32_t status)1183 void JsEventTarget::CallKeyboardRepeatRatePromise(uv_work_t *work, int32_t status)
1184 {
1185     CALL_DEBUG_ENTER;
1186     CHKPV(work);
1187     if (work->data == nullptr) {
1188         JsUtil::DeletePtr<uv_work_t *>(work);
1189         MMI_HILOGE("Check data is nullptr");
1190         return;
1191     }
1192     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
1193     JsUtil::DeletePtr<uv_work_t *>(work);
1194     cb->DecStrongRef(nullptr);
1195     CHKPV(cb->env);
1196 
1197     napi_handle_scope scope = nullptr;
1198     napi_open_handle_scope(cb->env, &scope);
1199     CHKPV(scope);
1200 
1201     napi_value callResult;
1202     if (cb->errCode != RET_OK) {
1203         if (cb->errCode == RET_ERR) {
1204             napi_close_handle_scope(cb->env, scope);
1205             MMI_HILOGE("Other errors");
1206             return;
1207         }
1208         NapiError codeMsg;
1209         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
1210             napi_close_handle_scope(cb->env, scope);
1211             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
1212             return;
1213         }
1214         callResult = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
1215         if (callResult == nullptr) {
1216             MMI_HILOGE("callResult is nullptr");
1217             napi_close_handle_scope(cb->env, scope);
1218             return;
1219         }
1220         CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, callResult), REJECT_DEFERRED, scope);
1221     } else {
1222         CHKRV_SCOPE(
1223             cb->env, napi_create_int32(cb->env, cb->data.keyboardRepeatRate, &callResult), CREATE_INT32, scope);
1224         CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, callResult), RESOLVE_DEFERRED, scope);
1225     }
1226     napi_close_handle_scope(cb->env, scope);
1227 }
1228 
AddListener(napi_env env,const std::string & type,napi_value handle)1229 void JsEventTarget::AddListener(napi_env env, const std::string &type, napi_value handle)
1230 {
1231     CALL_DEBUG_ENTER;
1232     std::lock_guard<std::mutex> guard(mutex_);
1233     auto iter = devListener_.find(type);
1234     if (iter == devListener_.end()) {
1235         MMI_HILOGE("Find %{public}s failed", type.c_str());
1236         return;
1237     }
1238 
1239     for (const auto &temp : iter->second) {
1240         CHKPC(temp);
1241         if (temp->env != env) {
1242             continue;
1243         }
1244         if (JsUtil::IsSameHandle(env, handle, temp->ref)) {
1245             MMI_HILOGW("The handle already exists");
1246             return;
1247         }
1248     }
1249     napi_ref ref = nullptr;
1250     CHKRV(napi_create_reference(env, handle, 1, &ref), CREATE_REFERENCE);
1251     auto monitor = std::make_unique<JsUtil::CallbackInfo>();
1252     monitor->env = env;
1253     monitor->ref = ref;
1254     iter->second.push_back(std::move(monitor));
1255     if (!isListeningProcess_) {
1256         isListeningProcess_ = true;
1257         InputManager::GetInstance()->RegisterDevListener("change", shared_from_this());
1258     }
1259 }
1260 
RemoveListener(napi_env env,const std::string & type,napi_value handle)1261 void JsEventTarget::RemoveListener(napi_env env, const std::string &type, napi_value handle)
1262 {
1263     CALL_DEBUG_ENTER;
1264     std::lock_guard<std::mutex> guard(mutex_);
1265     auto iter = devListener_.find(type);
1266     if (iter == devListener_.end()) {
1267         MMI_HILOGE("Find %{public}s failed", type.c_str());
1268         return;
1269     }
1270     if (handle == nullptr) {
1271         iter->second.clear();
1272         goto monitorLabel;
1273     }
1274     for (auto it = iter->second.begin(); it != iter->second.end(); ++it) {
1275         if ((*it)->env != env) {
1276             continue;
1277         }
1278         if (JsUtil::IsSameHandle(env, handle, (*it)->ref)) {
1279             MMI_HILOGD("Succeeded in removing monitor");
1280             JsUtil::DeleteCallbackInfo(std::move(*it));
1281             iter->second.erase(it);
1282             goto monitorLabel;
1283         }
1284     }
1285 
1286 monitorLabel:
1287     if (isListeningProcess_ && iter->second.empty()) {
1288         isListeningProcess_ = false;
1289         InputManager::GetInstance()->UnregisterDevListener("change", shared_from_this());
1290     }
1291 }
1292 
GreateBusinessError(napi_env env,int32_t errCode,std::string errMessage)1293 napi_value JsEventTarget::GreateBusinessError(napi_env env, int32_t errCode, std::string errMessage)
1294 {
1295     CALL_DEBUG_ENTER;
1296     napi_value result = nullptr;
1297     napi_value resultCode = nullptr;
1298     napi_value resultMessage = nullptr;
1299     CHKRP(napi_create_int32(env, errCode, &resultCode), CREATE_INT32);
1300     CHKRP(napi_create_string_utf8(env, errMessage.data(), NAPI_AUTO_LENGTH, &resultMessage), CREATE_STRING_UTF8);
1301     CHKRP(napi_create_error(env, nullptr, resultMessage, &result), CREATE_ERROR);
1302     CHKRP(napi_set_named_property(env, result, ERR_CODE.c_str(), resultCode), SET_NAMED_PROPERTY);
1303     return result;
1304 }
1305 
CreateCallbackInfo(napi_env env,napi_value handle,sptr<JsUtil::CallbackInfo> cb)1306 napi_value JsEventTarget::CreateCallbackInfo(napi_env env, napi_value handle, sptr<JsUtil::CallbackInfo> cb)
1307 {
1308     CALL_DEBUG_ENTER;
1309     CHKPP(cb);
1310     cb->env = env;
1311     napi_value promise = nullptr;
1312     if (handle == nullptr) {
1313         CHKRP(napi_create_promise(env, &cb->deferred, &promise), CREATE_PROMISE);
1314     } else {
1315         CHKRP(napi_create_reference(env, handle, 1, &cb->ref), CREATE_REFERENCE);
1316     }
1317     return promise;
1318 }
1319 
EmitJsGetIntervalSinceLastInput(sptr<JsUtil::CallbackInfo> cb,int64_t timeInterval)1320 void JsEventTarget::EmitJsGetIntervalSinceLastInput(sptr<JsUtil::CallbackInfo> cb, int64_t timeInterval)
1321 {
1322     CALL_DEBUG_ENTER;
1323     CHKPV(cb);
1324     CHKPV(cb->env);
1325     cb->data.IntervalSinceLastInput = timeInterval;
1326     uv_loop_s *loop = nullptr;
1327     CHKRV(napi_get_uv_event_loop(cb->env, &loop), GET_UV_EVENT_LOOP);
1328     uv_work_t *work = new (std::nothrow) uv_work_t;
1329     CHKPV(work);
1330     cb->IncStrongRef(nullptr);
1331     work->data = cb.GetRefPtr();
1332     int32_t ret = 0;
1333     ret = uv_queue_work_with_qos(
1334         loop, work,
1335         [](uv_work_t *work) {
1336             MMI_HILOGD("uv_queue_work callback function is called");
1337         },
1338         CallIntervalSinceLastInputPromise, uv_qos_user_initiated);
1339     if (ret != 0) {
1340         MMI_HILOGE("uv_queue_work_with_qos failed");
1341         cb->DecStrongRef(nullptr);
1342         JsUtil::DeletePtr<uv_work_t *>(work);
1343     }
1344 }
1345 
CallIntervalSinceLastInputPromise(uv_work_t * work,int32_t status)1346 void JsEventTarget::CallIntervalSinceLastInputPromise(uv_work_t *work, int32_t status)
1347 {
1348     CALL_DEBUG_ENTER;
1349     CHKPV(work);
1350     if (work->data == nullptr) {
1351         JsUtil::DeletePtr<uv_work_t *>(work);
1352         MMI_HILOGE("Check data is nullptr");
1353         return;
1354     }
1355     sptr<JsUtil::CallbackInfo> cb(static_cast<JsUtil::CallbackInfo *>(work->data));
1356     JsUtil::DeletePtr<uv_work_t *>(work);
1357     cb->DecStrongRef(nullptr);
1358     CHKPV(cb->env);
1359 
1360     napi_handle_scope scope = nullptr;
1361     napi_open_handle_scope(cb->env, &scope);
1362     CHKPV(scope);
1363     napi_value callResult;
1364     CHKRV_SCOPE(cb->env, napi_create_int64(cb->env, cb->data.IntervalSinceLastInput, &callResult),
1365         CREATE_INT64, scope);
1366     CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, callResult), RESOLVE_DEFERRED, scope);
1367     napi_close_handle_scope(cb->env, scope);
1368 }
1369 
ResetEnv()1370 void JsEventTarget::ResetEnv()
1371 {
1372     CALL_DEBUG_ENTER;
1373     std::lock_guard<std::mutex> guard(mutex_);
1374     devListener_.clear();
1375     InputManager::GetInstance()->UnregisterDevListener("change", shared_from_this());
1376 }
1377 } // namespace MMI
1378 } // namespace OHOS
1379