• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "js_event_target.h"
17 
18 #include "napi_constants.h"
19 #include "util_napi_error.h"
20 
21 namespace OHOS {
22 namespace MMI {
23 namespace {
24 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MMI_LOG_DOMAIN, "JsEventTarget" };
25 
26 std::mutex mutex_;
27 const std::string ADD_EVENT = "add";
28 const std::string REMOVE_EVENT = "remove";
29 } // namespace
30 
JsEventTarget()31 JsEventTarget::JsEventTarget()
32 {
33     CALL_DEBUG_ENTER;
34     auto ret = devListener_.insert({ CHANGED_TYPE, std::vector<std::unique_ptr<JsUtil::CallbackInfo>>() });
35     CK(ret.second, VAL_NOT_EXP);
36 }
37 
~JsEventTarget()38 JsEventTarget::~JsEventTarget() {}
39 
EmitAddedDeviceEvent(uv_work_t * work,int32_t status)40 void JsEventTarget::EmitAddedDeviceEvent(uv_work_t *work, int32_t status)
41 {
42     CALL_DEBUG_ENTER;
43     std::lock_guard<std::mutex> guard(mutex_);
44     CHKPV(work);
45     if (work->data == nullptr) {
46         JsUtil::DeletePtr<uv_work_t*>(work);
47         MMI_HILOGE("Check data is null");
48         return;
49     }
50     auto temp = static_cast<std::unique_ptr<JsUtil::CallbackInfo>*>(work->data);
51     JsUtil::DeletePtr<uv_work_t*>(work);
52     auto addEvent = devListener_.find(CHANGED_TYPE);
53     if (addEvent == devListener_.end()) {
54         MMI_HILOGE("Find change event failed");
55         return;
56     }
57 
58     for (const auto &item : addEvent->second) {
59         CHKPC(item->env);
60         if (item->ref != (*temp)->ref) {
61             continue;
62         }
63         napi_handle_scope scope = nullptr;
64         napi_open_handle_scope(item->env, &scope);
65         if (scope == nullptr) {
66             MMI_HILOGE("scope is nullptr");
67             return;
68         }
69         napi_value eventType = nullptr;
70         CHKRV_SCOPE(item->env, napi_create_string_utf8(item->env, ADD_EVENT.c_str(), NAPI_AUTO_LENGTH, &eventType),
71                 CREATE_STRING_UTF8, scope);
72         napi_value deviceId = nullptr;
73         CHKRV_SCOPE(item->env, napi_create_int32(item->env, item->data.deviceId, &deviceId), CREATE_INT32, scope);
74         napi_value object = nullptr;
75         CHKRV_SCOPE(item->env, napi_create_object(item->env, &object), CREATE_OBJECT, scope);
76         CHKRV_SCOPE(item->env, napi_set_named_property(item->env, object, "type", eventType),
77                 SET_NAMED_PROPERTY, scope);
78         CHKRV_SCOPE(item->env, napi_set_named_property(item->env, object, "deviceId", deviceId),
79                 SET_NAMED_PROPERTY, scope);
80         napi_value handler = nullptr;
81         CHKRV_SCOPE(item->env, napi_get_reference_value(item->env, item->ref, &handler), GET_REFERENCE, scope);
82         napi_value ret = nullptr;
83         CHKRV_SCOPE(item->env, napi_call_function(item->env, nullptr, handler, 1, &object, &ret),
84                 CALL_FUNCTION, scope);
85         napi_close_handle_scope(item->env, scope);
86     }
87 }
88 
EmitRemoveDeviceEvent(uv_work_t * work,int32_t status)89 void JsEventTarget::EmitRemoveDeviceEvent(uv_work_t *work, int32_t status)
90 {
91     CALL_DEBUG_ENTER;
92     std::lock_guard<std::mutex> guard(mutex_);
93     CHKPV(work);
94     if (work->data == nullptr) {
95         JsUtil::DeletePtr<uv_work_t*>(work);
96         MMI_HILOGE("Check data is null");
97         return;
98     }
99     auto temp = static_cast<std::unique_ptr<JsUtil::CallbackInfo>*>(work->data);
100     JsUtil::DeletePtr<uv_work_t*>(work);
101     auto removeEvent = devListener_.find(CHANGED_TYPE);
102     if (removeEvent == devListener_.end()) {
103         MMI_HILOGE("Find change event failed");
104         return;
105     }
106 
107     for (const auto &item : removeEvent->second) {
108         CHKPC(item->env);
109         if (item->ref != (*temp)->ref) {
110             continue;
111         }
112         napi_handle_scope scope = nullptr;
113         napi_open_handle_scope(item->env, &scope);
114         if (scope == nullptr) {
115             MMI_HILOGE("scope is nullptr");
116             return;
117         }
118         napi_value eventType = nullptr;
119         CHKRV_SCOPE(item->env, napi_create_string_utf8(item->env, REMOVE_EVENT.c_str(), NAPI_AUTO_LENGTH,
120              &eventType),
121              CREATE_STRING_UTF8, scope);
122 
123         napi_value deviceId = nullptr;
124         CHKRV_SCOPE(item->env, napi_create_int32(item->env, item->data.deviceId, &deviceId),
125              CREATE_INT32, scope);
126 
127         napi_value object = nullptr;
128         CHKRV_SCOPE(item->env, napi_create_object(item->env, &object), CREATE_OBJECT, scope);
129         CHKRV_SCOPE(item->env, napi_set_named_property(item->env, object, "type", eventType),
130              SET_NAMED_PROPERTY, scope);
131         CHKRV_SCOPE(item->env, napi_set_named_property(item->env, object, "deviceId", deviceId),
132              SET_NAMED_PROPERTY, scope);
133 
134         napi_value handler = nullptr;
135         CHKRV_SCOPE(item->env, napi_get_reference_value(item->env, item->ref, &handler), GET_REFERENCE, scope);
136 
137         napi_value ret = nullptr;
138         CHKRV_SCOPE(item->env, napi_call_function(item->env, nullptr, handler, 1, &object, &ret),
139              CALL_FUNCTION, scope);
140         napi_close_handle_scope(item->env, scope);
141     }
142 }
143 
OnDeviceAdded(int32_t deviceId,const std::string & type)144 void JsEventTarget::OnDeviceAdded(int32_t deviceId, const std::string &type)
145 {
146     CALL_DEBUG_ENTER;
147     std::lock_guard<std::mutex> guard(mutex_);
148     auto changeEvent = devListener_.find(CHANGED_TYPE);
149     if (changeEvent == devListener_.end()) {
150         MMI_HILOGE("Find %{public}s failed", CHANGED_TYPE.c_str());
151         return;
152     }
153 
154     for (auto &item : changeEvent->second) {
155         CHKPC(item);
156         CHKPC(item->env);
157         uv_loop_s *loop = nullptr;
158         CHKRV(item->env, napi_get_uv_event_loop(item->env, &loop), GET_UV_LOOP);
159         uv_work_t *work = new (std::nothrow) uv_work_t;
160         CHKPV(work);
161         item->data.deviceId = deviceId;
162         work->data = static_cast<void*>(&item);
163         int32_t ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, EmitAddedDeviceEvent);
164         if (ret != 0) {
165             MMI_HILOGE("uv_queue_work failed");
166             JsUtil::DeletePtr<uv_work_t*>(work);
167             return;
168         }
169     }
170 }
171 
OnDeviceRemoved(int32_t deviceId,const std::string & type)172 void JsEventTarget::OnDeviceRemoved(int32_t deviceId, const std::string &type)
173 {
174     CALL_DEBUG_ENTER;
175     std::lock_guard<std::mutex> guard(mutex_);
176     auto changeEvent = devListener_.find(CHANGED_TYPE);
177     if (changeEvent == devListener_.end()) {
178         MMI_HILOGE("Find %{public}s failed", CHANGED_TYPE.c_str());
179         return;
180     }
181     for (auto &item : changeEvent->second) {
182         CHKPC(item);
183         CHKPC(item->env);
184         uv_loop_s *loop = nullptr;
185         CHKRV(item->env, napi_get_uv_event_loop(item->env, &loop), GET_UV_LOOP);
186         uv_work_t *work = new (std::nothrow) uv_work_t;
187         CHKPV(work);
188         item->data.deviceId = deviceId;
189         work->data = static_cast<void*>(&item);
190         int32_t ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, EmitRemoveDeviceEvent);
191         if (ret != 0) {
192             MMI_HILOGE("uv_queue_work failed");
193             JsUtil::DeletePtr<uv_work_t*>(work);
194             return;
195         }
196     }
197 }
198 
CallIdsAsyncWork(uv_work_t * work,int32_t status)199 void JsEventTarget::CallIdsAsyncWork(uv_work_t *work, int32_t status)
200 {
201     CALL_DEBUG_ENTER;
202     CHKPV(work);
203     if (work->data == nullptr) {
204         JsUtil::DeletePtr<uv_work_t*>(work);
205         MMI_HILOGE("Check data is null");
206         return;
207     }
208     std::unique_ptr<JsUtil::CallbackInfo> cb = GetCallbackInfo(work);
209     CHKPV(cb);
210     CHKPV(cb->env);
211 
212     napi_handle_scope scope = nullptr;
213     napi_open_handle_scope(cb->env, &scope);
214     if (scope == nullptr) {
215         MMI_HILOGE("scope is nullptr");
216         return;
217     }
218     napi_value arr[2];
219     CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &arr[0]), GET_UNDEFINED, scope);
220     CHKRV_SCOPE(cb->env, napi_create_array(cb->env, &arr[1]), CREATE_ARRAY, scope);
221     uint32_t index = 0;
222     napi_value value = nullptr;
223     for (const auto &item : cb->data.ids) {
224         CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, item, &value), CREATE_INT32, scope);
225         CHKRV_SCOPE(cb->env, napi_set_element(cb->env, arr[1], index, value), SET_ELEMENT, scope);
226         ++index;
227     }
228 
229     napi_value handler = nullptr;
230     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE, scope);
231     napi_value result = nullptr;
232     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handler, 2, arr, &result), CALL_FUNCTION, scope);
233     napi_close_handle_scope(cb->env, scope);
234     JsUtil::DeleteCallbackInfo(std::move(cb));
235 }
236 
CallIdsPromiseWork(uv_work_t * work,int32_t status)237 void JsEventTarget::CallIdsPromiseWork(uv_work_t *work, int32_t status)
238 {
239     CALL_DEBUG_ENTER;
240     CHKPV(work);
241     if (work->data == nullptr) {
242         JsUtil::DeletePtr<uv_work_t*>(work);
243         MMI_HILOGE("Check data is null");
244         return;
245     }
246     std::unique_ptr<JsUtil::CallbackInfo> cb = GetCallbackInfo(work);
247     CHKPV(cb);
248     CHKPV(cb->env);
249 
250     napi_handle_scope scope = nullptr;
251     napi_open_handle_scope(cb->env, &scope);
252     if (scope == nullptr) {
253         MMI_HILOGE("scope is nullptr");
254         return;
255     }
256     napi_value arr = nullptr;
257     CHKRV_SCOPE(cb->env, napi_create_array(cb->env, &arr), CREATE_ARRAY, scope);
258     uint32_t index = 0;
259     napi_value value = nullptr;
260     for (const auto &item : cb->data.ids) {
261         CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, item, &value), CREATE_INT32, scope);
262         CHKRV_SCOPE(cb->env, napi_set_element(cb->env, arr, index, value), SET_ELEMENT, scope);
263         ++index;
264     }
265     CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, arr), RESOLVE_DEFERRED, scope);
266     napi_close_handle_scope(cb->env, scope);
267     JsUtil::DeleteCallbackInfo(std::move(cb));
268 }
269 
EmitJsIds(int32_t userData,std::vector<int32_t> & ids)270 void JsEventTarget::EmitJsIds(int32_t userData, std::vector<int32_t> &ids)
271 {
272     CALL_DEBUG_ENTER;
273     std::lock_guard<std::mutex> guard(mutex_);
274     auto iter = callback_.find(userData);
275     if (iter == callback_.end()) {
276         MMI_HILOGE("Failed to search for userData");
277         return;
278     }
279     CHKPV(iter->second);
280     if (iter->second->env == nullptr) {
281         callback_.erase(iter);
282         MMI_HILOGE("The env is nullptr");
283         return;
284     }
285 
286     iter->second->data.ids = ids;
287     iter->second->errCode = RET_OK;
288     uv_loop_s *loop = nullptr;
289     CHKRV(iter->second->env, napi_get_uv_event_loop(iter->second->env, &loop), GET_UV_LOOP);
290     uv_work_t *work = new (std::nothrow) uv_work_t;
291     CHKPV(work);
292     int32_t *uData = new (std::nothrow) int32_t(userData);
293     if ((uData) == nullptr) {
294         JsUtil::DeletePtr<uv_work_t*>(work);
295         MMI_HILOGE("Check uData is null");
296         return;
297     }
298     work->data = static_cast<void*>(uData);
299     int32_t ret;
300     if (iter->second->isApi9) {
301         if (iter->second->ref == nullptr) {
302             ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, CallDevListPromiseWork);
303         } else {
304             ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, CallDevListAsyncWork);
305         }
306     } else {
307         if (iter->second->ref == nullptr) {
308             ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, CallIdsPromiseWork);
309         } else {
310             ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, CallIdsAsyncWork);
311         }
312     }
313     if (ret != 0) {
314         MMI_HILOGE("uv_queue_work failed");
315         JsUtil::DeletePtr<uv_work_t*>(work);
316         JsUtil::DeletePtr<int32_t*>(uData);
317     }
318 }
319 
CallDevAsyncWork(uv_work_t * work,int32_t status)320 void JsEventTarget::CallDevAsyncWork(uv_work_t *work, int32_t status)
321 {
322     CALL_DEBUG_ENTER;
323     CHKPV(work);
324     if (work->data == nullptr) {
325         JsUtil::DeletePtr<uv_work_t*>(work);
326         MMI_HILOGE("Check data is null");
327         return;
328     }
329     std::unique_ptr<JsUtil::CallbackInfo> cb = GetCallbackInfo(work);
330     CHKPV(cb);
331     CHKPV(cb->env);
332     napi_handle_scope scope = nullptr;
333     napi_open_handle_scope(cb->env, &scope);
334     if (scope == nullptr) {
335         MMI_HILOGE("scope is nullptr");
336         return;
337     }
338     napi_value object[2];
339     CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &object[0]), GET_UNDEFINED, scope);
340     object[1] = JsUtil::GetDeviceInfo(cb);
341     napi_value handler = nullptr;
342     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE, scope);
343     napi_value result = nullptr;
344     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handler, 2, object, &result), CALL_FUNCTION,
345         scope);
346     napi_close_handle_scope(cb->env, scope);
347     JsUtil::DeleteCallbackInfo(std::move(cb));
348 }
349 
CallDevPromiseWork(uv_work_t * work,int32_t status)350 void JsEventTarget::CallDevPromiseWork(uv_work_t *work, int32_t status)
351 {
352     CALL_DEBUG_ENTER;
353     CHKPV(work);
354     if (work->data == nullptr) {
355         JsUtil::DeletePtr<uv_work_t*>(work);
356         MMI_HILOGE("Check data is null");
357         return;
358     }
359     std::unique_ptr<JsUtil::CallbackInfo> cb = GetCallbackInfo(work);
360     CHKPV(cb);
361     CHKPV(cb->env);
362     napi_handle_scope scope = nullptr;
363     napi_open_handle_scope(cb->env, &scope);
364     if (scope == nullptr) {
365         MMI_HILOGE("scope is nullptr");
366         return;
367     }
368     napi_value object = JsUtil::GetDeviceInfo(cb);
369     if (object == nullptr) {
370         MMI_HILOGE("Check object is null");
371         napi_close_handle_scope(cb->env, scope);
372         return;
373     }
374     CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, object), RESOLVE_DEFERRED, scope);
375     napi_close_handle_scope(cb->env, scope);
376     JsUtil::DeleteCallbackInfo(std::move(cb));
377 }
378 
EmitJsDev(int32_t userData,std::shared_ptr<InputDevice> device)379 void JsEventTarget::EmitJsDev(int32_t userData, std::shared_ptr<InputDevice> device)
380 {
381     CALL_DEBUG_ENTER;
382     std::lock_guard<std::mutex> guard(mutex_);
383     CHKPV(device);
384     auto iter = callback_.find(userData);
385     if (iter == callback_.end()) {
386         MMI_HILOGE("Failed to search for userData");
387         return;
388     }
389     CHKPV(iter->second);
390     if (iter->second->env == nullptr) {
391         callback_.erase(iter);
392         MMI_HILOGE("The env is nullptr");
393         return;
394     }
395 
396     iter->second->data.device = device;
397     iter->second->errCode = RET_OK;
398     uv_loop_s *loop = nullptr;
399     CHKRV(iter->second->env, napi_get_uv_event_loop(iter->second->env, &loop), GET_UV_LOOP);
400     uv_work_t *work = new (std::nothrow) uv_work_t;
401     CHKPV(work);
402     int32_t *uData = new (std::nothrow) int32_t(userData);
403     CHKPV(uData);
404     work->data = static_cast<void*>(uData);
405     int32_t ret;
406     if (iter->second->isApi9) {
407         if (iter->second->ref == nullptr) {
408             ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, CallDevInfoPromiseWork);
409         } else {
410             ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, CallDevInfoAsyncWork);
411         }
412     } else {
413         if (iter->second->ref == nullptr) {
414             ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, CallDevPromiseWork);
415         } else {
416             ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, CallDevAsyncWork);
417         }
418     }
419     if (ret != 0) {
420         MMI_HILOGE("uv_queue_work failed");
421         JsUtil::DeletePtr<uv_work_t*>(work);
422         JsUtil::DeletePtr<int32_t*>(uData);
423         return;
424     }
425 }
426 
CallKeystrokeAbilityPromise(uv_work_t * work,int32_t status)427 void JsEventTarget::CallKeystrokeAbilityPromise(uv_work_t *work, int32_t status)
428 {
429     CALL_DEBUG_ENTER;
430     CHKPV(work);
431     if (work->data == nullptr) {
432         JsUtil::DeletePtr<uv_work_t*>(work);
433         MMI_HILOGE("Check data is null");
434         return;
435     }
436     std::unique_ptr<JsUtil::CallbackInfo> cb = GetCallbackInfo(work);
437     CHKPV(cb);
438     CHKPV(cb->env);
439 
440     napi_handle_scope scope = nullptr;
441     napi_open_handle_scope(cb->env, &scope);
442     CHKPV(scope);
443     napi_value callResult = nullptr;
444     if (cb->errCode != RET_OK) {
445         if (cb->errCode == RET_ERR) {
446             napi_close_handle_scope(cb->env, scope);
447             MMI_HILOGE("Other errors");
448             return;
449         }
450         NapiError codeMsg;
451         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
452             napi_close_handle_scope(cb->env, scope);
453             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
454             return;
455         }
456         callResult = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
457         CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, callResult), REJECT_DEFERRED, scope);
458     } else {
459         CHKRV_SCOPE(cb->env, napi_create_array(cb->env, &callResult), CREATE_ARRAY, scope);
460         for (size_t i = 0; i < cb->data.keystrokeAbility.size(); ++i) {
461             napi_value ret = nullptr;
462             napi_value isSupport = nullptr;
463             CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, cb->data.keystrokeAbility[i] ? 1 : 0, &ret),
464                 CREATE_INT32, scope);
465             CHKRV_SCOPE(cb->env, napi_coerce_to_bool(cb->env, ret, &isSupport), COERCE_TO_BOOL, scope);
466             CHKRV_SCOPE(cb->env, napi_set_element(cb->env, callResult, static_cast<uint32_t>(i), isSupport),
467                 SET_ELEMENT, scope);
468         }
469         CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, callResult), RESOLVE_DEFERRED, scope);
470     }
471     napi_close_handle_scope(cb->env, scope);
472     JsUtil::DeleteCallbackInfo(std::move(cb));
473 }
474 
CallKeystrokeAbilityAsync(uv_work_t * work,int32_t status)475 void JsEventTarget::CallKeystrokeAbilityAsync(uv_work_t *work, int32_t status)
476 {
477     CALL_DEBUG_ENTER;
478     CHKPV(work);
479     if (work->data == nullptr) {
480         JsUtil::DeletePtr<uv_work_t*>(work);
481         MMI_HILOGE("Check data is null");
482         return;
483     }
484     std::unique_ptr<JsUtil::CallbackInfo> cb = GetCallbackInfo(work);
485     CHKPV(cb);
486     CHKPV(cb->env);
487 
488     napi_handle_scope scope = nullptr;
489     napi_open_handle_scope(cb->env, &scope);
490     CHKPV(scope);
491     napi_value callResult[2] = { 0 };
492     if (cb->errCode != RET_OK) {
493         if (cb->errCode == RET_ERR) {
494             napi_close_handle_scope(cb->env, scope);
495             MMI_HILOGE("Other errors");
496             return;
497         }
498         NapiError codeMsg;
499         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
500             napi_close_handle_scope(cb->env, scope);
501             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
502             return;
503         }
504         callResult[0] = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
505         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[1]), GET_UNDEFINED, scope);
506     } else {
507         CHKRV_SCOPE(cb->env, napi_create_array(cb->env, &callResult[1]), CREATE_ARRAY, scope);
508         for (size_t i = 0; i < cb->data.keystrokeAbility.size(); ++i) {
509             napi_value ret = nullptr;
510             napi_value isSupport = nullptr;
511             CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, cb->data.keystrokeAbility[i] ? 1 : 0, &ret),
512                 CREATE_INT32, scope);
513             CHKRV_SCOPE(cb->env, napi_coerce_to_bool(cb->env, ret, &isSupport), COERCE_TO_BOOL, scope);
514             CHKRV_SCOPE(cb->env, napi_set_element(cb->env, callResult[1], static_cast<uint32_t>(i), isSupport),
515                 SET_ELEMENT, scope);
516         }
517         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[0]), GET_UNDEFINED, scope);
518     }
519     napi_value handler = nullptr;
520     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler),
521         GET_REFERENCE, scope);
522     napi_value result = nullptr;
523     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handler, 2, callResult, &result),
524         CALL_FUNCTION, scope);
525     napi_close_handle_scope(cb->env, scope);
526     JsUtil::DeleteCallbackInfo(std::move(cb));
527 }
528 
EmitSupportKeys(int32_t userData,std::vector<bool> & keystrokeAbility)529 void JsEventTarget::EmitSupportKeys(int32_t userData, std::vector<bool> &keystrokeAbility)
530 {
531     CALL_DEBUG_ENTER;
532     std::lock_guard<std::mutex> guard(mutex_);
533     auto iter = callback_.find(userData);
534     if (iter == callback_.end()) {
535         MMI_HILOGE("Failed to search for userData");
536         return;
537     }
538     CHKPV(iter->second);
539     if (iter->second->env == nullptr) {
540         callback_.erase(iter);
541         MMI_HILOGE("The env is nullptr");
542         return;
543     }
544 
545     iter->second->data.keystrokeAbility = keystrokeAbility;
546     iter->second->errCode = RET_OK;
547     uv_loop_s *loop = nullptr;
548     CHKRV(iter->second->env, napi_get_uv_event_loop(iter->second->env, &loop), GET_UV_LOOP);
549     uv_work_t *work = new (std::nothrow) uv_work_t;
550     CHKPV(work);
551     int32_t *uData = new (std::nothrow) int32_t(userData);
552     CHKPV(uData);
553     work->data = static_cast<void*>(uData);
554     int32_t ret;
555     if (iter->second->ref == nullptr) {
556         ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, CallKeystrokeAbilityPromise);
557     } else {
558         ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, CallKeystrokeAbilityAsync);
559     }
560     if (ret != 0) {
561         MMI_HILOGE("uv_queue_work failed");
562         JsUtil::DeletePtr<uv_work_t*>(work);
563         JsUtil::DeletePtr<int32_t*>(uData);
564         return;
565     }
566 }
567 
EmitJsKeyboardType(int32_t userData,int32_t keyboardType)568 void JsEventTarget::EmitJsKeyboardType(int32_t userData, int32_t keyboardType)
569 {
570     CALL_DEBUG_ENTER;
571     std::lock_guard<std::mutex> guard(mutex_);
572     auto iter = callback_.find(userData);
573     if (iter == callback_.end()) {
574         MMI_HILOGE("Failed to search for userData");
575         return;
576     }
577     CHKPV(iter->second);
578     if (iter->second->env == nullptr) {
579         callback_.erase(iter);
580         MMI_HILOGE("The env is nullptr");
581         return;
582     }
583     iter->second->data.keyboardType = keyboardType;
584     iter->second->errCode = RET_OK;
585     uv_loop_s *loop = nullptr;
586     CHKRV(iter->second->env, napi_get_uv_event_loop(iter->second->env, &loop), GET_UV_LOOP);
587 
588     uv_work_t *work = new (std::nothrow) uv_work_t;
589     CHKPV(work);
590     int32_t *uData = new (std::nothrow) int32_t(userData);
591     CHKPV(uData);
592     work->data = static_cast<void*>(uData);
593     int32_t ret = 0;
594     if (iter->second->ref == nullptr) {
595         ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, CallKeyboardTypePromise);
596     } else {
597         ret = uv_queue_work(loop, work, [](uv_work_t *work) {}, CallKeyboardTypeAsync);
598     }
599     if (ret != 0) {
600         MMI_HILOGE("uv_queue_work failed");
601         JsUtil::DeletePtr<uv_work_t*>(work);
602         JsUtil::DeletePtr<int32_t*>(uData);
603         return;
604     }
605 }
606 
CallKeyboardTypeAsync(uv_work_t * work,int32_t status)607 void JsEventTarget::CallKeyboardTypeAsync(uv_work_t *work, int32_t status)
608 {
609     CALL_DEBUG_ENTER;
610     CHKPV(work);
611     if (work->data == nullptr) {
612         JsUtil::DeletePtr<uv_work_t*>(work);
613         MMI_HILOGE("Check data is null");
614         return;
615     }
616     std::unique_ptr<JsUtil::CallbackInfo> cb = GetCallbackInfo(work);
617     CHKPV(cb);
618     CHKPV(cb->env);
619 
620     napi_handle_scope scope = nullptr;
621     napi_open_handle_scope(cb->env, &scope);
622     CHKPV(scope);
623 
624     napi_value callResult[2] = { 0 };
625     if (cb->errCode != RET_OK) {
626         if (cb->errCode == RET_ERR) {
627             napi_close_handle_scope(cb->env, scope);
628             MMI_HILOGE("Other errors");
629             return;
630         }
631         NapiError codeMsg;
632         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
633             napi_close_handle_scope(cb->env, scope);
634             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
635             return;
636         }
637         callResult[0] = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
638         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[1]), GET_UNDEFINED, scope);
639     } else {
640         CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, cb->data.keyboardType, &callResult[1]), CREATE_INT32, scope);
641         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[0]), GET_UNDEFINED, scope);
642     }
643     napi_value handler = nullptr;
644     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE, scope);
645     napi_value result = nullptr;
646     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handler, 2, callResult, &result),
647 	    CALL_FUNCTION, scope);
648     napi_close_handle_scope(cb->env, scope);
649     JsUtil::DeleteCallbackInfo(std::move(cb));
650 }
651 
CallKeyboardTypePromise(uv_work_t * work,int32_t status)652 void JsEventTarget::CallKeyboardTypePromise(uv_work_t *work, int32_t status)
653 {
654     CALL_DEBUG_ENTER;
655     CHKPV(work);
656     if (work->data == nullptr) {
657         JsUtil::DeletePtr<uv_work_t*>(work);
658         MMI_HILOGE("Check data is null");
659         return;
660     }
661     std::unique_ptr<JsUtil::CallbackInfo> cb = GetCallbackInfo(work);
662     CHKPV(cb);
663     CHKPV(cb->env);
664 
665     napi_handle_scope scope = nullptr;
666     napi_open_handle_scope(cb->env, &scope);
667     CHKPV(scope);
668 
669     napi_value callResult;
670     if (cb->errCode != RET_OK) {
671         if (cb->errCode == RET_ERR) {
672             napi_close_handle_scope(cb->env, scope);
673             MMI_HILOGE("Other errors");
674             return;
675         }
676         NapiError codeMsg;
677         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
678             napi_close_handle_scope(cb->env, scope);
679             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
680             return;
681         }
682         callResult = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
683         CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, callResult), REJECT_DEFERRED, scope);
684     } else {
685         CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, cb->data.keyboardType, &callResult), CREATE_INT32, scope);
686         CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, callResult), RESOLVE_DEFERRED, scope);
687     }
688     napi_close_handle_scope(cb->env, scope);
689     JsUtil::DeleteCallbackInfo(std::move(cb));
690 }
691 
CallDevListAsyncWork(uv_work_t * work,int32_t status)692 void JsEventTarget::CallDevListAsyncWork(uv_work_t *work, int32_t status)
693 {
694     CALL_DEBUG_ENTER;
695     CHKPV(work);
696     if (work->data == nullptr) {
697         JsUtil::DeletePtr<uv_work_t*>(work);
698         MMI_HILOGE("Check data is null");
699         return;
700     }
701     std::unique_ptr<JsUtil::CallbackInfo> cb = GetCallbackInfo(work);
702     CHKPV(cb);
703     CHKPV(cb->env);
704     napi_handle_scope scope = nullptr;
705     napi_open_handle_scope(cb->env, &scope);
706     CHKPV(scope);
707 
708     napi_value callResult[2] = { 0 };
709     if (cb->errCode != RET_OK) {
710         if (cb->errCode == RET_ERR) {
711             napi_close_handle_scope(cb->env, scope);
712             MMI_HILOGE("Other errors");
713             return;
714         }
715         NapiError codeMsg;
716         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
717             napi_close_handle_scope(cb->env, scope);
718             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
719             return;
720         }
721         callResult[0] = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
722         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[1]), GET_UNDEFINED, scope);
723     } else {
724         CHKRV_SCOPE(cb->env, napi_create_array(cb->env, &callResult[1]), CREATE_ARRAY, scope);
725         uint32_t index = 0;
726         napi_value value = nullptr;
727         for (const auto &item : cb->data.ids) {
728             CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, item, &value), CREATE_INT32, scope);
729             CHKRV_SCOPE(cb->env, napi_set_element(cb->env, callResult[1], index, value), SET_ELEMENT, scope);
730             ++index;
731         }
732         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[0]), GET_UNDEFINED, scope);
733     }
734     napi_value handler = nullptr;
735     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE, scope);
736     napi_value result = nullptr;
737     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handler, 2, callResult, &result),
738         CALL_FUNCTION, scope);
739     napi_close_handle_scope(cb->env, scope);
740     JsUtil::DeleteCallbackInfo(std::move(cb));
741 }
742 
CallDevListPromiseWork(uv_work_t * work,int32_t status)743 void JsEventTarget::CallDevListPromiseWork(uv_work_t *work, int32_t status)
744 {
745     CALL_DEBUG_ENTER;
746     CHKPV(work);
747     if (work->data == nullptr) {
748         JsUtil::DeletePtr<uv_work_t*>(work);
749         MMI_HILOGE("Check data is null");
750         return;
751     }
752     std::unique_ptr<JsUtil::CallbackInfo> cb = GetCallbackInfo(work);
753     CHKPV(cb);
754     CHKPV(cb->env);
755     napi_handle_scope scope = nullptr;
756     napi_open_handle_scope(cb->env, &scope);
757     CHKPV(scope);
758     napi_value callResult = nullptr;
759     if (cb->errCode != RET_OK) {
760         if (cb->errCode == RET_ERR) {
761             napi_close_handle_scope(cb->env, scope);
762             MMI_HILOGE("Other errors");
763             return;
764         }
765         NapiError codeMsg;
766         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
767             napi_close_handle_scope(cb->env, scope);
768             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
769             return;
770         }
771         callResult = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
772         CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, callResult), REJECT_DEFERRED, scope);
773     } else {
774         CHKRV_SCOPE(cb->env, napi_create_array(cb->env, &callResult), CREATE_ARRAY, scope);
775         uint32_t index = 0;
776         napi_value value = nullptr;
777         for (const auto &item : cb->data.ids) {
778             CHKRV_SCOPE(cb->env, napi_create_int32(cb->env, item, &value), CREATE_INT32, scope);
779             CHKRV_SCOPE(cb->env, napi_set_element(cb->env, callResult, index, value), SET_ELEMENT, scope);
780             ++index;
781         }
782         CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, callResult), RESOLVE_DEFERRED, scope);
783     }
784     napi_close_handle_scope(cb->env, scope);
785     JsUtil::DeleteCallbackInfo(std::move(cb));
786 }
787 
CallDevInfoPromiseWork(uv_work_t * work,int32_t status)788 void JsEventTarget::CallDevInfoPromiseWork(uv_work_t *work, int32_t status)
789 {
790     CALL_DEBUG_ENTER;
791     CHKPV(work);
792     if (work->data == nullptr) {
793         JsUtil::DeletePtr<uv_work_t*>(work);
794         MMI_HILOGE("Check data is null");
795         return;
796     }
797     std::unique_ptr<JsUtil::CallbackInfo> cb = GetCallbackInfo(work);
798     CHKPV(cb);
799     CHKPV(cb->env);
800     napi_handle_scope scope = nullptr;
801     napi_open_handle_scope(cb->env, &scope);
802     CHKPV(scope);
803     napi_value callResult = nullptr;
804     if (cb->errCode != RET_OK) {
805         if (cb->errCode == RET_ERR) {
806             napi_close_handle_scope(cb->env, scope);
807             MMI_HILOGE("Other errors");
808             return;
809         }
810         NapiError codeMsg;
811         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
812             napi_close_handle_scope(cb->env, scope);
813             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
814             return;
815         }
816         callResult = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
817         CHKRV_SCOPE(cb->env, napi_reject_deferred(cb->env, cb->deferred, callResult), REJECT_DEFERRED, scope);
818     } else {
819         callResult = JsUtil::GetDeviceInfo(cb);
820         if (callResult == nullptr) {
821             MMI_HILOGE("Check callResult is null");
822             napi_close_handle_scope(cb->env, scope);
823             return;
824         }
825         CHKRV_SCOPE(cb->env, napi_resolve_deferred(cb->env, cb->deferred, callResult), RESOLVE_DEFERRED, scope);
826     }
827     napi_close_handle_scope(cb->env, scope);
828     JsUtil::DeleteCallbackInfo(std::move(cb));
829 }
830 
CallDevInfoAsyncWork(uv_work_t * work,int32_t status)831 void JsEventTarget::CallDevInfoAsyncWork(uv_work_t *work, int32_t status)
832 {
833     CALL_DEBUG_ENTER;
834     CHKPV(work);
835     if (work->data == nullptr) {
836         JsUtil::DeletePtr<uv_work_t*>(work);
837         MMI_HILOGE("Check data is null");
838         return;
839     }
840     std::unique_ptr<JsUtil::CallbackInfo> cb = GetCallbackInfo(work);
841     CHKPV(cb);
842     CHKPV(cb->env);
843     napi_handle_scope scope = nullptr;
844     napi_open_handle_scope(cb->env, &scope);
845     CHKPV(scope);
846     napi_value callResult[2] = { 0 };
847     if (cb->errCode != RET_OK) {
848         if (cb->errCode == RET_ERR) {
849             napi_close_handle_scope(cb->env, scope);
850             MMI_HILOGE("Other errors");
851             return;
852         }
853         NapiError codeMsg;
854         if (!UtilNapiError::GetApiError(cb->errCode, codeMsg)) {
855             napi_close_handle_scope(cb->env, scope);
856             MMI_HILOGE("Error code %{public}d not found", cb->errCode);
857             return;
858         }
859         callResult[0] = GreateBusinessError(cb->env, cb->errCode, codeMsg.msg);
860         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[1]), GET_UNDEFINED, scope);
861     } else {
862         callResult[1] = JsUtil::GetDeviceInfo(cb);
863         CHKRV_SCOPE(cb->env, napi_get_undefined(cb->env, &callResult[0]), GET_UNDEFINED, scope);
864     }
865     napi_value handler = nullptr;
866     CHKRV_SCOPE(cb->env, napi_get_reference_value(cb->env, cb->ref, &handler), GET_REFERENCE, scope);
867     napi_value result = nullptr;
868     CHKRV_SCOPE(cb->env, napi_call_function(cb->env, nullptr, handler, 2, callResult, &result), CALL_FUNCTION,
869         scope);
870     napi_close_handle_scope(cb->env, scope);
871     JsUtil::DeleteCallbackInfo(std::move(cb));
872 }
873 
AddListener(napi_env env,const std::string & type,napi_value handle)874 void JsEventTarget::AddListener(napi_env env, const std::string &type, napi_value handle)
875 {
876     CALL_DEBUG_ENTER;
877     std::lock_guard<std::mutex> guard(mutex_);
878     auto iter = devListener_.find(type);
879     if (iter == devListener_.end()) {
880         MMI_HILOGE("Find %{public}s failed", type.c_str());
881         return;
882     }
883 
884     for (const auto &temp : iter->second) {
885         CHKPC(temp);
886         if (temp->env != env) {
887             continue;
888         }
889         if (JsUtil::IsSameHandle(env, handle, temp->ref)) {
890             MMI_HILOGW("The handle already exists");
891             return;
892         }
893     }
894     napi_ref ref = nullptr;
895     CHKRV(env, napi_create_reference(env, handle, 1, &ref), CREATE_REFERENCE);
896     auto monitor = std::make_unique<JsUtil::CallbackInfo>();
897     monitor->env = env;
898     monitor->ref = ref;
899     iter->second.push_back(std::move(monitor));
900     if (!isListeningProcess_) {
901         isListeningProcess_ = true;
902         InputMgr->RegisterDevListener("change", shared_from_this());
903     }
904 }
905 
RemoveListener(napi_env env,const std::string & type,napi_value handle)906 void JsEventTarget::RemoveListener(napi_env env, const std::string &type, napi_value handle)
907 {
908     CALL_DEBUG_ENTER;
909     std::lock_guard<std::mutex> guard(mutex_);
910     auto iter = devListener_.find(type);
911     if (iter == devListener_.end()) {
912         MMI_HILOGE("Find %{public}s failed", type.c_str());
913         return;
914     }
915     if (handle == nullptr) {
916         iter->second.clear();
917         goto monitorLabel;
918     }
919     for (auto it = iter->second.begin(); it != iter->second.end(); ++it) {
920         if ((*it)->env != env) {
921             continue;
922         }
923         if (JsUtil::IsSameHandle(env, handle, (*it)->ref)) {
924             MMI_HILOGD("Succeeded in removing monitor");
925             JsUtil::DeleteCallbackInfo(std::move(*it));
926             iter->second.erase(it);
927             goto monitorLabel;
928         }
929     }
930 
931 monitorLabel:
932     if (isListeningProcess_ && iter->second.empty()) {
933         isListeningProcess_ = false;
934         InputMgr->UnregisterDevListener("change", shared_from_this());
935     }
936 }
937 
CreateCallbackInfo(napi_env env,napi_value handle,const int32_t userData,bool isApi9)938 napi_value JsEventTarget::CreateCallbackInfo(napi_env env, napi_value handle, const int32_t userData, bool isApi9)
939 {
940     CALL_DEBUG_ENTER;
941     std::lock_guard<std::mutex> guard(mutex_);
942     auto cb = std::make_unique<JsUtil::CallbackInfo>();
943     cb->env = env;
944     cb->isApi9 = isApi9;
945     napi_value promise = nullptr;
946     if (handle == nullptr) {
947         CHKRP(env, napi_create_promise(env, &cb->deferred, &promise), CREATE_PROMISE);
948     } else {
949         CHKRP(env, napi_create_reference(env, handle, 1, &cb->ref), CREATE_REFERENCE);
950     }
951     callback_.emplace(userData, std::move(cb));
952     return promise;
953 }
954 
GreateBusinessError(napi_env env,int32_t errCode,std::string errMessage)955 napi_value JsEventTarget::GreateBusinessError(napi_env env, int32_t errCode, std::string errMessage)
956 {
957     CALL_DEBUG_ENTER;
958     napi_value result = nullptr;
959     napi_value resultCode = nullptr;
960     napi_value resultMessage = nullptr;
961     CHKRP(env, napi_create_int32(env, errCode, &resultCode), CREATE_INT32);
962     CHKRP(env, napi_create_string_utf8(env, errMessage.data(), NAPI_AUTO_LENGTH, &resultMessage), CREATE_STRING_UTF8);
963     CHKRP(env, napi_create_error(env, nullptr, resultMessage, &result), CREATE_ERROR);
964     CHKRP(env, napi_set_named_property(env, result, ERR_CODE.c_str(), resultCode), SET_NAMED_PROPERTY);
965     return result;
966 }
967 
GetCallbackInfo(uv_work_t * work)968 std::unique_ptr<JsUtil::CallbackInfo> JsEventTarget::GetCallbackInfo(uv_work_t *work)
969 {
970     std::lock_guard<std::mutex> guard(mutex_);
971     int32_t *uData = static_cast<int32_t*>(work->data);
972     int32_t userData = *uData;
973     JsUtil::DeletePtr<uv_work_t*>(work);
974     JsUtil::DeletePtr<int32_t*>(uData);
975 
976     auto iter = callback_.find(userData);
977     if (iter == callback_.end()) {
978         MMI_HILOGE("Find userData failed");
979         return nullptr;
980     }
981     auto cb = std::move(iter->second);
982     callback_.erase(iter);
983     return cb;
984 }
985 
RemoveCallbackInfo(napi_env env,napi_value handle,int32_t userData)986 void JsEventTarget::RemoveCallbackInfo(napi_env env, napi_value handle, int32_t userData)
987 {
988     CALL_DEBUG_ENTER;
989     std::lock_guard<std::mutex> guard(mutex_);
990     auto iter = callback_.find(userData);
991     if (iter != callback_.end()) {
992         auto cb = std::move(iter->second);
993         JsUtil::DeleteCallbackInfo(std::move(cb));
994         callback_.erase(iter);
995     }
996 }
997 
ResetEnv()998 void JsEventTarget::ResetEnv()
999 {
1000     CALL_DEBUG_ENTER;
1001     std::lock_guard<std::mutex> guard(mutex_);
1002     callback_.clear();
1003     devListener_.clear();
1004     InputMgr->UnregisterDevListener("change", shared_from_this());
1005 }
1006 } // namespace MMI
1007 } // namespace OHOS