• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 "input_manager.h"
17 #include "js_register_util.h"
18 #include "napi_constants.h"
19 #include "util_napi_error.h"
20 
21 #undef MMI_LOG_TAG
22 #define MMI_LOG_TAG "JSRegisterModule"
23 
24 namespace OHOS {
25 namespace MMI {
26 namespace {
27 constexpr size_t EVENT_NAME_LEN { 64 };
28 constexpr size_t PRE_KEYS_SIZE { 4 };
29 constexpr size_t AT_LEAST_ONE_PARAMETER { 1 };
30 constexpr size_t INPUT_PARAMETER_MIDDLE { 2 };
31 constexpr size_t INPUT_PARAMETER_MAX { 3 };
32 constexpr size_t KEY_MONITOR_EXPECT_N_PARAMS { 3 };
33 constexpr size_t FIRST_PARAMETER { 0 };
34 constexpr size_t SECOND_PARAMETER { 1 };
35 constexpr size_t THIRD_PARAMETER { 2 };
36 constexpr int32_t OCCUPIED_BY_SYSTEM { -3 };
37 constexpr int32_t OCCUPIED_BY_OTHER { -4 };
38 constexpr int32_t BOOLEAN_TRUE { 1 };
39 constexpr int32_t BOOLEAN_FALSE { 0 };
40 constexpr int32_t BOOLEAN_NONE { -1 };
41 constexpr uint32_t DEFAULT_REFERENCE_COUNT { 1 };
42 } // namespace
43 
44 static Callbacks callbacks = {};
45 static Callbacks hotkeyCallbacks = {};
46 std::mutex sCallBacksMutex;
47 static const std::vector<int32_t> pressKeyCodes = {
48     KeyEvent::KEYCODE_ALT_LEFT,
49     KeyEvent::KEYCODE_ALT_RIGHT,
50     KeyEvent::KEYCODE_SHIFT_LEFT,
51     KeyEvent::KEYCODE_SHIFT_RIGHT,
52     KeyEvent::KEYCODE_CTRL_LEFT,
53     KeyEvent::KEYCODE_CTRL_RIGHT
54 };
55 static const std::vector<int32_t> finalKeyCodes = {
56     KeyEvent::KEYCODE_ALT_LEFT,
57     KeyEvent::KEYCODE_ALT_RIGHT,
58     KeyEvent::KEYCODE_SHIFT_LEFT,
59     KeyEvent::KEYCODE_SHIFT_RIGHT,
60     KeyEvent::KEYCODE_CTRL_LEFT,
61     KeyEvent::KEYCODE_CTRL_RIGHT,
62     KeyEvent::KEYCODE_META_LEFT,
63     KeyEvent::KEYCODE_META_RIGHT
64 };
TypeOf(napi_env env,napi_value value,napi_valuetype type)65 bool JsCommon::TypeOf(napi_env env, napi_value value, napi_valuetype type)
66 {
67     napi_valuetype valueType = napi_undefined;
68     CHKRF(napi_typeof(env, value, &valueType), TYPEOF);
69     if (valueType != type) {
70         return false;
71     }
72     return true;
73 }
74 
ThrowError(napi_env env,int32_t code)75 void JsCommon::ThrowError(napi_env env, int32_t code)
76 {
77     int32_t errorCode = std::abs(code);
78     if (errorCode == COMMON_USE_SYSAPI_ERROR) {
79         MMI_HILOGE("Non system applications use system API");
80         THROWERR_CUSTOM(env, COMMON_USE_SYSAPI_ERROR, "Non system applications use system API");
81     } else if (errorCode == COMMON_PERMISSION_CHECK_ERROR) {
82         MMI_HILOGE("Shield api need ohos.permission.INPUT_CONTROL_DISPATCHING");
83         THROWERR_API9(env, COMMON_PERMISSION_CHECK_ERROR, "shiled API", "ohos.permission.INPUT_CONTROL_DISPATCHING");
84     } else {
85         MMI_HILOGE("Dispatch control failed");
86     }
87 }
88 
GetHotkeyEventInfo(napi_env env,napi_callback_info info,sptr<KeyEventMonitorInfo> event,std::shared_ptr<KeyOption> keyOption)89 napi_value GetHotkeyEventInfo(napi_env env, napi_callback_info info, sptr<KeyEventMonitorInfo> event,
90     std::shared_ptr<KeyOption> keyOption)
91 {
92     CALL_DEBUG_ENTER;
93     CHKPP(event);
94     CHKPP(keyOption);
95     size_t argc = 3;
96     napi_value argv[3] = { 0 };
97     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
98     napi_value receiveValue = nullptr;
99     CHKRP(napi_get_named_property(env, argv[1], "preKeys", &receiveValue), GET_NAMED_PROPERTY);
100     if (receiveValue == nullptr) {
101         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "PreKeys not found");
102         return nullptr;
103     }
104     std::set<int32_t> preKeys;
105     if (GetPreKeys(env, receiveValue, preKeys) == nullptr) {
106         MMI_HILOGE("Get preKeys failed");
107         return nullptr;
108     }
109     if (preKeys.size() > PRE_KEYS_SIZE) {
110         MMI_HILOGE("PreKeys size invalid");
111         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "PreKeys size invalid");
112         return nullptr;
113     }
114     MMI_HILOGD("PreKeys size:%{public}zu", preKeys.size());
115     keyOption->SetPreKeys(preKeys);
116     std::string subKeyNames = "";
117     for (const auto &item : preKeys) {
118         auto it = std::find(pressKeyCodes.begin(), pressKeyCodes.end(), item);
119         if (it == pressKeyCodes.end()) {
120             MMI_HILOGE("PreKeys is not expect");
121             THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "PreKeys size invalid");
122             return nullptr;
123         }
124         subKeyNames += std::to_string(item);
125         subKeyNames += ",";
126         MMI_HILOGD("PreKeys:%{private}d", item);
127     }
128     std::optional<int32_t> finalKeyOption = GetNamedPropertyInt32(env, argv[1], "finalKey");
129     if (!finalKeyOption) {
130         MMI_HILOGE("GetNamedPropertyInt32 failed");
131         return nullptr;
132     }
133     int32_t finalKey = finalKeyOption.value();
134     if (finalKey < 0) {
135         MMI_HILOGE("FinalKey:%{private}d is less 0, can not process", finalKey);
136         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "FinalKey must be greater than or equal to 0");
137         return nullptr;
138     }
139     auto it = std::find(finalKeyCodes.begin(), finalKeyCodes.end(), finalKey);
140     if (it != finalKeyCodes.end()) {
141         MMI_HILOGE("FinalKey is not expect");
142         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "FinalKey is not expect");
143         return nullptr;
144     }
145     subKeyNames += std::to_string(finalKey);
146     subKeyNames += ",";
147     keyOption->SetFinalKey(finalKey);
148     MMI_HILOGD("FinalKey:%{private}d", finalKey);
149 
150     bool isFinalKeyDown = true;
151     subKeyNames += std::to_string(isFinalKeyDown);
152     subKeyNames += ",";
153     keyOption->SetFinalKeyDown(isFinalKeyDown);
154     MMI_HILOGD("IsFinalKeyDown:%{private}d,", (isFinalKeyDown == true ? 1 : 0));
155 
156     int32_t finalKeyDownDuration = 0;
157     subKeyNames += std::to_string(finalKeyDownDuration);
158     subKeyNames += ",";
159     keyOption->SetFinalKeyDownDuration(finalKeyDownDuration);
160 
161     bool isRepeat = true;
162     if (!GetNamedPropertyBool(env, argv[1], "isRepeat", isRepeat)) {
163         MMI_HILOGD("IsRepeat field is default");
164     }
165     subKeyNames += std::to_string(isRepeat);
166     keyOption->SetRepeat(isRepeat);
167     MMI_HILOGD("IsRepeat:%{public}s", (isRepeat ? "true" : "false"));
168     event->eventType = subKeyNames;
169 
170     napi_value ret;
171     CHKRP(napi_create_int32(env, RET_OK, &ret), CREATE_INT32);
172     return ret;
173 }
174 
GetEventInfoAPI9(napi_env env,napi_callback_info info,sptr<KeyEventMonitorInfo> event,std::shared_ptr<KeyOption> keyOption)175 napi_value GetEventInfoAPI9(napi_env env, napi_callback_info info, sptr<KeyEventMonitorInfo> event,
176     std::shared_ptr<KeyOption> keyOption)
177 {
178     CALL_DEBUG_ENTER;
179     CHKPP(event);
180     CHKPP(keyOption);
181     size_t argc = 3;
182     napi_value argv[3] = { 0 };
183     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
184     napi_value receiveValue = nullptr;
185     CHKRP(napi_get_named_property(env, argv[1], "preKeys", &receiveValue), GET_NAMED_PROPERTY);
186     if (receiveValue == nullptr) {
187         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "preKeys not found");
188         return nullptr;
189     }
190     std::set<int32_t> preKeys;
191     if (GetPreKeys(env, receiveValue, preKeys) == nullptr) {
192         MMI_HILOGE("Get preKeys failed");
193         return nullptr;
194     }
195     if (preKeys.size() > PRE_KEYS_SIZE) {
196         MMI_HILOGE("PreKeys size invalid");
197         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "preKeys size invalid");
198         return nullptr;
199     }
200     MMI_HILOGD("PreKeys size:%{public}zu", preKeys.size());
201     keyOption->SetPreKeys(preKeys);
202     std::string subKeyNames = "";
203     for (const auto &item : preKeys) {
204         subKeyNames += std::to_string(item);
205         subKeyNames += ",";
206         MMI_HILOGD("preKeys:%{private}d", item);
207     }
208     std::optional<int32_t> tempFinalKey = GetNamedPropertyInt32(env, argv[1], "finalKey");
209     if (!tempFinalKey) {
210         MMI_HILOGE("GetNamedPropertyInt32 failed");
211         return nullptr;
212     }
213     int32_t finalKey = tempFinalKey.value();
214     if (finalKey < 0) {
215         MMI_HILOGE("finalKey:%{private}d is less 0, can not process", finalKey);
216         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "finalKey must be greater than or equal to 0");
217         return nullptr;
218     }
219     subKeyNames += std::to_string(finalKey);
220     subKeyNames += ",";
221     keyOption->SetFinalKey(finalKey);
222     MMI_HILOGD("FinalKey:%{private}d", finalKey);
223     bool isFinalKeyDown;
224     if (!GetNamedPropertyBool(env, argv[1], "isFinalKeyDown", isFinalKeyDown)) {
225         MMI_HILOGE("GetNamedPropertyBool failed");
226         return nullptr;
227     }
228     subKeyNames += std::to_string(isFinalKeyDown);
229     subKeyNames += ",";
230     keyOption->SetFinalKeyDown(isFinalKeyDown);
231     MMI_HILOGD("IsFinalKeyDown:%{private}d,map_key:%{private}s",
232         (isFinalKeyDown == true ? 1 : 0), subKeyNames.c_str());
233     std::optional<int32_t> tempKeyDownDuration = GetNamedPropertyInt32(env, argv[1], "finalKeyDownDuration");
234     if (!tempKeyDownDuration) {
235         MMI_HILOGE("GetNamedPropertyInt32 failed");
236         return nullptr;
237     }
238     int32_t finalKeyDownDuration = tempKeyDownDuration.value();
239     if (finalKeyDownDuration < 0) {
240         MMI_HILOGE("finalKeyDownDuration:%{public}d is less 0, can not process", finalKeyDownDuration);
241         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "finalKeyDownDuration must be greater than or equal to 0");
242         return nullptr;
243     }
244     subKeyNames += std::to_string(finalKeyDownDuration);
245     subKeyNames += ",";
246     keyOption->SetFinalKeyDownDuration(finalKeyDownDuration);
247     MMI_HILOGD("FinalKeyDownDuration:%{public}d", finalKeyDownDuration);
248     bool isRepeat = true;
249     if (!GetNamedPropertyBool(env, argv[1], "isRepeat", isRepeat)) {
250         MMI_HILOGD("IsRepeat field is default");
251     }
252     subKeyNames += std::to_string(isRepeat);
253     keyOption->SetRepeat(isRepeat);
254     MMI_HILOGD("IsRepeat:%{public}s", (isRepeat ? "true" : "false"));
255     event->eventType = subKeyNames;
256     napi_value ret;
257     CHKRP(napi_create_int32(env, RET_OK, &ret), CREATE_INT32);
258     return ret;
259 }
260 
IsMatchKeyAction(bool isFinalKeydown,int32_t keyAction)261 static bool IsMatchKeyAction(bool isFinalKeydown, int32_t keyAction)
262 {
263     CALL_DEBUG_ENTER;
264     MMI_HILOGD("isFinalKeydown:%{public}d, keyAction:%{public}d", isFinalKeydown, keyAction);
265     if (isFinalKeydown && keyAction == KeyEvent::KEY_ACTION_DOWN) {
266         return true;
267     }
268     if (!isFinalKeydown && keyAction == KeyEvent::KEY_ACTION_UP) {
269         return true;
270     }
271     MMI_HILOGE("isFinalKeydown not matched with keyAction");
272     return false;
273 }
274 
MatchCombinationKeys(sptr<KeyEventMonitorInfo> monitorInfo,std::shared_ptr<KeyEvent> keyEvent)275 static bool MatchCombinationKeys(sptr<KeyEventMonitorInfo> monitorInfo, std::shared_ptr<KeyEvent> keyEvent)
276 {
277     CALL_DEBUG_ENTER;
278     CHKPF(monitorInfo);
279     CHKPF(keyEvent);
280     auto keyOption = monitorInfo->keyOption;
281     CHKPF(keyOption);
282     std::vector<KeyEvent::KeyItem> items = keyEvent->GetKeyItems();
283     int32_t infoFinalKey = keyOption->GetFinalKey();
284     int32_t keyEventFinalKey = keyEvent->GetKeyCode();
285     bool isFinalKeydown = keyOption->IsFinalKeyDown();
286     MMI_HILOGD("InfoFinalKey:%{private}d,keyEventFinalKey:%{private}d", infoFinalKey, keyEventFinalKey);
287     if (infoFinalKey != keyEventFinalKey || items.size() > PRE_KEYS_SIZE ||
288         !IsMatchKeyAction(isFinalKeydown, keyEvent->GetKeyAction())) {
289         MMI_HILOGD("key Param invalid");
290         return false;
291     }
292     std::set<int32_t> infoPreKeys = keyOption->GetPreKeys();
293     int32_t infoSize = 0;
294     for (auto it = infoPreKeys.begin(); it != infoPreKeys.end(); ++it) {
295         if (*it >= 0) {
296             infoSize++;
297         }
298     }
299     int32_t count = 0;
300     for (const auto &item : items) {
301         if (item.GetKeyCode() == keyEventFinalKey) {
302             continue;
303         }
304         auto iter = find(infoPreKeys.begin(), infoPreKeys.end(), item.GetKeyCode());
305         if (iter == infoPreKeys.end()) {
306             MMI_HILOGW("No keyCode in preKeys");
307             return false;
308         }
309         count++;
310     }
311     MMI_HILOGD("kevEventSize:%{public}d, infoSize:%{public}d", count, infoSize);
312     std::optional<KeyEvent::KeyItem> keyItem = keyEvent->GetKeyItem();
313     if (!keyItem) {
314         MMI_HILOGE("The keyItem is nullopt");
315         return false;
316     }
317     auto downTime = keyItem->GetDownTime();
318     auto upTime = keyEvent->GetActionTime();
319     auto curDurationTime = keyOption->GetFinalKeyDownDuration();
320     if (curDurationTime > 0 && (upTime - downTime >= (static_cast<int64_t>(curDurationTime) * 1000))) {
321         MMI_HILOGE("Skip, upTime - downTime >= duration");
322         return false;
323     }
324     return count == infoSize;
325 }
326 
SubKeyEventCallback(std::shared_ptr<KeyEvent> keyEvent,const std::string & keyOptionKey)327 static void SubKeyEventCallback(std::shared_ptr<KeyEvent> keyEvent, const std::string& keyOptionKey)
328 {
329     CALL_DEBUG_ENTER;
330     CHKPV(keyEvent);
331     std::lock_guard guard(sCallBacksMutex);
332     auto iter = callbacks.find(keyOptionKey);
333     if (iter != callbacks.end()) {
334         auto &list = iter->second;
335         MMI_HILOGD("list size:%{public}zu", list.size());
336         for (auto monitorInfo : list) {
337             if (MatchCombinationKeys(monitorInfo, keyEvent)) {
338                 EmitAsyncCallbackWork(monitorInfo);
339             }
340         }
341     } else {
342         MMI_HILOGE("No Matches found for SubKeyEventCallback");
343     }
344 }
345 
SubHotkeyEventCallback(std::shared_ptr<KeyEvent> keyEvent)346 static void SubHotkeyEventCallback(std::shared_ptr<KeyEvent> keyEvent)
347 {
348     CALL_DEBUG_ENTER;
349     CHKPV(keyEvent);
350     std::lock_guard guard(sCallBacksMutex);
351     auto iter = hotkeyCallbacks.begin();
352     while (iter != hotkeyCallbacks.end()) {
353         auto &list = iter->second;
354         ++iter;
355         MMI_HILOGD("Callback list size:%{public}zu", list.size());
356         auto infoIter = list.begin();
357         while (infoIter != list.end()) {
358             auto monitorInfo = *infoIter;
359             if (MatchCombinationKeys(monitorInfo, keyEvent)) {
360                 EmitAsyncCallbackWork(monitorInfo);
361             }
362             ++infoIter;
363         }
364     }
365 }
366 
GenerateKeyOptionKey(const std::shared_ptr<KeyOption> & keyOption)367 std::string GenerateKeyOptionKey(const std::shared_ptr<KeyOption>& keyOption)
368 {
369     std::string subKeyNames;
370     const std::set<int32_t>& preKeys = keyOption->GetPreKeys();
371     int32_t finalKey = keyOption->GetFinalKey();
372     bool isFinalKeyDown = keyOption->IsFinalKeyDown();
373     int32_t finalKeyDownDuration = keyOption->GetFinalKeyDownDuration();
374     bool isRepeat = keyOption->IsRepeat();
375     for (const auto& key : preKeys) {
376         subKeyNames.append(std::to_string(key)).append(",");
377     }
378     subKeyNames.append(std::to_string(finalKey)).append(",");
379     subKeyNames.append(std::to_string(isFinalKeyDown)).append(",");
380     subKeyNames.append(std::to_string(finalKeyDownDuration)).append(",");
381     subKeyNames.append(std::to_string(isRepeat));
382     return subKeyNames;
383 }
384 
SubscribeKey(napi_env env,napi_callback_info info,sptr<KeyEventMonitorInfo> event,std::shared_ptr<KeyOption> keyOption)385 napi_value SubscribeKey(napi_env env, napi_callback_info info, sptr<KeyEventMonitorInfo> event,
386     std::shared_ptr<KeyOption> keyOption)
387 {
388     CALL_DEBUG_ENTER;
389     CHKPP(event);
390     CHKPP(keyOption);
391     if (GetEventInfoAPI9(env, info, event, keyOption) == nullptr) {
392         MMI_HILOGE("GetEventInfoAPI9 failed");
393         return nullptr;
394     }
395     event->keyOption = keyOption;
396     int32_t preSubscribeId = GetPreSubscribeId(callbacks, event);
397     if (preSubscribeId < 0) {
398         MMI_HILOGD("EventType:%{private}s, eventName:%{public}s", event->eventType.c_str(), event->name.c_str());
399         int32_t subscribeId = -1;
400         subscribeId = InputManager::GetInstance()->SubscribeKeyEvent(keyOption,
401             [keyOption](std::shared_ptr<KeyEvent> keyEvent) {
402                 std::string keyOptionKey = GenerateKeyOptionKey(keyOption);
403                 SubKeyEventCallback(keyEvent, keyOptionKey);
404             });
405         if (subscribeId < 0) {
406             MMI_HILOGE("SubscribeId invalid:%{public}d", subscribeId);
407             return nullptr;
408         }
409         MMI_HILOGD("SubscribeId:%{public}d", subscribeId);
410         event->subscribeId = subscribeId;
411     } else {
412         event->subscribeId = preSubscribeId;
413     }
414     if (AddEventCallback(env, callbacks, event) < 0) {
415         MMI_HILOGE("AddEventCallback failed");
416         return nullptr;
417     }
418     napi_value ret;
419     CHKRP(napi_create_int32(env, RET_OK, &ret), CREATE_INT32);
420     return ret;
421 }
422 
SubscribeHotkey(napi_env env,napi_callback_info info,sptr<KeyEventMonitorInfo> event,std::shared_ptr<KeyOption> keyOption)423 napi_value SubscribeHotkey(napi_env env, napi_callback_info info, sptr<KeyEventMonitorInfo> event,
424     std::shared_ptr<KeyOption> keyOption)
425 {
426     CALL_DEBUG_ENTER;
427     CHKPP(event);
428     CHKPP(keyOption);
429     if (GetHotkeyEventInfo(env, info, event, keyOption) == nullptr) {
430         MMI_HILOGE("GetHotkeyEventInfo failed");
431         return nullptr;
432     }
433     event->keyOption = keyOption;
434     int32_t preSubscribeId = GetPreSubscribeId(hotkeyCallbacks, event);
435     if (preSubscribeId < 0) {
436         MMI_HILOGD("EventType:%{private}s, eventName:%{public}s", event->eventType.c_str(), event->name.c_str());
437         int32_t subscribeId = -1;
438         subscribeId = InputManager::GetInstance()->SubscribeHotkey(keyOption, SubHotkeyEventCallback);
439         if (subscribeId == ERROR_UNSUPPORT) {
440             MMI_HILOGE("SubscribeId invalid:%{public}d", subscribeId);
441             THROWERR_CUSTOM(env, INPUT_DEVICE_NOT_SUPPORTED, "Hotkey occupied by other");
442             return nullptr;
443         }
444         if (subscribeId == OCCUPIED_BY_SYSTEM) {
445             MMI_HILOGE("SubscribeId invalid:%{public}d", subscribeId);
446             THROWERR_CUSTOM(env, INPUT_OCCUPIED_BY_SYSTEM, "Hotkey occupied by system");
447             return nullptr;
448         }
449         if (subscribeId == OCCUPIED_BY_OTHER) {
450             MMI_HILOGE("SubscribeId invalid:%{public}d", subscribeId);
451             THROWERR_CUSTOM(env, INPUT_OCCUPIED_BY_OTHER, "Hotkey occupied by other");
452             return nullptr;
453         }
454         MMI_HILOGD("SubscribeId:%{public}d", subscribeId);
455         event->subscribeId = subscribeId;
456     } else {
457         event->subscribeId = preSubscribeId;
458     }
459     if (AddEventCallback(env, hotkeyCallbacks, event) < 0) {
460         MMI_HILOGE("AddEventCallback failed");
461         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "AddEventCallback failed");
462         return nullptr;
463     }
464     napi_value ret;
465     CHKRP(napi_create_int32(env, RET_OK, &ret), CREATE_INT32);
466     return ret;
467 }
468 
GetEventType(napi_env env,napi_callback_info info,sptr<KeyEventMonitorInfo> event,std::string & keyType)469 bool GetEventType(napi_env env, napi_callback_info info, sptr<KeyEventMonitorInfo> event, std::string &keyType)
470 {
471     CALL_DEBUG_ENTER;
472     size_t argc = 3;
473     napi_value argv[3] = { 0 };
474     CHKRF(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
475     if (argc < INPUT_PARAMETER_MIDDLE) {
476         MMI_HILOGE("Parameter number error argc:%{public}zu", argc);
477         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "parameter number error");
478         return false;
479     }
480     if (!UtilNapi::TypeOf(env, argv[0], napi_string)) {
481         MMI_HILOGE("The first parameter is not string");
482         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "type", "string");
483         return false;
484     }
485     if (!UtilNapi::TypeOf(env, argv[1], napi_object)) {
486         MMI_HILOGE("The second parameter is not napi_object");
487         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "keyOptions", "object");
488         return false;
489     }
490     if (argc == INPUT_PARAMETER_MAX) {
491         napi_valuetype valueType = napi_undefined;
492         CHKRF(napi_typeof(env, argv[INPUT_PARAMETER_MIDDLE], &valueType), TYPEOF);
493         if (valueType != napi_function) {
494             MMI_HILOGE("The third parameter is not napi_function");
495             THROWERR_API9(env, COMMON_PARAMETER_ERROR, "callback", "function");
496             return false;
497         }
498         CHKRF(napi_create_reference(env, argv[INPUT_PARAMETER_MIDDLE], 1, &event->callback), REFERENCE_REF);
499     } else {
500         event->callback = nullptr;
501     }
502 
503     char eventType[EVENT_NAME_LEN] = { 0 };
504     size_t typeLen = 0;
505     CHKRF(napi_get_value_string_utf8(env, argv[0], eventType, EVENT_NAME_LEN - 1, &typeLen), GET_VALUE_STRING_UTF8);
506     keyType = eventType;
507     if (keyType != SUBSCRIBE_TYPE && keyType != HOTKEY_SUBSCRIBE_TYPE) {
508         MMI_HILOGE("Type is not key or hotkey");
509         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Type must be key or hotkeyChange");
510         return false;
511     }
512     return true;
513 }
514 
ResolveEventType(napi_env env,napi_callback_info info)515 static std::optional<std::string> ResolveEventType(napi_env env, napi_callback_info info)
516 {
517     CALL_DEBUG_ENTER;
518     size_t argc { KEY_MONITOR_EXPECT_N_PARAMS };
519     napi_value argv[KEY_MONITOR_EXPECT_N_PARAMS] {};
520 
521     auto ret = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
522     if (ret != napi_ok) {
523         MMI_HILOGE("napi_get_cb_info fail");
524         THROWERR_CUSTOM(env, OTHER_ERROR, "Operation fail");
525         return std::nullopt;
526     }
527     if (argc < AT_LEAST_ONE_PARAMETER) {
528         MMI_HILOGE("Type of subscription is required");
529         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Type of subscription is required");
530         return std::nullopt;
531     }
532     if (!UtilNapi::TypeOf(env, argv[FIRST_PARAMETER], napi_string)) {
533         MMI_HILOGE("The first parameter is not string");
534         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "type", "string");
535         return std::nullopt;
536     }
537     char eventType[EVENT_NAME_LEN] {};
538     size_t typeLen { 0 };
539 
540     ret = napi_get_value_string_utf8(env, argv[0], eventType, sizeof(eventType), &typeLen);
541     if (ret != napi_ok) {
542         MMI_HILOGE("napi_get_value_string_utf8 fail");
543         THROWERR_CUSTOM(env, OTHER_ERROR, "Operation fail");
544         return std::nullopt;
545     }
546     return std::string(eventType);
547 }
548 
JsOn(napi_env env,napi_callback_info info)549 static napi_value JsOn(napi_env env, napi_callback_info info)
550 {
551     CALL_DEBUG_ENTER;
552     auto etOpt = ResolveEventType(env, info);
553     if (!etOpt) {
554         MMI_HILOGE("ResolveEventType fail");
555         return nullptr;
556     }
557     if (*etOpt == KEY_MONITOR_SUBSCRIBE_TYPE) {
558         JsInputConsumer::GetInstance()->SubscribeKeyMonitor(env, info);
559         return nullptr;
560     }
561     sptr<KeyEventMonitorInfo> event = new (std::nothrow) KeyEventMonitorInfo();
562     CHKPP(event);
563     event->env = env;
564     auto keyOption = std::make_shared<KeyOption>();
565     std::string keyType;
566     size_t argc = 3;
567     napi_value argv[3] = { 0 };
568     if (napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr) != napi_ok) {
569         MMI_HILOGE("GET_CB_INFO failed");
570         return nullptr;
571     }
572     if (argc < INPUT_PARAMETER_MAX) {
573         MMI_HILOGE("Parameter number error argc:%{public}zu", argc);
574         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "parameter number error");
575         return nullptr;
576     }
577     if (!GetEventType(env, info, event, keyType)) {
578         MMI_HILOGE("GetEventType fail, type must be key or hotkeyChange");
579         return nullptr;
580     }
581     event->name = keyType;
582     if (keyType == HOTKEY_SUBSCRIBE_TYPE) {
583         if (SubscribeHotkey(env, info, event, keyOption) == nullptr) {
584             MMI_HILOGE("SubscribeHotkey failed");
585             return nullptr;
586         }
587     } else {
588         if (SubscribeKey(env, info, event, keyOption) == nullptr) {
589             MMI_HILOGE("SubscribeKey failed");
590             return nullptr;
591         }
592     }
593     return nullptr;
594 }
595 
JsOff(napi_env env,napi_callback_info info)596 static napi_value JsOff(napi_env env, napi_callback_info info)
597 {
598     CALL_DEBUG_ENTER;
599     auto etOpt = ResolveEventType(env, info);
600     if (!etOpt) {
601         MMI_HILOGE("ResolveEventType fail");
602         return nullptr;
603     }
604     if (*etOpt == KEY_MONITOR_SUBSCRIBE_TYPE) {
605         JsInputConsumer::GetInstance()->UnsubscribeKeyMonitor(env, info);
606         return nullptr;
607     }
608     sptr<KeyEventMonitorInfo> event = new (std::nothrow) KeyEventMonitorInfo();
609     CHKPP(event);
610     event->env = env;
611     auto keyOption = std::make_shared<KeyOption>();
612     std::string keyType;
613     if (!GetEventType(env, info, event, keyType)) {
614         MMI_HILOGE("GetEventType fail, type must be key or hotkeyChange");
615         return nullptr;
616     }
617     event->name = keyType;
618     int32_t subscribeId = -1;
619     if (keyType == HOTKEY_SUBSCRIBE_TYPE) {
620         if (GetHotkeyEventInfo(env, info, event, keyOption) == nullptr) {
621             MMI_HILOGE("GetHotkeyEventInfo failed");
622             return nullptr;
623         }
624         if (DelEventCallback(env, hotkeyCallbacks, event, subscribeId) < 0) {
625             MMI_HILOGE("DelEventCallback failed");
626             return nullptr;
627         }
628         MMI_HILOGI("Unsubscribe hot key(%{public}d)", subscribeId);
629         InputManager::GetInstance()->UnsubscribeHotkey(subscribeId);
630     } else {
631         if (GetEventInfoAPI9(env, info, event, keyOption) == nullptr) {
632             MMI_HILOGE("GetEventInfoAPI9 failed");
633             return nullptr;
634         }
635         if (DelEventCallback(env, callbacks, event, subscribeId) < 0) {
636             MMI_HILOGE("DelEventCallback failed");
637             return nullptr;
638         }
639         MMI_HILOGI("Unsubscribe key event(%{public}d)", subscribeId);
640         InputManager::GetInstance()->UnsubscribeKeyEvent(subscribeId);
641     }
642     return nullptr;
643 }
644 
SetShieldStatus(napi_env env,napi_callback_info info)645 static napi_value SetShieldStatus(napi_env env, napi_callback_info info)
646 {
647     CALL_DEBUG_ENTER;
648     size_t argc = 2;
649     napi_value argv[2] = { 0 };
650     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
651     if (argc < INPUT_PARAMETER_MIDDLE) {
652         MMI_HILOGE("At least two parameters is required");
653         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "shieldMode", "number");
654         return nullptr;
655     }
656     if (!JsCommon::TypeOf(env, argv[0], napi_number)) {
657         MMI_HILOGE("shieldMode parameter type is invalid");
658         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "shieldMode", "number");
659         return nullptr;
660     }
661     int32_t shieldMode = 0;
662     CHKRP(napi_get_value_int32(env, argv[0], &shieldMode), GET_VALUE_INT32);
663     if (shieldMode < FACTORY_MODE || shieldMode > OOBE_MODE) {
664         MMI_HILOGE("Undefined shield mode");
665         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Shield mode does not exist");
666         return nullptr;
667     }
668 
669     if (!JsCommon::TypeOf(env, argv[1], napi_boolean)) {
670         MMI_HILOGE("isShield parameter type is invalid");
671         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "isShield", "boolean");
672         return nullptr;
673     }
674     bool isShield = true;
675     CHKRP(napi_get_value_bool(env, argv[1], &isShield), GET_VALUE_BOOL);
676 
677     int32_t errCode = InputManager::GetInstance()->SetShieldStatus(shieldMode, isShield);
678     JsCommon::ThrowError(env, errCode);
679     napi_value result = nullptr;
680     if (napi_get_undefined(env, &result) != napi_ok) {
681         MMI_HILOGE("Get undefined result is failed");
682         return nullptr;
683     }
684     return result;
685 }
686 
GetShieldStatus(napi_env env,napi_callback_info info)687 static napi_value GetShieldStatus(napi_env env, napi_callback_info info)
688 {
689     CALL_DEBUG_ENTER;
690     size_t argc = 1;
691     napi_value argv[1] = { 0 };
692     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
693     if (argc < 1) {
694         MMI_HILOGE("At least 1 parameter is required");
695         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "shieldMode", "number");
696         return nullptr;
697     }
698     if (!JsCommon::TypeOf(env, argv[0], napi_number)) {
699         MMI_HILOGE("shieldMode parameter type is invalid");
700         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "shieldMode", "number");
701         return nullptr;
702     }
703     int32_t shieldMode = 0;
704     CHKRP(napi_get_value_int32(env, argv[0], &shieldMode), GET_VALUE_INT32);
705     if (shieldMode < FACTORY_MODE || shieldMode > OOBE_MODE) {
706         MMI_HILOGE("Undefined shield mode");
707         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Shield mode does not exist");
708         return nullptr;
709     }
710     bool isShield { false };
711     auto errCode = InputManager::GetInstance()->GetShieldStatus(shieldMode, isShield);
712     JsCommon::ThrowError(env, errCode);
713     napi_value result = nullptr;
714     NAPI_CALL(env, napi_get_boolean(env, isShield, &result));
715     return result;
716 }
717 
GetAllSystemHotkeys(napi_env env,napi_callback_info info)718 static napi_value GetAllSystemHotkeys(napi_env env, napi_callback_info info)
719 {
720     CALL_DEBUG_ENTER;
721     return GetSystemHotkey(env);
722 }
723 
EnumConstructor(napi_env env,napi_callback_info info)724 static napi_value EnumConstructor(napi_env env, napi_callback_info info)
725 {
726     CALL_DEBUG_ENTER;
727     size_t argc = 0;
728     napi_value args[1] = { 0 };
729     napi_value ret = nullptr;
730     void *data = nullptr;
731     CHKRP(napi_get_cb_info(env, info, &argc, args, &ret, &data), GET_CB_INFO);
732     return ret;
733 }
734 
CreateShieldMode(napi_env env,napi_value exports)735 static napi_value CreateShieldMode(napi_env env, napi_value exports)
736 {
737     CALL_DEBUG_ENTER;
738     napi_value factory_mode = nullptr;
739     CHKRP(napi_create_int32(env, SHIELD_MODE::FACTORY_MODE, &factory_mode), CREATE_INT32);
740     napi_value oobe_mode = nullptr;
741     CHKRP(napi_create_int32(env, SHIELD_MODE::OOBE_MODE, &oobe_mode), CREATE_INT32);
742 
743     napi_property_descriptor desc[] = {
744         DECLARE_NAPI_STATIC_PROPERTY("FACTORY_MODE", factory_mode),
745         DECLARE_NAPI_STATIC_PROPERTY("OOBE_MODE", oobe_mode),
746     };
747     napi_value result = nullptr;
748     CHKRP(napi_define_class(env, "ShieldMode", NAPI_AUTO_LENGTH, EnumConstructor, nullptr,
749         sizeof(desc) / sizeof(*desc), desc, &result), DEFINE_CLASS);
750     CHKRP(napi_set_named_property(env, exports, "ShieldMode", result), SET_NAMED_PROPERTY);
751     return exports;
752 }
753 
~KeyEventMonitorInfo()754 KeyEventMonitorInfo::~KeyEventMonitorInfo()
755 {
756     if (callback == nullptr) {
757         return;
758     }
759     uint32_t refcount = 0;
760     CHKRV(napi_reference_unref(env, callback, &refcount), REFERENCE_UNREF);
761     if (refcount == 0) {
762         CHKRV(napi_delete_reference(env, callback), DELETE_REFERENCE);
763     }
764     callback = nullptr;
765 }
766 
767 std::mutex JsInputConsumer::clsMutex_;
768 std::shared_ptr<JsInputConsumer> JsInputConsumer::instance_;
769 
GetInstance()770 std::shared_ptr<JsInputConsumer> JsInputConsumer::GetInstance()
771 {
772     if (instance_ == nullptr) {
773         std::lock_guard<std::mutex> guard(clsMutex_);
774         if (instance_ == nullptr) {
775             instance_ = std::make_shared<JsInputConsumer>();
776         }
777     }
778     return instance_;
779 }
780 
Parse(napi_env env,napi_callback_info info)781 bool JsInputConsumer::KeyMonitor::Parse(napi_env env, napi_callback_info info)
782 {
783     size_t argc { KEY_MONITOR_EXPECT_N_PARAMS };
784     napi_value argv[KEY_MONITOR_EXPECT_N_PARAMS] {};
785     CHKRF(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
786 
787     if (argc < KEY_MONITOR_EXPECT_N_PARAMS) {
788         MMI_HILOGE("Parameter number error argc:%{public}zu", argc);
789         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "parameter number error");
790         return false;
791     }
792     if (!UtilNapi::TypeOf(env, argv[FIRST_PARAMETER], napi_string)) {
793         MMI_HILOGE("The first parameter is not string");
794         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "type", "string");
795         return false;
796     }
797     if (!UtilNapi::TypeOf(env, argv[SECOND_PARAMETER], napi_object)) {
798         MMI_HILOGE("The second parameter is not object");
799         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "options", "object");
800         return false;
801     }
802     if (!UtilNapi::TypeOf(env, argv[THIRD_PARAMETER], napi_function)) {
803         MMI_HILOGE("The third parameter is not function");
804         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "callback", "function");
805         return false;
806     }
807     if (!ParseKeyMonitorOption(env, argv[SECOND_PARAMETER])) {
808         MMI_HILOGE("Invalid KeyMonitorOption");
809         return false;
810     }
811     auto ret = napi_create_reference(env, argv[THIRD_PARAMETER], DEFAULT_REFERENCE_COUNT, &callback_);
812     if (ret != napi_ok) {
813         MMI_HILOGE("napi_create_reference fail");
814         THROWERR_CUSTOM(env, OTHER_ERROR, "Operation fail");
815         return false;
816     }
817     env_ = env;
818     return true;
819 }
820 
ParseKeyMonitorOption(napi_env env,napi_value keyOption)821 bool JsInputConsumer::KeyMonitor::ParseKeyMonitorOption(napi_env env, napi_value keyOption)
822 {
823     CALL_DEBUG_ENTER;
824     auto optKey = GetNamedPropertyInt32(env, keyOption, "key");
825     if (!optKey) {
826         MMI_HILOGE("Expect 'key'");
827         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Expect 'key'");
828         return false;
829     }
830     auto optAction = GetNamedPropertyInt32(env, keyOption, "action");
831     if (!optAction) {
832         MMI_HILOGE("Expect 'action'");
833         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Expect 'action'");
834         return false;
835     }
836     bool isRepeat { true };
837     if (!GetNamedPropertyBool(env, keyOption, "isRepeat", isRepeat)) {
838         MMI_HILOGE("Expect 'isRepeat'");
839         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Expect 'isRepeat'");
840         return false;
841     }
842 
843     keyOption_.SetKey(*optKey);
844     keyOption_.SetAction(JsInputConsumer::JsKeyAction2KeyAction(*optAction));
845     keyOption_.SetRepeat(isRepeat);
846     return true;
847 }
848 
ParseUnsubscription(napi_env env,napi_callback_info info)849 bool JsInputConsumer::KeyMonitor::ParseUnsubscription(napi_env env, napi_callback_info info)
850 {
851     size_t argc { KEY_MONITOR_EXPECT_N_PARAMS };
852     napi_value argv[KEY_MONITOR_EXPECT_N_PARAMS] {};
853 
854     auto ret = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
855     if (ret != napi_ok) {
856         MMI_HILOGE("napi_get_cb_info fail");
857         THROWERR_CUSTOM(env, OTHER_ERROR, "Operation fail");
858         return false;
859     }
860     if (argc < AT_LEAST_ONE_PARAMETER) {
861         MMI_HILOGE("Type of subscription is required");
862         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Type of subscription is required");
863         return false;
864     }
865     if (argc == AT_LEAST_ONE_PARAMETER) {
866         callback_ = nullptr;
867         return true;
868     }
869     if (!UtilNapi::TypeOf(env, argv[SECOND_PARAMETER], napi_function)) {
870         MMI_HILOGE("The second parameter is not function");
871         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "callback", "function");
872         return false;
873     }
874     ret = napi_create_reference(env, argv[SECOND_PARAMETER], DEFAULT_REFERENCE_COUNT, &callback_);
875     if (ret != napi_ok) {
876         MMI_HILOGE("napi_create_reference fail");
877         THROWERR_CUSTOM(env, OTHER_ERROR, "Operation fail");
878         return false;
879     }
880     env_ = env;
881     return true;
882 }
883 
SubscribeKeyMonitor(napi_env env,napi_callback_info info)884 void JsInputConsumer::SubscribeKeyMonitor(napi_env env, napi_callback_info info)
885 {
886     std::lock_guard guard(mutex_);
887     KeyMonitor keyMonitor {};
888 
889     if (!keyMonitor.Parse(env, info)) {
890         MMI_HILOGE("Unexpected key monitor");
891         return;
892     }
893     MMI_HILOGI("[NAPI] Subscribe key monitor");
894     if (!SubscribeKeyMonitor(env, keyMonitor)) {
895         CleanupKeyMonitor(env, keyMonitor);
896     }
897 }
898 
UnsubscribeKeyMonitor(napi_env env,napi_callback_info info)899 void JsInputConsumer::UnsubscribeKeyMonitor(napi_env env, napi_callback_info info)
900 {
901     std::lock_guard guard(mutex_);
902     KeyMonitor keyMonitor {};
903 
904     if (!keyMonitor.ParseUnsubscription(env, info)) {
905         MMI_HILOGE("Unexpected key monitor");
906         return;
907     }
908     if (keyMonitor.callback_ != nullptr) {
909         MMI_HILOGI("[NAPI] Unsubscribe key monitor");
910         UnsubscribeKeyMonitor(env, keyMonitor);
911     } else {
912         UnsubscribeKeyMonitors(env);
913     }
914     CleanupKeyMonitor(env, keyMonitor);
915 }
916 
GenerateId()917 size_t JsInputConsumer::GenerateId()
918 {
919     return ++baseId_;
920 }
921 
CleanupKeyMonitor(napi_env env,KeyMonitor & keyMonitor) const922 void JsInputConsumer::CleanupKeyMonitor(napi_env env, KeyMonitor &keyMonitor) const
923 {
924     if (keyMonitor.callback_ != nullptr) {
925         auto ret = napi_delete_reference(env, keyMonitor.callback_);
926         if (ret != napi_ok) {
927             MMI_HILOGE("napi_delete_reference fail");
928         }
929         keyMonitor.callback_ = nullptr;
930     }
931 }
932 
IsIdentical(napi_env env,const KeyMonitor & sMonitor,const KeyMonitor & tMonitor) const933 int32_t JsInputConsumer::IsIdentical(napi_env env, const KeyMonitor &sMonitor, const KeyMonitor &tMonitor) const
934 {
935     napi_value sHandler { nullptr };
936     napi_value tHandler { nullptr };
937     bool isEqual { false };
938 
939     auto ret = napi_get_reference_value(env, sMonitor.callback_, &sHandler);
940     if (ret != napi_ok) {
941         MMI_HILOGE("napi_get_reference_value fail");
942         return BOOLEAN_NONE;
943     }
944     ret = napi_get_reference_value(env, tMonitor.callback_, &tHandler);
945     if (ret != napi_ok) {
946         MMI_HILOGE("napi_get_reference_value fail");
947         return BOOLEAN_NONE;
948     }
949     ret = napi_strict_equals(env, sHandler, tHandler, &isEqual);
950     if (ret != napi_ok) {
951         MMI_HILOGE("napi_strict_equals fail");
952         return BOOLEAN_NONE;
953     }
954     return (isEqual ? BOOLEAN_TRUE : BOOLEAN_FALSE);
955 }
956 
HasSubscribed(napi_env env,const KeyMonitor & keyMonitor) const957 int32_t JsInputConsumer::HasSubscribed(napi_env env, const KeyMonitor &keyMonitor) const
958 {
959     napi_value sHandler { nullptr };
960     auto ret = napi_get_reference_value(env, keyMonitor.callback_, &sHandler);
961     if (ret != napi_ok) {
962         MMI_HILOGE("napi_get_reference_value fail");
963         return BOOLEAN_NONE;
964     }
965     for (const auto &[_, monitor] : monitors_) {
966         napi_value tHandler { nullptr };
967         auto ret = napi_get_reference_value(env, monitor.callback_, &tHandler);
968         if (ret != napi_ok) {
969             MMI_HILOGE("napi_get_reference_value fail");
970             return BOOLEAN_NONE;
971         }
972         bool isEqual { false };
973         ret = napi_strict_equals(env, sHandler, tHandler, &isEqual);
974         if (ret != napi_ok) {
975             MMI_HILOGE("napi_strict_equals fail");
976             return BOOLEAN_NONE;
977         }
978         if (isEqual) {
979             MMI_HILOGE("Callback already exist");
980             return BOOLEAN_TRUE;
981         }
982     }
983     return BOOLEAN_FALSE;
984 }
985 
SubscribeKeyMonitor(napi_env env,KeyMonitor & keyMonitor)986 bool JsInputConsumer::SubscribeKeyMonitor(napi_env env, KeyMonitor &keyMonitor)
987 {
988     auto hasSubscribed = HasSubscribed(env, keyMonitor);
989     if (hasSubscribed < 0) {
990         MMI_HILOGE("HasSubscribed fail");
991         THROWERR_CUSTOM(env, OTHER_ERROR, "Operation fail");
992         return false;
993     }
994     if (hasSubscribed) {
995         MMI_HILOGE("Duplicate subscription of key monitor");
996         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Duplicate subscription of key monitor");
997         return false;
998     }
999     auto keyMonitorId = GenerateId();
1000     auto subscriberId = InputManager::GetInstance()->SubscribeKeyMonitor(keyMonitor.keyOption_,
1001         [keyMonitorId](std::shared_ptr<KeyEvent> keyEvent) {
1002             JsInputConsumer::GetInstance()->OnSubscribeKeyMonitor(keyMonitorId, keyEvent);
1003         });
1004     if (subscriberId < 0) {
1005         if (subscriberId == ERROR_UNSUPPORT) {
1006             MMI_HILOGE("Capability not supported");
1007             THROWERR_CUSTOM(env, INPUT_DEVICE_NOT_SUPPORTED, "Capability not supported.");
1008         } else {
1009             MMI_HILOGE("SubscribeKeyMonitor fail, error:%{public}d", subscriberId);
1010             THROWERR_CUSTOM(env, OTHER_ERROR, "Operation fail");
1011         }
1012         return false;
1013     }
1014     MMI_HILOGI("[NAPI] Subscribe key monitor(ID:%{public}zu, subscriberId:%{public}d)", keyMonitorId, subscriberId);
1015     keyMonitor.env_ = env;
1016     keyMonitor.subscriberId_ = subscriberId;
1017     monitors_.emplace(keyMonitorId, keyMonitor);
1018     return true;
1019 }
1020 
UnsubscribeKeyMonitor(napi_env env,const KeyMonitor & keyMonitor)1021 void JsInputConsumer::UnsubscribeKeyMonitor(napi_env env, const KeyMonitor &keyMonitor)
1022 {
1023     for (auto mIter = monitors_.begin(); mIter != monitors_.end(); ++mIter) {
1024         auto identical = IsIdentical(env, keyMonitor, mIter->second);
1025         if (identical < 0) {
1026             MMI_HILOGE("IsIdentical fail");
1027             return;
1028         }
1029         if (identical) {
1030             auto &tMonitor = mIter->second;
1031             MMI_HILOGI("[NAPI] Unsubscribe key monitor(ID:%{public}zu, subscriberId:%{public}d)",
1032                 mIter->first, tMonitor.subscriberId_);
1033             InputManager::GetInstance()->UnsubscribeKeyMonitor(tMonitor.subscriberId_);
1034             CleanupKeyMonitor(env, tMonitor);
1035             monitors_.erase(mIter);
1036             return;
1037         }
1038     }
1039 }
1040 
UnsubscribeKeyMonitors(napi_env env)1041 void JsInputConsumer::UnsubscribeKeyMonitors(napi_env env)
1042 {
1043     for (auto &[monitorId, monitor] : monitors_) {
1044         MMI_HILOGI("[NAPI] Unsubscribe key monitor(ID:%{public}zu, subscriberId:%{public}d)",
1045             monitorId, monitor.subscriberId_);
1046         InputManager::GetInstance()->UnsubscribeKeyMonitor(monitor.subscriberId_);
1047         CleanupKeyMonitor(env, monitor);
1048     }
1049     monitors_.clear();
1050 }
1051 
OnSubscribeKeyMonitor(size_t keyMonitorId,std::shared_ptr<KeyEvent> keyEvent)1052 void JsInputConsumer::OnSubscribeKeyMonitor(size_t keyMonitorId, std::shared_ptr<KeyEvent> keyEvent)
1053 {
1054     CALL_DEBUG_ENTER;
1055     std::lock_guard guard(mutex_);
1056     auto mIter = monitors_.find(keyMonitorId);
1057     if (mIter == monitors_.end()) {
1058         MMI_HILOGE("No key monitor with ID(%{public}zu)", keyMonitorId);
1059         return;
1060     }
1061     auto &monitor = mIter->second;
1062     uv_loop_s *loop = nullptr;
1063     CHKRV(napi_get_uv_event_loop(monitor.env_, &loop), GET_UV_EVENT_LOOP);
1064 
1065     auto work = std::make_shared<Work>();
1066     work->keyMonitorId_ = keyMonitorId;
1067     work->work_.data = work.get();
1068 
1069     auto ret = uv_queue_work_with_qos(
1070         loop, &work->work_,
1071         [](uv_work_t *work) {
1072             MMI_HILOGD("uv_queue_work callback function is called");
1073         },
1074         JsInputConsumer::HandleKeyMonitor, uv_qos_user_initiated);
1075     if (ret != 0) {
1076         MMI_HILOGE("uv_queue_work_with_qos fail, error:%{public}d", ret);
1077         return;
1078     }
1079     pendingWorks_.emplace(&work->work_, work);
1080 }
1081 
NotifyKeyMonitor(uv_work_t * work,int32_t status)1082 void JsInputConsumer::NotifyKeyMonitor(uv_work_t *work, int32_t status)
1083 {
1084     CALL_DEBUG_ENTER;
1085     std::lock_guard guard(mutex_);
1086     auto pwIter = pendingWorks_.find(work);
1087     if (pwIter == pendingWorks_.end()) {
1088         MMI_HILOGW("Not a pending work(%{private}p)", work);
1089         return;
1090     }
1091     auto keyMonitorId = pwIter->second->keyMonitorId_;
1092     pendingWorks_.erase(pwIter);
1093 
1094     auto mIter = monitors_.find(keyMonitorId);
1095     if (mIter == monitors_.end()) {
1096         MMI_HILOGE("No key monitor with ID(%{public}zu)", keyMonitorId);
1097         return;
1098     }
1099     NotifyKeyMonitor(mIter->second);
1100 }
1101 
NotifyKeyMonitor(const KeyMonitor & keyMonitor)1102 void JsInputConsumer::NotifyKeyMonitor(const KeyMonitor &keyMonitor)
1103 {
1104     napi_handle_scope scope { nullptr };
1105     napi_open_handle_scope(keyMonitor.env_, &scope);
1106     CHKPV(scope);
1107     NotifyKeyMonitorScoped(keyMonitor);
1108     napi_close_handle_scope(keyMonitor.env_, scope);
1109 }
1110 
NotifyKeyMonitorScoped(const KeyMonitor & keyMonitor)1111 void JsInputConsumer::NotifyKeyMonitorScoped(const KeyMonitor &keyMonitor)
1112 {
1113     napi_value callback { nullptr };
1114     CHKRV(napi_get_reference_value(keyMonitor.env_, keyMonitor.callback_, &callback), GET_REFERENCE_VALUE);
1115     napi_value keyOption = ConstructKeyMonitorOption(keyMonitor.env_, keyMonitor.keyOption_);
1116     CHKPV(keyOption);
1117     napi_value result { nullptr };
1118     CHKRV(napi_call_function(keyMonitor.env_, nullptr, callback, 1, &keyOption, &result), CALL_FUNCTION);
1119 }
1120 
ConstructKeyMonitorOption(napi_env env,const KeyMonitorOption & keyOption)1121 napi_value JsInputConsumer::ConstructKeyMonitorOption(napi_env env, const KeyMonitorOption &keyOption)
1122 {
1123     napi_value result { nullptr };
1124     CHKRP(napi_create_object(env, &result), CREATE_OBJECT);
1125     MMI::SetNamedProperty(env, result, "key", keyOption.GetKey());
1126     MMI::SetNamedProperty(env, result, "action", JsInputConsumer::KeyAction2JsKeyAction(keyOption.GetAction()));
1127     MMI::SetNamedProperty(env, result, "isRepeat", keyOption.IsRepeat());
1128     return result;
1129 }
1130 
HandleKeyMonitor(uv_work_t * work,int32_t status)1131 void JsInputConsumer::HandleKeyMonitor(uv_work_t *work, int32_t status)
1132 {
1133     JsInputConsumer::GetInstance()->NotifyKeyMonitor(work, status);
1134 }
1135 
JsKeyAction2KeyAction(int32_t action)1136 int32_t JsInputConsumer::JsKeyAction2KeyAction(int32_t action)
1137 {
1138     static const std::map<int32_t, int32_t> keyActionMap {
1139         { JsKeyAction::JS_KEY_ACTION_CANCEL, KeyEvent::KEY_ACTION_CANCEL },
1140         { JsKeyAction::JS_KEY_ACTION_DOWN, KeyEvent::KEY_ACTION_DOWN },
1141         { JsKeyAction::JS_KEY_ACTION_UP, KeyEvent::KEY_ACTION_UP },
1142     };
1143     if (auto iter = keyActionMap.find(action); iter != keyActionMap.cend()) {
1144         return iter->second;
1145     } else {
1146         return KeyEvent::KEY_ACTION_UNKNOWN;
1147     }
1148 }
1149 
KeyAction2JsKeyAction(int32_t action)1150 int32_t JsInputConsumer::KeyAction2JsKeyAction(int32_t action)
1151 {
1152     static const std::map<int32_t, int32_t> keyActionMap {
1153         { KeyEvent::KEY_ACTION_CANCEL, JsKeyAction::JS_KEY_ACTION_CANCEL },
1154         { KeyEvent::KEY_ACTION_DOWN, JsKeyAction::JS_KEY_ACTION_DOWN },
1155         { KeyEvent::KEY_ACTION_UP, JsKeyAction::JS_KEY_ACTION_UP },
1156     };
1157     if (auto iter = keyActionMap.find(action); iter != keyActionMap.cend()) {
1158         return iter->second;
1159     } else {
1160         return JsKeyAction::JS_KEY_ACTION_CANCEL;
1161     }
1162 }
1163 
1164 EXTERN_C_START
MmiInit(napi_env env,napi_value exports)1165 static napi_value MmiInit(napi_env env, napi_value exports)
1166 {
1167     CALL_DEBUG_ENTER;
1168     napi_property_descriptor desc[] = {
1169         DECLARE_NAPI_FUNCTION("on", JsOn),
1170         DECLARE_NAPI_FUNCTION("off", JsOff),
1171         DECLARE_NAPI_FUNCTION("setShieldStatus", SetShieldStatus),
1172         DECLARE_NAPI_FUNCTION("getShieldStatus", GetShieldStatus),
1173         DECLARE_NAPI_FUNCTION("getAllSystemHotkeys", GetAllSystemHotkeys)
1174     };
1175     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
1176     if (CreateShieldMode(env, exports) == nullptr) {
1177         THROWERR(env, "Failed to create shield mode");
1178         return nullptr;
1179     }
1180     return exports;
1181 }
1182 EXTERN_C_END
1183 
1184 static napi_module mmiModule = {
1185     .nm_version = 1,
1186     .nm_flags = 0,
1187     .nm_filename = nullptr,
1188     .nm_register_func = MmiInit,
1189     .nm_modname = "multimodalInput.inputConsumer",
1190     .nm_priv = ((void*)0),
1191     .reserved = { 0 },
1192 };
1193 
RegisterModule(void)1194 extern "C" __attribute__((constructor)) void RegisterModule(void)
1195 {
1196     napi_module_register(&mmiModule);
1197 }
1198 } // namespace MMI
1199 } // namespace OHOS
1200