1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "input_event_handler.h"
17 
18 #include <cinttypes>
19 #include <cstdio>
20 #include <cstring>
21 #include <functional>
22 #include <vector>
23 
24 #include <sys/stat.h>
25 #include <unistd.h>
26 
27 #include "libinput.h"
28 #include "key_command_handler.h"
29 #include "timer_manager.h"
30 #include "util.h"
31 
32 #undef MMI_LOG_DOMAIN
33 #define MMI_LOG_DOMAIN MMI_LOG_HANDLER
34 #undef MMI_LOG_TAG
35 #define MMI_LOG_TAG "InputEventHandler"
36 
37 namespace OHOS {
38 namespace MMI {
39 namespace {
40 constexpr int32_t MT_TOOL_PALM { 2 };
41 constexpr uint32_t KEY_ESC { 1 };
42 constexpr uint32_t KEY_KPASTERISK { 55 };
43 constexpr uint32_t KEY_F1 { 59 };
44 constexpr uint32_t KEY_LEFTCTRL { 29 };
45 constexpr uint32_t KEY_RIGHTCTRL { 97 };
46 constexpr uint32_t KEY_LEFTALT { 56 };
47 constexpr uint32_t KEY_RIGHTALT { 100 };
48 constexpr uint32_t KEY_LEFTSHIFT { 42 };
49 constexpr uint32_t KEY_RIGHTSHIFT { 54 };
50 constexpr uint32_t KEY_FN { 0x1d0 };
51 constexpr uint32_t KEY_CAPSLOCK { 58 };
52 constexpr uint32_t KEY_TAB { 15 };
53 constexpr uint32_t KEY_COMPOSE { 127 };
54 constexpr uint32_t KEY_RIGHTMETA { 126 };
55 constexpr uint32_t KEY_LEFTMETA { 125 };
56 } // namespace
57 
InputEventHandler()58 InputEventHandler::InputEventHandler()
59 {
60     lastEventBeginTime_ = GetSysClockTime();
61     udsServer_ = nullptr;
62 }
63 
~InputEventHandler()64 InputEventHandler::~InputEventHandler() {}
65 
Init(UDSServer& udsServer)66 void InputEventHandler::Init(UDSServer& udsServer)
67 {
68     udsServer_ = &udsServer;
69     BuildInputHandlerChain();
70 }
71 
OnEvent(void *event, int64_t frameTime)72 void InputEventHandler::OnEvent(void *event, int64_t frameTime)
73 {
74     CHKPV(eventNormalizeHandler_);
75     if (event == nullptr) {
76         eventNormalizeHandler_->HandleEvent(nullptr, frameTime);
77         return;
78     }
79 
80     idSeed_ += 1;
81     const uint64_t maxUInt64 = (std::numeric_limits<uint64_t>::max)() - 1;
82     if (idSeed_ >= maxUInt64) {
83         MMI_HILOGE("The value is flipped. id:%{public}" PRId64, idSeed_);
84         idSeed_ = 1;
85     }
86 
87     auto *lpEvent = static_cast<libinput_event *>(event);
88     CHKPV(lpEvent);
89     int32_t eventType = libinput_event_get_type(lpEvent);
90     int64_t beginTime = GetSysClockTime();
91     lastEventBeginTime_ = beginTime;
92     MMI_HILOGD("Event reporting. id:%{public}" PRId64 ",tid:%{public}" PRId64 ",eventType:%{public}d,"
93                "beginTime:%{public}" PRId64, idSeed_, GetThisThreadId(), eventType, beginTime);
94 
95     UpdateDwtRecord(lpEvent);
96     if (IsTouchpadMistouch(lpEvent)) {
97         return;
98     }
99 
100     ResetLogTrace();
101     eventNormalizeHandler_->HandleEvent(lpEvent, frameTime);
102     int64_t endTime = GetSysClockTime();
103     int64_t lostTime = endTime - beginTime;
104     MMI_HILOGD("Event handling completed. id:%{public}" PRId64 ",endTime:%{public}" PRId64
105                ",lostTime:%{public}" PRId64, idSeed_, endTime, lostTime);
106 }
107 
UpdateDwtRecord(libinput_event *event)108 void InputEventHandler::UpdateDwtRecord(libinput_event *event)
109 {
110     CHKPV(event);
111     auto type = libinput_event_get_type(event);
112     if (type == LIBINPUT_EVENT_TOUCHPAD_DOWN || type == LIBINPUT_EVENT_TOUCHPAD_MOTION) {
113         UpdateDwtTouchpadRecord(event);
114     }
115     if (type == LIBINPUT_EVENT_KEYBOARD_KEY) {
116         UpdateDwtKeyboardRecord(event);
117     }
118 }
119 
UpdateDwtTouchpadRecord(libinput_event *event)120 void InputEventHandler::UpdateDwtTouchpadRecord(libinput_event *event)
121 {
122     auto touchpadEvent = libinput_event_get_touchpad_event(event);
123     CHKPV(touchpadEvent);
124     auto type = libinput_event_get_type(event);
125     if (type == LIBINPUT_EVENT_TOUCHPAD_DOWN) {
126         auto touchpadDevice = libinput_event_get_device(event); // guaranteed valid during event lifetime
127         CHKPV(touchpadDevice);
128         double touchpadSizeX;
129         double touchpadSizeY;
130         if (libinput_device_get_size(touchpadDevice, &touchpadSizeX, &touchpadSizeY) != 0) {
131             MMI_HILOGW("failed to get touchpad device size");
132             return;
133         }
134         touchpadEventDownAbsX_ = libinput_event_touchpad_get_x(touchpadEvent);
135         touchpadEventDownAbsY_ = libinput_event_touchpad_get_y(touchpadEvent);
136         touchpadEventAbsX_ = touchpadEventDownAbsX_;
137         touchpadEventAbsY_ = touchpadEventDownAbsY_;
138         if (touchpadEventDownAbsX_ > TOUCHPAD_EDGE_WIDTH &&
139             touchpadEventDownAbsX_ < touchpadSizeX - TOUCHPAD_EDGE_WIDTH) {
140             isDwtEdgeAreaForTouchpadMotionActing_ = false;
141             MMI_HILOGD("Pointer edge dwt unlocked, coordX = %{public}f", touchpadEventDownAbsX_);
142         }
143         if (touchpadEventDownAbsX_ > TOUCHPAD_EDGE_WIDTH_FOR_BUTTON &&
144             touchpadEventDownAbsX_ < touchpadSizeX - TOUCHPAD_EDGE_WIDTH_FOR_BUTTON) {
145             isDwtEdgeAreaForTouchpadButtonActing_ = false;
146             MMI_HILOGD("Button edge dwt unlocked, coordX = %{public}f", touchpadEventDownAbsX_);
147         }
148         if (touchpadEventDownAbsX_ > TOUCHPAD_EDGE_WIDTH_FOR_TAP &&
149             touchpadEventDownAbsX_ < touchpadSizeX - TOUCHPAD_EDGE_WIDTH_FOR_TAP) {
150             isDwtEdgeAreaForTouchpadTapActing_ = false;
151             MMI_HILOGD("Tap edge dwt unlocked, coordX = %{public}f", touchpadEventDownAbsX_);
152         }
153     }
154     if (type == LIBINPUT_EVENT_TOUCHPAD_MOTION) {
155         touchpadEventAbsX_ = libinput_event_touchpad_get_x(touchpadEvent);
156         touchpadEventAbsY_ = libinput_event_touchpad_get_y(touchpadEvent);
157     }
158 }
159 
UpdateDwtKeyboardRecord(libinput_event *event)160 void InputEventHandler::UpdateDwtKeyboardRecord(libinput_event *event)
161 {
162     auto keyboardEvent = libinput_event_get_keyboard_event(event);
163     CHKPV(keyboardEvent);
164     uint32_t key = libinput_event_keyboard_get_key(keyboardEvent);
165     if (IsStandaloneFunctionKey(key)) {
166         return;
167     }
168 
169     auto keyState = libinput_event_keyboard_get_key_state(keyboardEvent);
170     if (IsModifierKey(key)) {
171         modifierPressedCount_ += (keyState == LIBINPUT_KEY_STATE_PRESSED) ? 1 : -1;
172     }
173     if (keyState == LIBINPUT_KEY_STATE_PRESSED && modifierPressedCount_ > 0) {
174         isKeyPressedWithAnyModifiers_[key] = true; // set flag when key is pressed with modifiers
175     }
176     if (!IsModifierKey(key) && !isKeyPressedWithAnyModifiers_[key]) {
177         RefreshDwtActingState();
178     }
179     if (keyState == LIBINPUT_KEY_STATE_RELEASED) {
180         isKeyPressedWithAnyModifiers_[key] = false; // always reset flag when key is released
181     }
182 }
183 
IsStandaloneFunctionKey(uint32_t keycode)184 bool InputEventHandler::IsStandaloneFunctionKey(uint32_t keycode)
185 {
186     if (IsModifierKey(keycode)) {
187         return false;
188     }
189     switch (keycode) {
190         case KEY_ESC:
191         case KEY_KPASTERISK:
192             return true;
193         default:
194             return keycode >= KEY_F1;
195     }
196 }
197 
IsModifierKey(uint32_t keycode)198 bool InputEventHandler::IsModifierKey(uint32_t keycode)
199 {
200     switch (keycode) {
201         case KEY_LEFTCTRL:
202         case KEY_RIGHTCTRL:
203         case KEY_LEFTALT:
204         case KEY_RIGHTALT:
205         case KEY_LEFTSHIFT:
206         case KEY_RIGHTSHIFT:
207         case KEY_FN:
208         case KEY_CAPSLOCK:
209         case KEY_TAB:
210         case KEY_COMPOSE:
211         case KEY_RIGHTMETA:
212         case KEY_LEFTMETA:
213             return true;
214         default:
215             return false;
216     }
217 }
218 
RefreshDwtActingState()219 void InputEventHandler::RefreshDwtActingState()
220 {
221     isDwtEdgeAreaForTouchpadMotionActing_ = true;
222     isDwtEdgeAreaForTouchpadButtonActing_ = true;
223     isDwtEdgeAreaForTouchpadTapActing_ = true;
224 }
225 
IsTouchpadMistouch(libinput_event *event)226 bool InputEventHandler::IsTouchpadMistouch(libinput_event *event)
227 {
228     CHKPF(event);
229     auto type = libinput_event_get_type(event);
230     if (type >= LIBINPUT_EVENT_TOUCHPAD_DOWN && type <= LIBINPUT_EVENT_TOUCHPAD_MOTION) {
231         auto touchpadEvent = libinput_event_get_touchpad_event(event);
232         CHKPF(touchpadEvent);
233         int32_t toolType = libinput_event_touchpad_get_tool_type(touchpadEvent);
234         if (toolType == MT_TOOL_PALM) {
235             MMI_HILOGD("Touchpad event is palm");
236             return false;
237         }
238     }
239 
240     if (type == LIBINPUT_EVENT_POINTER_BUTTON_TOUCHPAD) {
241         return IsTouchpadButtonMistouch(event);
242     }
243     if (type == LIBINPUT_EVENT_POINTER_TAP) {
244         return IsTouchpadTapMistouch(event);
245     }
246     if (type == LIBINPUT_EVENT_TOUCHPAD_MOTION) {
247         return IsTouchpadMotionMistouch(event);
248     }
249     if (type == LIBINPUT_EVENT_POINTER_MOTION_TOUCHPAD) {
250         return IsTouchpadPointerMotionMistouch(event);
251     }
252 
253     return false;
254 }
255 
IsTouchpadButtonMistouch(libinput_event* event)256 bool InputEventHandler::IsTouchpadButtonMistouch(libinput_event* event)
257 {
258     CHKPF(event);
259     auto touchpadButtonEvent = libinput_event_get_pointer_event(event);
260     CHKPF(touchpadButtonEvent);
261     auto buttonState = libinput_event_pointer_get_button_state(touchpadButtonEvent);
262     if (buttonState == LIBINPUT_BUTTON_STATE_PRESSED) {
263         auto touchpadDevice = libinput_event_get_device(event); // guaranteed valid during event lifetime
264         CHKPF(touchpadDevice);
265         double touchpadSizeX;
266         double touchpadSizeY;
267         if (libinput_device_get_size(touchpadDevice, &touchpadSizeX, &touchpadSizeY) != 0) {
268             return false;
269         }
270         double coordX = touchpadEventAbsX_;
271         if (isDwtEdgeAreaForTouchpadButtonActing_ &&
272             (coordX <= TOUCHPAD_EDGE_WIDTH_FOR_BUTTON || coordX >= touchpadSizeX - TOUCHPAD_EDGE_WIDTH_FOR_BUTTON)) {
273             isButtonMistouch_ = true;
274             MMI_HILOGD("The buttonPressed event is mistouch");
275             return true;
276         }
277     }
278     if (buttonState == LIBINPUT_BUTTON_STATE_RELEASED) {
279         if (isButtonMistouch_) {
280             isButtonMistouch_ = false;
281             MMI_HILOGD("The buttonReleased event is mistouch");
282             return true;
283         }
284     }
285     return false;
286 }
287 
IsTouchpadTapMistouch(libinput_event* event)288 bool InputEventHandler::IsTouchpadTapMistouch(libinput_event* event)
289 {
290     CHKPF(event);
291     auto data = libinput_event_get_pointer_event(event);
292     CHKPF(data);
293     auto state = libinput_event_pointer_get_button_state(data);
294     if (state == LIBINPUT_BUTTON_STATE_PRESSED) {
295         auto touchpadDevice = libinput_event_get_device(event); // guaranteed valid during event lifetime
296         CHKPF(touchpadDevice);
297         double touchpadSizeX;
298         double touchpadSizeY;
299         if (libinput_device_get_size(touchpadDevice, &touchpadSizeX, &touchpadSizeY) != 0) {
300             return false;
301         }
302         double coordX = touchpadEventDownAbsX_;
303         if (isDwtEdgeAreaForTouchpadTapActing_ &&
304             (coordX <= TOUCHPAD_EDGE_WIDTH_FOR_TAP || coordX >= touchpadSizeX - TOUCHPAD_EDGE_WIDTH_FOR_TAP)) {
305             isTapMistouch_ = true;
306             MMI_HILOGD("Touchpad tap presse event is mistouch");
307             return true;
308         }
309     }
310     if (state == LIBINPUT_BUTTON_STATE_RELEASED) {
311         if (isTapMistouch_) {
312             isTapMistouch_ = false;
313             MMI_HILOGD("Touchpad tap release event is mistouch");
314             return true;
315         }
316     }
317     return false;
318 }
319 
IsTouchpadMotionMistouch(libinput_event *event)320 bool InputEventHandler::IsTouchpadMotionMistouch(libinput_event *event)
321 {
322     if (!isDwtEdgeAreaForTouchpadMotionActing_) {
323         return false;
324     }
325 
326     CHKPF(event);
327     auto touchpadEvent = libinput_event_get_touchpad_event(event);
328     CHKPF(touchpadEvent);
329     auto touchpadDevice = libinput_event_get_device(event); // guaranteed valid during event lifetime
330     CHKPF(touchpadDevice);
331     double touchpadSizeX;
332     double touchpadSizeY;
333     if (libinput_device_get_size(touchpadDevice, &touchpadSizeX, &touchpadSizeY) != 0) {
334         return false;
335     }
336     auto coordX = touchpadEventDownAbsX_;
337     if (coordX <= TOUCHPAD_EDGE_WIDTH || coordX >= touchpadSizeX - TOUCHPAD_EDGE_WIDTH) {
338         MMI_HILOGD("Touchpad event is edge mistouch");
339         return true;
340     }
341     return false;
342 }
343 
IsTouchpadPointerMotionMistouch(libinput_event *event)344 bool InputEventHandler::IsTouchpadPointerMotionMistouch(libinput_event *event)
345 {
346     if (!isDwtEdgeAreaForTouchpadMotionActing_) {
347         return false;
348     }
349 
350     CHKPF(event);
351     auto pointerEvent = libinput_event_get_pointer_event(event);
352     CHKPF(pointerEvent);
353     auto touchpadDevice = libinput_event_get_device(event); // guaranteed valid during event lifetime
354     CHKPF(touchpadDevice);
355     double touchpadSizeX;
356     double touchpadSizeY;
357     if (libinput_device_get_size(touchpadDevice, &touchpadSizeX, &touchpadSizeY) != 0) {
358         return false;
359     }
360     double coordX = touchpadEventDownAbsX_;
361     if (coordX <= TOUCHPAD_EDGE_WIDTH || coordX >= touchpadSizeX - TOUCHPAD_EDGE_WIDTH) {
362         MMI_HILOGD("Touchpad pointer motion event is edge mistouch");
363         return true;
364     }
365     return false;
366 }
367 
BuildInputHandlerChain()368 int32_t InputEventHandler::BuildInputHandlerChain()
369 {
370     eventNormalizeHandler_ = std::make_shared<EventNormalizeHandler>();
371 #if !defined(OHOS_BUILD_ENABLE_KEYBOARD) && !defined(OHOS_BUILD_ENABLE_POINTER) && !defined(OHOS_BUILD_ENABLE_TOUCH)
372     return RET_OK;
373 #endif // !OHOS_BUILD_ENABLE_KEYBOARD && !OHOS_BUILD_ENABLE_POINTER && !OHOS_BUILD_ENABLE_TOUCH
374 
375     std::shared_ptr<IInputEventHandler> handler = eventNormalizeHandler_;
376 #if defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH)
377     eventFilterHandler_ = std::make_shared<EventFilterHandler>();
378     handler->SetNext(eventFilterHandler_);
379     handler = eventFilterHandler_;
380 #endif // OHOS_BUILD_ENABLE_POINTER || OHOS_BUILD_ENABLE_TOUCH
381 
382 #ifdef OHOS_BUILD_ENABLE_INTERCEPTOR
383     eventInterceptorHandler_ = std::make_shared<EventInterceptorHandler>();
384     handler->SetNext(eventInterceptorHandler_);
385     handler = eventInterceptorHandler_;
386 #endif // OHOS_BUILD_ENABLE_INTERCEPTOR
387 
388 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
389 #ifdef OHOS_BUILD_ENABLE_COMBINATION_KEY
390     eventKeyCommandHandler_ = std::make_shared<KeyCommandHandler>();
391     handler->SetNext(eventKeyCommandHandler_);
392     handler = eventKeyCommandHandler_;
393 #endif // OHOS_BUILD_ENABLE_COMBINATION_KEY
394     eventSubscriberHandler_ = std::make_shared<KeySubscriberHandler>();
395     handler->SetNext(eventSubscriberHandler_);
396     handler = eventSubscriberHandler_;
397 #endif // OHOS_BUILD_ENABLE_KEYBOARD
398 #ifdef OHOS_BUILD_ENABLE_SWITCH
399     switchEventSubscriberHandler_ = std::make_shared<SwitchSubscriberHandler>();
400     handler->SetNext(switchEventSubscriberHandler_);
401     handler = switchEventSubscriberHandler_;
402 #endif // OHOS_BUILD_ENABLE_SWITCH
403 #ifdef OHOS_BUILD_ENABLE_MONITOR
404     eventMonitorHandler_ = std::make_shared<EventMonitorHandler>();
405     handler->SetNext(eventMonitorHandler_);
406     handler = eventMonitorHandler_;
407 #endif // OHOS_BUILD_ENABLE_MONITOR
408     eventDispatchHandler_ = std::make_shared<EventDispatchHandler>();
409     handler->SetNext(eventDispatchHandler_);
410     return RET_OK;
411 }
412 
GetIntervalSinceLastInput(int64_t &timeInterval)413 int32_t InputEventHandler::GetIntervalSinceLastInput(int64_t &timeInterval)
414 {
415     int64_t currentSystemTime = GetSysClockTime();
416     timeInterval = currentSystemTime - lastEventBeginTime_;
417     return RET_OK;
418 }
419 
GetUDSServer() const420 UDSServer* InputEventHandler::GetUDSServer() const
421 {
422     return udsServer_;
423 }
424 
GetEventNormalizeHandler() const425 std::shared_ptr<EventNormalizeHandler> InputEventHandler::GetEventNormalizeHandler() const
426 {
427     return eventNormalizeHandler_;
428 }
429 
GetInterceptorHandler() const430 std::shared_ptr<EventInterceptorHandler> InputEventHandler::GetInterceptorHandler() const
431 {
432     return eventInterceptorHandler_;
433 }
434 
GetSubscriberHandler() const435 std::shared_ptr<KeySubscriberHandler> InputEventHandler::GetSubscriberHandler() const
436 {
437     return eventSubscriberHandler_;
438 }
439 
GetSwitchSubscriberHandler() const440 std::shared_ptr<SwitchSubscriberHandler> InputEventHandler::GetSwitchSubscriberHandler() const
441 {
442     return switchEventSubscriberHandler_;
443 }
444 
GetKeyCommandHandler() const445 std::shared_ptr<KeyCommandHandler> InputEventHandler::GetKeyCommandHandler() const
446 {
447     return eventKeyCommandHandler_;
448 }
449 
GetMonitorHandler() const450 std::shared_ptr<EventMonitorHandler> InputEventHandler::GetMonitorHandler() const
451 {
452     return eventMonitorHandler_;
453 }
454 
GetFilterHandler() const455 std::shared_ptr<EventFilterHandler> InputEventHandler::GetFilterHandler() const
456 {
457     return eventFilterHandler_;
458 }
459 
GetEventDispatchHandler() const460 std::shared_ptr<EventDispatchHandler> InputEventHandler::GetEventDispatchHandler() const
461 {
462     return eventDispatchHandler_;
463 }
464 
SetMoveEventFilters(bool flag)465 int32_t InputEventHandler::SetMoveEventFilters(bool flag)
466 {
467     CALL_INFO_TRACE;
468 #ifdef OHOS_BUILD_ENABLE_MOVE_EVENT_FILTERS
469     CHKPR(eventNormalizeHandler_, INVALID_HANDLER_ID);
470     return eventNormalizeHandler_->SetMoveEventFilters(flag);
471 #else
472     MMI_HILOGW("Set move event filters does not support");
473     return ERROR_UNSUPPORT;
474 #endif // OHOS_BUILD_ENABLE_MOVE_EVENT_FILTERS
475 }
476 } // namespace MMI
477 } // namespace OHOS