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 "js_register_module.h"
17 
18 #include <algorithm>
19 #include <cinttypes>
20 
21 #include "input_manager.h"
22 #include "js_register_util.h"
23 #include "napi_constants.h"
24 #include "util_napi.h"
25 #include "util_napi_error.h"
26 
27 #undef MMI_LOG_TAG
28 #define MMI_LOG_TAG "JSRegisterModule"
29 
30 namespace OHOS {
31 namespace MMI {
32 namespace {
33 constexpr size_t EVENT_NAME_LEN { 64 };
34 constexpr size_t PRE_KEYS_SIZE { 4 };
35 constexpr size_t INPUT_PARAMETER_MIDDLE { 2 };
36 constexpr size_t INPUT_PARAMETER_MAX { 3 };
37 constexpr int32_t OCCUPIED_BY_SYSTEM { -3 };
38 constexpr int32_t OCCUPIED_BY_OTHER { -4 };
39 } // namespace
40 
41 static Callbacks callbacks = {};
42 static Callbacks hotkeyCallbacks = {};
43 std::mutex sCallBacksMutex;
44 static const std::vector<int32_t> pressKeyCodes = {
45     KeyEvent::KEYCODE_ALT_LEFT,
46     KeyEvent::KEYCODE_ALT_RIGHT,
47     KeyEvent::KEYCODE_SHIFT_LEFT,
48     KeyEvent::KEYCODE_SHIFT_RIGHT,
49     KeyEvent::KEYCODE_CTRL_LEFT,
50     KeyEvent::KEYCODE_CTRL_RIGHT
51 };
52 static const std::vector<int32_t> finalKeyCodes = {
53     KeyEvent::KEYCODE_ALT_LEFT,
54     KeyEvent::KEYCODE_ALT_RIGHT,
55     KeyEvent::KEYCODE_SHIFT_LEFT,
56     KeyEvent::KEYCODE_SHIFT_RIGHT,
57     KeyEvent::KEYCODE_CTRL_LEFT,
58     KeyEvent::KEYCODE_CTRL_RIGHT,
59     KeyEvent::KEYCODE_META_LEFT,
60     KeyEvent::KEYCODE_META_RIGHT
61 };
TypeOf(napi_env env, napi_value value, napi_valuetype type)62 bool JsCommon::TypeOf(napi_env env, napi_value value, napi_valuetype type)
63 {
64     napi_valuetype valueType = napi_undefined;
65     CHKRF(napi_typeof(env, value, &valueType), TYPEOF);
66     if (valueType != type) {
67         return false;
68     }
69     return true;
70 }
71 
ThrowError(napi_env env, int32_t code)72 void JsCommon::ThrowError(napi_env env, int32_t code)
73 {
74     int32_t errorCode = std::abs(code);
75     if (errorCode == COMMON_USE_SYSAPI_ERROR) {
76         MMI_HILOGE("Non system applications use system API");
77         THROWERR_CUSTOM(env, COMMON_USE_SYSAPI_ERROR, "Non system applications use system API");
78     } else if (errorCode == COMMON_PERMISSION_CHECK_ERROR) {
79         MMI_HILOGE("Shield api need ohos.permission.INPUT_CONTROL_DISPATCHING");
80         THROWERR_API9(env, COMMON_PERMISSION_CHECK_ERROR, "shiled API", "ohos.permission.INPUT_CONTROL_DISPATCHING");
81     } else {
82         MMI_HILOGE("Dispatch control failed");
83     }
84 }
85 
GetHotkeyEventInfo(napi_env env, napi_callback_info info, sptr<KeyEventMonitorInfo> event, std::shared_ptr<KeyOption> keyOption)86 napi_value GetHotkeyEventInfo(napi_env env, napi_callback_info info, sptr<KeyEventMonitorInfo> event,
87     std::shared_ptr<KeyOption> keyOption)
88 {
89     CALL_DEBUG_ENTER;
90     CHKPP(event);
91     CHKPP(keyOption);
92     size_t argc = 3;
93     napi_value argv[3] = { 0 };
94     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
95     napi_value receiveValue = nullptr;
96     CHKRP(napi_get_named_property(env, argv[1], "preKeys", &receiveValue), GET_NAMED_PROPERTY);
97     if (receiveValue == nullptr) {
98         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "PreKeys not found");
99         return nullptr;
100     }
101     std::set<int32_t> preKeys;
102     if (GetPreKeys(env, receiveValue, preKeys) == nullptr) {
103         MMI_HILOGE("Get preKeys failed");
104         return nullptr;
105     }
106     if (preKeys.size() > INPUT_PARAMETER_MIDDLE) {
107         MMI_HILOGE("PreKeys size invalid");
108         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "PreKeys size invalid");
109         return nullptr;
110     }
111     MMI_HILOGD("PreKeys size:%{public}zu", preKeys.size());
112     keyOption->SetPreKeys(preKeys);
113     std::string subKeyNames = "";
114     for (const auto &item : preKeys) {
115         auto it = std::find(pressKeyCodes.begin(), pressKeyCodes.end(), item);
116         if (it == pressKeyCodes.end()) {
117             MMI_HILOGE("PreKeys is not expect");
118             THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "PreKeys size invalid");
119             return nullptr;
120         }
121         subKeyNames += std::to_string(item);
122         subKeyNames += ",";
123         MMI_HILOGD("PreKeys:%{private}d", item);
124     }
125     std::optional<int32_t> finalKeyOption = GetNamedPropertyInt32(env, argv[1], "finalKey");
126     if (!finalKeyOption) {
127         MMI_HILOGE("GetNamedPropertyInt32 failed");
128         return nullptr;
129     }
130     int32_t finalKey = finalKeyOption.value();
131     if (finalKey < 0) {
132         MMI_HILOGE("FinalKey:%{private}d is less 0, can not process", finalKey);
133         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "FinalKey must be greater than or equal to 0");
134         return nullptr;
135     }
136     auto it = std::find(finalKeyCodes.begin(), finalKeyCodes.end(), finalKey);
137     if (it != finalKeyCodes.end()) {
138         MMI_HILOGE("FinalKey is not expect");
139         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "FinalKey is not expect");
140         return nullptr;
141     }
142     subKeyNames += std::to_string(finalKey);
143     subKeyNames += ",";
144     keyOption->SetFinalKey(finalKey);
145     MMI_HILOGD("FinalKey:%{private}d", finalKey);
146 
147     bool isFinalKeyDown = true;
148     subKeyNames += std::to_string(isFinalKeyDown);
149     subKeyNames += ",";
150     keyOption->SetFinalKeyDown(isFinalKeyDown);
151     MMI_HILOGD("IsFinalKeyDown:%{private}d,", (isFinalKeyDown == true ? 1 : 0));
152 
153     int32_t finalKeyDownDuration = 0;
154     subKeyNames += std::to_string(finalKeyDownDuration);
155     subKeyNames += ",";
156     keyOption->SetFinalKeyDownDuration(finalKeyDownDuration);
157 
158     bool isRepeat = true;
159     if (!GetNamedPropertyBool(env, argv[1], "isRepeat", isRepeat)) {
160         MMI_HILOGD("IsRepeat field is default");
161     }
162     subKeyNames += std::to_string(isRepeat);
163     keyOption->SetRepeat(isRepeat);
164     MMI_HILOGD("IsRepeat:%{public}s", (isRepeat ? "true" : "false"));
165     event->eventType = subKeyNames;
166 
167     napi_value ret;
168     CHKRP(napi_create_int32(env, RET_OK, &ret), CREATE_INT32);
169     return ret;
170 }
171 
GetEventInfoAPI9(napi_env env, napi_callback_info info, sptr<KeyEventMonitorInfo> event, std::shared_ptr<KeyOption> keyOption)172 napi_value GetEventInfoAPI9(napi_env env, napi_callback_info info, sptr<KeyEventMonitorInfo> event,
173     std::shared_ptr<KeyOption> keyOption)
174 {
175     CALL_DEBUG_ENTER;
176     CHKPP(event);
177     CHKPP(keyOption);
178     size_t argc = 3;
179     napi_value argv[3] = { 0 };
180     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
181     napi_value receiveValue = nullptr;
182     CHKRP(napi_get_named_property(env, argv[1], "preKeys", &receiveValue), GET_NAMED_PROPERTY);
183     if (receiveValue == nullptr) {
184         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "preKeys not found");
185         return nullptr;
186     }
187     std::set<int32_t> preKeys;
188     if (GetPreKeys(env, receiveValue, preKeys) == nullptr) {
189         MMI_HILOGE("Get preKeys failed");
190         return nullptr;
191     }
192     if (preKeys.size() > PRE_KEYS_SIZE) {
193         MMI_HILOGE("preKeys size invalid");
194         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "preKeys size invalid");
195         return nullptr;
196     }
197     MMI_HILOGD("PreKeys size:%{public}zu", preKeys.size());
198     keyOption->SetPreKeys(preKeys);
199     std::string subKeyNames = "";
200     for (const auto &item : preKeys) {
201         subKeyNames += std::to_string(item);
202         subKeyNames += ",";
203         MMI_HILOGD("preKeys:%{private}d", item);
204     }
205     std::optional<int32_t> tempFinalKey = GetNamedPropertyInt32(env, argv[1], "finalKey");
206     if (!tempFinalKey) {
207         MMI_HILOGE("GetNamedPropertyInt32 failed");
208         return nullptr;
209     }
210     int32_t finalKey = tempFinalKey.value();
211     if (finalKey < 0) {
212         MMI_HILOGE("finalKey:%{private}d is less 0, can not process", finalKey);
213         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "finalKey must be greater than or equal to 0");
214         return nullptr;
215     }
216     subKeyNames += std::to_string(finalKey);
217     subKeyNames += ",";
218     keyOption->SetFinalKey(finalKey);
219     MMI_HILOGD("FinalKey:%{private}d", finalKey);
220     bool isFinalKeyDown;
221     if (!GetNamedPropertyBool(env, argv[1], "isFinalKeyDown", isFinalKeyDown)) {
222         MMI_HILOGE("GetNamedPropertyBool failed");
223         return nullptr;
224     }
225     subKeyNames += std::to_string(isFinalKeyDown);
226     subKeyNames += ",";
227     keyOption->SetFinalKeyDown(isFinalKeyDown);
228     MMI_HILOGD("IsFinalKeyDown:%{private}d,map_key:%{private}s",
229         (isFinalKeyDown == true ? 1 : 0), subKeyNames.c_str());
230     std::optional<int32_t> tempKeyDownDuration = GetNamedPropertyInt32(env, argv[1], "finalKeyDownDuration");
231     if (!tempKeyDownDuration) {
232         MMI_HILOGE("GetNamedPropertyInt32 failed");
233         return nullptr;
234     }
235     int32_t finalKeyDownDuration = tempKeyDownDuration.value();
236     if (finalKeyDownDuration < 0) {
237         MMI_HILOGE("finalKeyDownDuration:%{public}d is less 0, can not process", finalKeyDownDuration);
238         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "finalKeyDownDuration must be greater than or equal to 0");
239         return nullptr;
240     }
241     subKeyNames += std::to_string(finalKeyDownDuration);
242     subKeyNames += ",";
243     keyOption->SetFinalKeyDownDuration(finalKeyDownDuration);
244     MMI_HILOGD("FinalKeyDownDuration:%{public}d", finalKeyDownDuration);
245     bool isRepeat = true;
246     if (!GetNamedPropertyBool(env, argv[1], "isRepeat", isRepeat)) {
247         MMI_HILOGD("IsRepeat field is default");
248     }
249     subKeyNames += std::to_string(isRepeat);
250     keyOption->SetRepeat(isRepeat);
251     MMI_HILOGD("IsRepeat:%{public}s", (isRepeat ? "true" : "false"));
252     event->eventType = subKeyNames;
253     napi_value ret;
254     CHKRP(napi_create_int32(env, RET_OK, &ret), CREATE_INT32);
255     return ret;
256 }
257 
IsMatchKeyAction(bool isFinalKeydown, int32_t keyAction)258 static bool IsMatchKeyAction(bool isFinalKeydown, int32_t keyAction)
259 {
260     CALL_DEBUG_ENTER;
261     MMI_HILOGD("isFinalKeydown:%{public}d, keyAction:%{public}d", isFinalKeydown, keyAction);
262     if (isFinalKeydown && keyAction == KeyEvent::KEY_ACTION_DOWN) {
263         return true;
264     }
265     if (!isFinalKeydown && keyAction == KeyEvent::KEY_ACTION_UP) {
266         return true;
267     }
268     MMI_HILOGE("isFinalKeydown not matched with keyAction");
269     return false;
270 }
271 
MatchCombinationKeys(sptr<KeyEventMonitorInfo> monitorInfo, std::shared_ptr<KeyEvent> keyEvent)272 static bool MatchCombinationKeys(sptr<KeyEventMonitorInfo> monitorInfo, std::shared_ptr<KeyEvent> keyEvent)
273 {
274     CALL_DEBUG_ENTER;
275     CHKPF(monitorInfo);
276     CHKPF(keyEvent);
277     auto keyOption = monitorInfo->keyOption;
278     CHKPF(keyOption);
279     std::vector<KeyEvent::KeyItem> items = keyEvent->GetKeyItems();
280     int32_t infoFinalKey = keyOption->GetFinalKey();
281     int32_t keyEventFinalKey = keyEvent->GetKeyCode();
282     bool isFinalKeydown = keyOption->IsFinalKeyDown();
283     MMI_HILOGD("InfoFinalKey:%{private}d,keyEventFinalKey:%{private}d", infoFinalKey, keyEventFinalKey);
284     if (infoFinalKey != keyEventFinalKey || items.size() > PRE_KEYS_SIZE ||
285         !IsMatchKeyAction(isFinalKeydown, keyEvent->GetKeyAction())) {
286         MMI_HILOGD("key Param invalid");
287         return false;
288     }
289     std::set<int32_t> infoPreKeys = keyOption->GetPreKeys();
290     int32_t infoSize = 0;
291     for (auto it = infoPreKeys.begin(); it != infoPreKeys.end(); ++it) {
292         if (*it >= 0) {
293             infoSize++;
294         }
295     }
296     int32_t count = 0;
297     for (const auto &item : items) {
298         if (item.GetKeyCode() == keyEventFinalKey) {
299             continue;
300         }
301         auto iter = find(infoPreKeys.begin(), infoPreKeys.end(), item.GetKeyCode());
302         if (iter == infoPreKeys.end()) {
303             MMI_HILOGW("No keyCode in preKeys");
304             return false;
305         }
306         count++;
307     }
308     MMI_HILOGD("kevEventSize:%{public}d, infoSize:%{public}d", count, infoSize);
309     std::optional<KeyEvent::KeyItem> keyItem = keyEvent->GetKeyItem();
310     if (!keyItem) {
311         MMI_HILOGE("The keyItem is nullopt");
312         return false;
313     }
314     auto downTime = keyItem->GetDownTime();
315     auto upTime = keyEvent->GetActionTime();
316     auto curDurationTime = keyOption->GetFinalKeyDownDuration();
317     if (curDurationTime > 0 && (upTime - downTime >= (static_cast<int64_t>(curDurationTime) * 1000))) {
318         MMI_HILOGE("Skip, upTime - downTime >= duration");
319         return false;
320     }
321     return count == infoSize;
322 }
323 
SubKeyEventCallback(std::shared_ptr<KeyEvent> keyEvent)324 static void SubKeyEventCallback(std::shared_ptr<KeyEvent> keyEvent)
325 {
326     CALL_DEBUG_ENTER;
327     CHKPV(keyEvent);
328     std::lock_guard guard(sCallBacksMutex);
329     auto iter = callbacks.begin();
330     while (iter != callbacks.end()) {
331         auto &list = iter->second;
332         ++iter;
333         MMI_HILOGD("list size:%{public}zu", list.size());
334         auto infoIter = list.begin();
335         while (infoIter != list.end()) {
336             auto monitorInfo = *infoIter;
337             if (MatchCombinationKeys(monitorInfo, keyEvent)) {
338                 EmitAsyncCallbackWork(monitorInfo);
339             }
340             ++infoIter;
341         }
342     }
343 }
344 
SubHotkeyEventCallback(std::shared_ptr<KeyEvent> keyEvent)345 static void SubHotkeyEventCallback(std::shared_ptr<KeyEvent> keyEvent)
346 {
347     CALL_DEBUG_ENTER;
348     CHKPV(keyEvent);
349     std::lock_guard guard(sCallBacksMutex);
350     auto iter = hotkeyCallbacks.begin();
351     while (iter != hotkeyCallbacks.end()) {
352         auto &list = iter->second;
353         ++iter;
354         MMI_HILOGD("Callback list size:%{public}zu", list.size());
355         auto infoIter = list.begin();
356         while (infoIter != list.end()) {
357             auto monitorInfo = *infoIter;
358             if (MatchCombinationKeys(monitorInfo, keyEvent)) {
359                 EmitAsyncCallbackWork(monitorInfo);
360             }
361             ++infoIter;
362         }
363     }
364 }
365 
SubscribeKey(napi_env env, napi_callback_info info, sptr<KeyEventMonitorInfo> event, std::shared_ptr<KeyOption> keyOption)366 napi_value SubscribeKey(napi_env env, napi_callback_info info, sptr<KeyEventMonitorInfo> event,
367     std::shared_ptr<KeyOption> keyOption)
368 {
369     CALL_DEBUG_ENTER;
370     CHKPP(event);
371     CHKPP(keyOption);
372     if (GetEventInfoAPI9(env, info, event, keyOption) == nullptr) {
373         MMI_HILOGE("GetEventInfoAPI9 failed");
374         return nullptr;
375     }
376     event->keyOption = keyOption;
377     int32_t preSubscribeId = GetPreSubscribeId(callbacks, event);
378     if (preSubscribeId < 0) {
379         MMI_HILOGD("EventType:%{private}s, eventName:%{public}s", event->eventType.c_str(), event->name.c_str());
380         int32_t subscribeId = -1;
381         subscribeId = InputManager::GetInstance()->SubscribeKeyEvent(keyOption, SubKeyEventCallback);
382         if (subscribeId < 0) {
383             MMI_HILOGE("SubscribeId invalid:%{public}d", subscribeId);
384             return nullptr;
385         }
386         MMI_HILOGD("SubscribeId:%{public}d", subscribeId);
387         event->subscribeId = subscribeId;
388     } else {
389         event->subscribeId = preSubscribeId;
390     }
391     if (AddEventCallback(env, callbacks, event) < 0) {
392         MMI_HILOGE("AddEventCallback failed");
393         return nullptr;
394     }
395     napi_value ret;
396     CHKRP(napi_create_int32(env, RET_OK, &ret), CREATE_INT32);
397     return ret;
398 }
399 
SubscribeHotkey(napi_env env, napi_callback_info info, sptr<KeyEventMonitorInfo> event, std::shared_ptr<KeyOption> keyOption)400 napi_value SubscribeHotkey(napi_env env, napi_callback_info info, sptr<KeyEventMonitorInfo> event,
401     std::shared_ptr<KeyOption> keyOption)
402 {
403     CALL_DEBUG_ENTER;
404     CHKPP(event);
405     CHKPP(keyOption);
406     if (GetHotkeyEventInfo(env, info, event, keyOption) == nullptr) {
407         MMI_HILOGE("GetHotkeyEventInfo failed");
408         return nullptr;
409     }
410     event->keyOption = keyOption;
411     int32_t preSubscribeId = GetPreSubscribeId(hotkeyCallbacks, event);
412     if (preSubscribeId < 0) {
413         MMI_HILOGD("EventType:%{private}s, eventName:%{public}s", event->eventType.c_str(), event->name.c_str());
414         int32_t subscribeId = -1;
415         subscribeId = InputManager::GetInstance()->SubscribeHotkey(keyOption, SubHotkeyEventCallback);
416         if (subscribeId == OCCUPIED_BY_SYSTEM) {
417             MMI_HILOGE("SubscribeId invalid:%{public}d", subscribeId);
418             THROWERR_CUSTOM(env, INPUT_OCCUPIED_BY_SYSTEM, "Hotkey occupied by system");
419             return nullptr;
420         }
421         if (subscribeId == OCCUPIED_BY_OTHER) {
422             MMI_HILOGE("SubscribeId invalid:%{public}d", subscribeId);
423             THROWERR_CUSTOM(env, INPUT_OCCUPIED_BY_OTHER, "Hotkey occupied by other");
424             return nullptr;
425         }
426         MMI_HILOGD("SubscribeId:%{public}d", subscribeId);
427         event->subscribeId = subscribeId;
428     } else {
429         event->subscribeId = preSubscribeId;
430     }
431     if (AddEventCallback(env, hotkeyCallbacks, event) < 0) {
432         MMI_HILOGE("AddEventCallback failed");
433         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "AddEventCallback failed");
434         return nullptr;
435     }
436     napi_value ret;
437     CHKRP(napi_create_int32(env, RET_OK, &ret), CREATE_INT32);
438     return ret;
439 }
440 
GetEventType(napi_env env, napi_callback_info info, sptr<KeyEventMonitorInfo> event, std::string &keyType)441 bool GetEventType(napi_env env, napi_callback_info info, sptr<KeyEventMonitorInfo> event, std::string &keyType)
442 {
443     CALL_DEBUG_ENTER;
444     size_t argc = 3;
445     napi_value argv[3] = { 0 };
446     CHKRF(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
447     if (argc < INPUT_PARAMETER_MIDDLE) {
448         MMI_HILOGE("Parameter number error argc:%{public}zu", argc);
449         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "parameter number error");
450         return false;
451     }
452     if (!UtilNapi::TypeOf(env, argv[0], napi_string)) {
453         MMI_HILOGE("The first parameter is not string");
454         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "type", "string");
455         return false;
456     }
457     if (!UtilNapi::TypeOf(env, argv[1], napi_object)) {
458         MMI_HILOGE("The second parameter is not napi_object");
459         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "keyOptions", "object");
460         return false;
461     }
462     if (argc == INPUT_PARAMETER_MAX) {
463         napi_valuetype valueType = napi_undefined;
464         CHKRF(napi_typeof(env, argv[INPUT_PARAMETER_MIDDLE], &valueType), TYPEOF);
465         if (valueType != napi_function) {
466             MMI_HILOGE("The third parameter is not napi_function");
467             THROWERR_API9(env, COMMON_PARAMETER_ERROR, "callback", "function");
468             return false;
469         }
470         CHKRF(napi_create_reference(env, argv[INPUT_PARAMETER_MIDDLE], 1, &event->callback), REFERENCE_REF);
471     } else {
472         event->callback = nullptr;
473     }
474 
475     char eventType[EVENT_NAME_LEN] = { 0 };
476     size_t typeLen = 0;
477     CHKRF(napi_get_value_string_utf8(env, argv[0], eventType, EVENT_NAME_LEN - 1, &typeLen), GET_VALUE_STRING_UTF8);
478     keyType = eventType;
479     if (keyType != SUBSCRIBE_TYPE && keyType != HOTKEY_SUBSCRIBE_TYPE) {
480         MMI_HILOGE("Type is not key or hotkey");
481         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Type must be key or hotkeyChange");
482         return false;
483     }
484     return true;
485 }
486 
JsOn(napi_env env, napi_callback_info info)487 static napi_value JsOn(napi_env env, napi_callback_info info)
488 {
489     CALL_DEBUG_ENTER;
490     sptr<KeyEventMonitorInfo> event = new (std::nothrow) KeyEventMonitorInfo();
491     CHKPP(event);
492     event->env = env;
493     auto keyOption = std::make_shared<KeyOption>();
494     std::string keyType;
495     size_t argc = 3;
496     napi_value argv[3] = { 0 };
497     if (napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr) != napi_ok) {
498         MMI_HILOGE("GET_CB_INFO failed");
499         return nullptr;
500     }
501     if (argc < INPUT_PARAMETER_MAX) {
502         MMI_HILOGE("Parameter number error argc:%{public}zu", argc);
503         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "parameter number error");
504         return nullptr;
505     }
506     if (!GetEventType(env, info, event, keyType)) {
507         MMI_HILOGE("GetEventType fail, type must be key or hotkeyChange");
508         return nullptr;
509     }
510     event->name = keyType;
511     if (keyType == HOTKEY_SUBSCRIBE_TYPE) {
512         if (SubscribeHotkey(env, info, event, keyOption) == nullptr) {
513             MMI_HILOGE("SubscribeHotkey failed");
514             return nullptr;
515         }
516     } else {
517         if (SubscribeKey(env, info, event, keyOption) == nullptr) {
518             MMI_HILOGE("SubscribeKey failed");
519             return nullptr;
520         }
521     }
522     return nullptr;
523 }
524 
JsOff(napi_env env, napi_callback_info info)525 static napi_value JsOff(napi_env env, napi_callback_info info)
526 {
527     CALL_DEBUG_ENTER;
528     sptr<KeyEventMonitorInfo> event = new (std::nothrow) KeyEventMonitorInfo();
529     CHKPP(event);
530     event->env = env;
531     auto keyOption = std::make_shared<KeyOption>();
532     std::string keyType;
533     if (!GetEventType(env, info, event, keyType)) {
534         MMI_HILOGE("GetEventType fail, type must be key or hotkeyChange");
535         return nullptr;
536     }
537     event->name = keyType;
538     int32_t subscribeId = -1;
539     if (keyType == HOTKEY_SUBSCRIBE_TYPE) {
540         if (GetHotkeyEventInfo(env, info, event, keyOption) == nullptr) {
541             MMI_HILOGE("GetHotkeyEventInfo failed");
542             return nullptr;
543         }
544         if (DelEventCallback(env, hotkeyCallbacks, event, subscribeId) < 0) {
545             MMI_HILOGE("DelEventCallback failed");
546             return nullptr;
547         }
548         MMI_HILOGI("Unsubscribe hot key(%{public}d)", subscribeId);
549         InputManager::GetInstance()->UnsubscribeHotkey(subscribeId);
550     } else {
551         if (GetEventInfoAPI9(env, info, event, keyOption) == nullptr) {
552             MMI_HILOGE("GetEventInfoAPI9 failed");
553             return nullptr;
554         }
555         if (DelEventCallback(env, callbacks, event, subscribeId) < 0) {
556             MMI_HILOGE("DelEventCallback failed");
557             return nullptr;
558         }
559         MMI_HILOGI("Unsubscribe key event(%{public}d)", subscribeId);
560         InputManager::GetInstance()->UnsubscribeKeyEvent(subscribeId);
561     }
562     return nullptr;
563 }
564 
SetShieldStatus(napi_env env, napi_callback_info info)565 static napi_value SetShieldStatus(napi_env env, napi_callback_info info)
566 {
567     CALL_DEBUG_ENTER;
568     size_t argc = 2;
569     napi_value argv[2] = { 0 };
570     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
571     if (argc < INPUT_PARAMETER_MIDDLE) {
572         MMI_HILOGE("At least two parameters is required");
573         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "shieldMode", "number");
574         return nullptr;
575     }
576     if (!JsCommon::TypeOf(env, argv[0], napi_number)) {
577         MMI_HILOGE("shieldMode parameter type is invalid");
578         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "shieldMode", "number");
579         return nullptr;
580     }
581     int32_t shieldMode = 0;
582     CHKRP(napi_get_value_int32(env, argv[0], &shieldMode), GET_VALUE_INT32);
583     if (shieldMode < FACTORY_MODE || shieldMode > OOBE_MODE) {
584         MMI_HILOGE("Undefined shield mode");
585         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Shield mode does not exist");
586         return nullptr;
587     }
588 
589     if (!JsCommon::TypeOf(env, argv[1], napi_boolean)) {
590         MMI_HILOGE("isShield parameter type is invalid");
591         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "isShield", "boolean");
592         return nullptr;
593     }
594     bool isShield = true;
595     CHKRP(napi_get_value_bool(env, argv[1], &isShield), GET_VALUE_BOOL);
596 
597     int32_t errCode = InputManager::GetInstance()->SetShieldStatus(shieldMode, isShield);
598     JsCommon::ThrowError(env, errCode);
599     napi_value result = nullptr;
600     if (napi_get_undefined(env, &result) != napi_ok) {
601         MMI_HILOGE("Get undefined result is failed");
602         return nullptr;
603     }
604     return result;
605 }
606 
GetShieldStatus(napi_env env, napi_callback_info info)607 static napi_value GetShieldStatus(napi_env env, napi_callback_info info)
608 {
609     CALL_DEBUG_ENTER;
610     size_t argc = 1;
611     napi_value argv[1] = { 0 };
612     CHKRP(napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
613     if (argc < 1) {
614         MMI_HILOGE("At least 1 parameter is required");
615         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "shieldMode", "number");
616         return nullptr;
617     }
618     if (!JsCommon::TypeOf(env, argv[0], napi_number)) {
619         MMI_HILOGE("shieldMode parameter type is invalid");
620         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "shieldMode", "number");
621         return nullptr;
622     }
623     int32_t shieldMode = 0;
624     CHKRP(napi_get_value_int32(env, argv[0], &shieldMode), GET_VALUE_INT32);
625     if (shieldMode < FACTORY_MODE || shieldMode > OOBE_MODE) {
626         MMI_HILOGE("Undefined shield mode");
627         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Shield mode does not exist");
628         return nullptr;
629     }
630     bool isShield { false };
631     auto errCode = InputManager::GetInstance()->GetShieldStatus(shieldMode, isShield);
632     JsCommon::ThrowError(env, errCode);
633     napi_value result = nullptr;
634     NAPI_CALL(env, napi_get_boolean(env, isShield, &result));
635     return result;
636 }
637 
GetAllSystemHotkeys(napi_env env, napi_callback_info info)638 static napi_value GetAllSystemHotkeys(napi_env env, napi_callback_info info)
639 {
640     CALL_DEBUG_ENTER;
641     return GetSystemHotkey(env);
642 }
643 
EnumConstructor(napi_env env, napi_callback_info info)644 static napi_value EnumConstructor(napi_env env, napi_callback_info info)
645 {
646     CALL_DEBUG_ENTER;
647     size_t argc = 0;
648     napi_value args[1] = { 0 };
649     napi_value ret = nullptr;
650     void *data = nullptr;
651     CHKRP(napi_get_cb_info(env, info, &argc, args, &ret, &data), GET_CB_INFO);
652     return ret;
653 }
654 
CreateShieldMode(napi_env env, napi_value exports)655 static napi_value CreateShieldMode(napi_env env, napi_value exports)
656 {
657     CALL_DEBUG_ENTER;
658     napi_value factory_mode = nullptr;
659     CHKRP(napi_create_int32(env, SHIELD_MODE::FACTORY_MODE, &factory_mode), CREATE_INT32);
660     napi_value oobe_mode = nullptr;
661     CHKRP(napi_create_int32(env, SHIELD_MODE::OOBE_MODE, &oobe_mode), CREATE_INT32);
662 
663     napi_property_descriptor desc[] = {
664         DECLARE_NAPI_STATIC_PROPERTY("FACTORY_MODE", factory_mode),
665         DECLARE_NAPI_STATIC_PROPERTY("OOBE_MODE", oobe_mode),
666     };
667     napi_value result = nullptr;
668     CHKRP(napi_define_class(env, "ShieldMode", NAPI_AUTO_LENGTH, EnumConstructor, nullptr,
669         sizeof(desc) / sizeof(*desc), desc, &result), DEFINE_CLASS);
670     CHKRP(napi_set_named_property(env, exports, "ShieldMode", result), SET_NAMED_PROPERTY);
671     return exports;
672 }
673 
~KeyEventMonitorInfo()674 KeyEventMonitorInfo::~KeyEventMonitorInfo()
675 {}
676 
677 EXTERN_C_START
MmiInit(napi_env env, napi_value exports)678 static napi_value MmiInit(napi_env env, napi_value exports)
679 {
680     CALL_DEBUG_ENTER;
681     napi_property_descriptor desc[] = {
682         DECLARE_NAPI_FUNCTION("on", JsOn),
683         DECLARE_NAPI_FUNCTION("off", JsOff),
684         DECLARE_NAPI_FUNCTION("setShieldStatus", SetShieldStatus),
685         DECLARE_NAPI_FUNCTION("getShieldStatus", GetShieldStatus),
686         DECLARE_NAPI_FUNCTION("getAllSystemHotkeys", GetAllSystemHotkeys)
687     };
688     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
689     if (CreateShieldMode(env, exports) == nullptr) {
690         THROWERR(env, "Failed to create shield mode");
691         return nullptr;
692     }
693     return exports;
694 }
695 EXTERN_C_END
696 
697 static napi_module mmiModule = {
698     .nm_version = 1,
699     .nm_flags = 0,
700     .nm_filename = nullptr,
701     .nm_register_func = MmiInit,
702     .nm_modname = "multimodalInput.inputConsumer",
703     .nm_priv = ((void*)0),
704     .reserved = { 0 },
705 };
706 
RegisterModule(void)707 extern "C" __attribute__((constructor)) void RegisterModule(void)
708 {
709     napi_module_register(&mmiModule);
710 }
711 } // namespace MMI
712 } // namespace OHOS
713