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