1 /*
2  * Copyright (c) 2021-2023 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 "event_dispatch_handler.h"
17 
18 #include <cinttypes>
19 
20 #include <linux/input-event-codes.h>
21 
22 #include "transaction/rs_interfaces.h"
23 
24 #include "anr_manager.h"
25 #include "app_debug_listener.h"
26 #include "bytrace_adapter.h"
27 #include "dfx_hisysevent.h"
28 #include "error_multimodal.h"
29 #include "event_log_helper.h"
30 #include "input_event_data_transformation.h"
31 #include "input_event_handler.h"
32 #include "i_input_windows_manager.h"
33 #include "mouse_device_state.h"
34 #include "napi_constants.h"
35 #include "proto.h"
36 #include "util.h"
37 
38 #undef MMI_LOG_DOMAIN
39 #define MMI_LOG_DOMAIN MMI_LOG_DISPATCH
40 #undef MMI_LOG_TAG
41 #define MMI_LOG_TAG "EventDispatchHandler"
42 
43 namespace OHOS {
44 namespace MMI {
45 namespace {
46 constexpr int64_t ERROR_TIME {3000000};
47 constexpr int32_t INTERVAL_TIME { 3000 }; // log time interval is 3 seconds.
48 constexpr int32_t INTERVAL_DURATION { 10 };
49 constexpr int32_t THREE_FINGERS { 3 };
50 } // namespace
51 
52 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
HandleKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)53 void EventDispatchHandler::HandleKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)
54 {
55     CHKPV(keyEvent);
56     auto udsServer = InputHandler->GetUDSServer();
57     CHKPV(udsServer);
58     DispatchKeyEventPid(*udsServer, keyEvent);
59 }
60 #endif // OHOS_BUILD_ENABLE_KEYBOARD
61 
62 #ifdef OHOS_BUILD_ENABLE_POINTER
HandlePointerEvent(const std::shared_ptr<PointerEvent> pointerEvent)63 void EventDispatchHandler::HandlePointerEvent(const std::shared_ptr<PointerEvent> pointerEvent)
64 {
65     CHKPV(pointerEvent);
66     HandlePointerEventInner(pointerEvent);
67 }
68 #endif // OHOS_BUILD_ENABLE_POINTER
69 
70 #ifdef OHOS_BUILD_ENABLE_TOUCH
HandleTouchEvent(const std::shared_ptr<PointerEvent> pointerEvent)71 void EventDispatchHandler::HandleTouchEvent(const std::shared_ptr<PointerEvent> pointerEvent)
72 {
73     CHKPV(pointerEvent);
74     HandlePointerEventInner(pointerEvent);
75 }
76 #endif // OHOS_BUILD_ENABLE_TOUCH
77 
78 #if defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH)
FilterInvalidPointerItem(const std::shared_ptr<PointerEvent> pointerEvent, int32_t fd)79 void EventDispatchHandler::FilterInvalidPointerItem(const std::shared_ptr<PointerEvent> pointerEvent, int32_t fd)
80 {
81     CHKPV(pointerEvent);
82     auto udsServer = InputHandler->GetUDSServer();
83     CHKPV(udsServer);
84     auto pointerIdList = pointerEvent->GetPointerIds();
85     if (pointerIdList.size() > 1) {
86         for (const auto& id : pointerIdList) {
87             PointerEvent::PointerItem pointeritem;
88             if (!pointerEvent->GetPointerItem(id, pointeritem)) {
89                 MMI_HILOGW("Can't find this pointerItem");
90                 continue;
91             }
92             auto itemPid = WIN_MGR->GetWindowPid(pointeritem.GetTargetWindowId());
93             if ((itemPid >= 0) && (itemPid != udsServer->GetClientPid(fd))) {
94                 pointerEvent->RemovePointerItem(id);
95                 MMI_HILOGD("pointerIdList size:%{public}zu", pointerEvent->GetPointerIds().size());
96             }
97         }
98     }
99 }
100 
SearchCancelList(int32_t pointerId, int32_t windowId)101 std::shared_ptr<WindowInfo> EventDispatchHandler::SearchCancelList (int32_t pointerId, int32_t windowId)
102 {
103     if (cancelEventList_.find(pointerId) == cancelEventList_.end()) {
104         return nullptr;
105     }
106     auto windowList = cancelEventList_[pointerId];
107     for (auto &info : windowList) {
108         if (info->id == windowId) {
109             return info;
110         }
111     }
112     return nullptr;
113 }
114 
ReissueEvent(std::shared_ptr<PointerEvent> &point, int32_t windowId, std::optional<WindowInfo> &windowInfo)115 bool EventDispatchHandler::ReissueEvent(std::shared_ptr<PointerEvent> &point, int32_t windowId,
116     std::optional<WindowInfo> &windowInfo)
117 {
118     int32_t pointerId = point->GetPointerId();
119     if (windowInfo == std::nullopt) {
120         std::shared_ptr<WindowInfo> curInfo = SearchCancelList(pointerId, windowId);
121         if (curInfo != nullptr && point->GetPointerAction() == PointerEvent::POINTER_ACTION_UP) {
122             point->SetPointerAction(PointerEvent::POINTER_ACTION_CANCEL);
123             windowInfo = std::make_optional(*curInfo);
124             MMI_HILOG_DISPATCHI("Touch event send cancel to window:%{public}d", windowId);
125         } else {
126             if (point->GetPointerAction() != PointerEvent::POINTER_ACTION_MOVE) {
127                 MMI_HILOGE("Window:%{public}d is nullptr", windowId);
128             }
129             return false;
130         }
131     }
132     std::shared_ptr<WindowInfo> curWindowInfo = std::make_shared<WindowInfo>(*windowInfo);
133     if (point->GetPointerAction() == PointerEvent::POINTER_ACTION_DOWN) {
134         if (cancelEventList_.find(pointerId) == cancelEventList_.end()) {
135             cancelEventList_[pointerId] = std::set<std::shared_ptr<WindowInfo>, EventDispatchHandler::CancelCmp>();
136         }
137         cancelEventList_[pointerId].insert(curWindowInfo);
138     } else if (point->GetPointerAction() == PointerEvent::POINTER_ACTION_UP ||
139         point->GetPointerAction() == PointerEvent::POINTER_ACTION_CANCEL) {
140         if (cancelEventList_.find(pointerId) != cancelEventList_.end() &&
141             cancelEventList_[pointerId].find(curWindowInfo) != cancelEventList_[pointerId].end()) {
142             cancelEventList_[pointerId].erase(curWindowInfo);
143         } else {
144             return false;
145         }
146     }
147     return true;
148 }
149 
HandleMultiWindowPointerEvent(std::shared_ptr<PointerEvent> point, PointerEvent::PointerItem pointerItem)150 void EventDispatchHandler::HandleMultiWindowPointerEvent(std::shared_ptr<PointerEvent> point,
151     PointerEvent::PointerItem pointerItem)
152 {
153     CALL_DEBUG_ENTER;
154     CHKPV(point);
155     std::vector<int32_t> windowIds;
156     WIN_MGR->GetTargetWindowIds(pointerItem.GetPointerId(), point->GetSourceType(), windowIds);
157     int32_t count = 0;
158     int32_t pointerId = point->GetPointerId();
159     if (point->GetPointerAction() == PointerEvent::POINTER_ACTION_DOWN) {
160         if (cancelEventList_.find(pointerId) != cancelEventList_.end()) {
161             cancelEventList_.erase(pointerId);
162         }
163     }
164     for (auto windowId : windowIds) {
165         auto pointerEvent = std::make_shared<PointerEvent>(*point);
166         auto windowInfo = WIN_MGR->GetWindowAndDisplayInfo(windowId, point->GetTargetDisplayId());
167         if (!ReissueEvent(pointerEvent, windowId, windowInfo)) {
168             continue;
169         }
170         if (!windowInfo) {
171             continue;
172         }
173         if (pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_PULL_UP &&
174             windowInfo->windowInputType == WindowInputType::TRANSMIT_ALL && windowIds.size() > 1) {
175             MMI_HILOGD("When the drag is finished, the multi-window distribution is canceled. window:%{public}d,"
176                 "windowInputType:%{public}d", windowId, static_cast<int32_t>(windowInfo->windowInputType));
177             pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_CANCEL);
178         }
179         auto fd = WIN_MGR->GetClientFd(pointerEvent, windowInfo->id);
180         if (fd < 0) {
181             auto udsServer = InputHandler->GetUDSServer();
182             CHKPV(udsServer);
183             fd = udsServer->GetClientFd(windowInfo->pid);
184             MMI_HILOGI("Window:%{public}d exit front desk, windowfd:%{public}d", windowId, fd);
185         }
186         pointerEvent->SetTargetWindowId(windowId);
187         pointerEvent->SetAgentWindowId(windowInfo->agentWindowId);
188         int32_t windowX = pointerItem.GetDisplayX() - windowInfo->area.x;
189         int32_t windowY = pointerItem.GetDisplayY() - windowInfo->area.y;
190         if (!windowInfo->transform.empty()) {
191             auto windowXY = WIN_MGR->TransformWindowXY(*windowInfo, pointerItem.GetDisplayX(),
192                 pointerItem.GetDisplayY());
193             windowX = windowXY.first;
194             windowY = windowXY.second;
195         }
196         pointerItem.SetWindowX(windowX);
197         pointerItem.SetWindowY(windowY);
198         pointerItem.SetTargetWindowId(windowId);
199         pointerEvent->UpdatePointerItem(pointerId, pointerItem);
200         pointerEvent->SetDispatchTimes(count++);
201         DispatchPointerEventInner(pointerEvent, fd);
202     }
203     if (point->GetPointerAction() == PointerEvent::POINTER_ACTION_UP ||
204         point->GetPointerAction() == PointerEvent::POINTER_ACTION_PULL_UP ||
205         point->GetPointerAction() == PointerEvent::POINTER_ACTION_CANCEL ||
206         point->GetPointerAction() == PointerEvent::POINTER_ACTION_HOVER_EXIT) {
207         WIN_MGR->ClearTargetWindowId(pointerId);
208     }
209 }
210 
NotifyPointerEventToRS(int32_t pointAction, const std::string& programName, uint32_t pid, int32_t pointCnt)211 void EventDispatchHandler::NotifyPointerEventToRS(int32_t pointAction, const std::string& programName,
212     uint32_t pid, int32_t pointCnt)
213 {
214     OHOS::Rosen::RSInterfaces::GetInstance().NotifyTouchEvent(pointAction, pointCnt);
215 }
216 
AcquireEnableMark(std::shared_ptr<PointerEvent> event)217 bool EventDispatchHandler::AcquireEnableMark(std::shared_ptr<PointerEvent> event)
218 {
219     auto currentEventTime = std::chrono::high_resolution_clock::now();
220     int64_t tm64Cost = std::chrono::duration_cast<std::chrono::milliseconds>(
221         std::chrono::high_resolution_clock::now() - LasteventBeginTime_).count();
222 
223     if (event->GetPointerAction() == PointerEvent::POINTER_ACTION_PULL_MOVE
224         || event->GetPointerAction() == PointerEvent::POINTER_ACTION_MOVE) {
225         enableMark_ = (tm64Cost > INTERVAL_DURATION) ? true : false;
226         if (enableMark_) {
227             LasteventBeginTime_ = currentEventTime;
228         }
229         MMI_HILOGD("Id:%{public}d, markEnabled:%{public}d", event->GetId(), enableMark_);
230         return enableMark_;
231     }
232     return true;
233 }
234 
SendWindowStateError(int32_t pid, int32_t windowId)235 void EventDispatchHandler::SendWindowStateError(int32_t pid, int32_t windowId)
236 {
237     CALL_DEBUG_ENTER;
238     auto udsServer = InputHandler->GetUDSServer();
239     auto sess = udsServer->GetSessionByPid(WIN_MGR->GetWindowStateNotifyPid());
240     if (sess != nullptr) {
241         NetPacket pkt(MmiMessageId::WINDOW_STATE_ERROR_NOTIFY);
242         pkt << pid << windowId;
243         if (!sess->SendMsg(pkt)) {
244             MMI_HILOGE("SendMsg failed");
245             return;
246         }
247         windowStateErrorInfo_.windowId = -1;
248         windowStateErrorInfo_.startTime = -1;
249         windowStateErrorInfo_.pid = -1;
250     }
251 }
252 
HandlePointerEventInner(const std::shared_ptr<PointerEvent> point)253 void EventDispatchHandler::HandlePointerEventInner(const std::shared_ptr<PointerEvent> point)
254 {
255     CALL_DEBUG_ENTER;
256     CHKPV(point);
257 #ifdef OHOS_BUILD_ENABLE_ANCO
258     if (point->GetAncoDeal()) {
259         MMI_HILOGD("event dealed by anco, ignore it");
260         return;
261     }
262 #endif // OHOS_BUILD_ENABLE_ANCO
263     int32_t pointerId = point->GetPointerId();
264     PointerEvent::PointerItem pointerItem;
265     if (!point->GetPointerItem(pointerId, pointerItem)) {
266         MMI_HILOGE("Can't find pointer item, pointer:%{public}d", pointerId);
267         return;
268     }
269     std::vector<int32_t> windowIds;
270     WIN_MGR->GetTargetWindowIds(pointerItem.GetPointerId(), point->GetSourceType(), windowIds);
271     if (!windowIds.empty()) {
272         HandleMultiWindowPointerEvent(point, pointerItem);
273         return;
274     }
275     auto udsServer = InputHandler->GetUDSServer();
276     auto fd = WIN_MGR->GetClientFd(point);
277     auto pid = WIN_MGR->GetPidByWindowId(point->GetTargetWindowId());
278     if (WIN_MGR->GetCancelEventFlag(point) && udsServer->GetSession(fd) == nullptr &&
279         pid != -1 && point->GetTargetWindowId() != -1) {
280         if (point->GetTargetWindowId() == windowStateErrorInfo_.windowId && pid == windowStateErrorInfo_.pid) {
281             if (GetSysClockTime() - windowStateErrorInfo_.startTime >= ERROR_TIME) {
282                 SendWindowStateError(pid, point->GetTargetWindowId());
283             }
284         } else {
285             windowStateErrorInfo_.windowId = point->GetTargetWindowId();
286             windowStateErrorInfo_.startTime = GetSysClockTime();
287             windowStateErrorInfo_.pid = pid;
288         }
289     }
290     DispatchPointerEventInner(point, fd);
291 }
292 
DispatchPointerEventInner(std::shared_ptr<PointerEvent> point, int32_t fd)293 void EventDispatchHandler::DispatchPointerEventInner(std::shared_ptr<PointerEvent> point, int32_t fd)
294 {
295     currentTime_ = point->GetActionTime();
296     if (fd < 0 && currentTime_ - eventTime_ > INTERVAL_TIME) {
297         eventTime_ = currentTime_;
298         if (point->GetPointerCount() < THREE_FINGERS &&
299             point->GetPointerAction() != PointerEvent::POINTER_ACTION_AXIS_UPDATE &&
300             point->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_UPDATE &&
301             point->GetPointerAction() != PointerEvent::POINTER_ACTION_MOVE) {
302             MMI_HILOGE("InputTracking id:%{public}d The fd less than 0, fd:%{public}d", point->GetId(), fd);
303         }
304         return;
305     }
306     auto udsServer = InputHandler->GetUDSServer();
307     CHKPV(udsServer);
308     auto sess = udsServer->GetSession(fd);
309     if (sess == nullptr) {
310         return;
311     }
312     auto currentTime = GetSysClockTime();
313     BytraceAdapter::StartBytrace(point, BytraceAdapter::TRACE_STOP);
314     if (ANRMgr->TriggerANR(ANR_DISPATCH, currentTime, sess)) {
315         MMI_HILOGD("The pointer event does not report normally,app not respon. PointerEvent(deviceid:%{public}d,"
316             "action:%{public}s)", point->GetDeviceId(), point->DumpPointerAction());
317         return;
318     }
319     auto pointerEvent = std::make_shared<PointerEvent>(*point);
320     pointerEvent->SetMarkEnabled(AcquireEnableMark(pointerEvent));
321     pointerEvent->SetSensorInputTime(point->GetSensorInputTime());
322     FilterInvalidPointerItem(pointerEvent, fd);
323     NetPacket pkt(MmiMessageId::ON_POINTER_EVENT);
324     InputEventDataTransformation::Marshalling(pointerEvent, pkt);
325 #ifdef OHOS_BUILD_ENABLE_SECURITY_COMPONENT
326     InputEventDataTransformation::MarshallingEnhanceData(pointerEvent, pkt);
327 #endif // OHOS_BUILD_ENABLE_SECURITY_COMPONENT
328     int32_t pointerAc = pointerEvent->GetPointerAction();
329     if (pointerAc == PointerEvent::POINTER_ACTION_PULL_DOWN || pointerAc == PointerEvent::POINTER_ACTION_UP ||
330         pointerAc == PointerEvent::POINTER_ACTION_DOWN || pointerAc == PointerEvent::POINTER_ACTION_PULL_UP) {
331         NotifyPointerEventToRS(pointerAc, sess->GetProgramName(),
332             static_cast<uint32_t>(sess->GetPid()), pointerEvent->GetPointerCount());
333     }
334     if (pointerAc != PointerEvent::POINTER_ACTION_MOVE && pointerAc != PointerEvent::POINTER_ACTION_AXIS_UPDATE &&
335         pointerAc != PointerEvent::POINTER_ACTION_ROTATE_UPDATE &&
336         pointerAc != PointerEvent::POINTER_ACTION_PULL_MOVE) {
337         MMI_HILOG_FREEZEI("SendMsg to %{public}s:pid:%{public}d, action:%{public}d",
338             sess->GetProgramName().c_str(), sess->GetPid(), pointerEvent->GetPointerAction());
339     }
340     if (!udsServer->SendMsg(fd, pkt)) {
341         MMI_HILOGE("Sending structure of EventTouch failed! errCode:%{public}d", MSG_SEND_FAIL);
342         return;
343     }
344     if (sess->GetPid() != AppDebugListener::GetInstance()->GetAppDebugPid() && pointerEvent->IsMarkEnabled()) {
345         MMI_HILOGD("Session pid:%{public}d", sess->GetPid());
346         ANRMgr->AddTimer(ANR_DISPATCH, point->GetId(), currentTime, sess);
347     }
348 }
349 #endif // OHOS_BUILD_ENABLE_POINTER || OHOS_BUILD_ENABLE_POINTER
350 
351 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
DispatchKeyEventPid(UDSServer& udsServer, std::shared_ptr<KeyEvent> key)352 int32_t EventDispatchHandler::DispatchKeyEventPid(UDSServer& udsServer, std::shared_ptr<KeyEvent> key)
353 {
354     CALL_DEBUG_ENTER;
355     CHKPR(key, PARAM_INPUT_INVALID);
356     int32_t ret = RET_OK;
357     // 1.Determine whether the key event is a focus type event or an operation type event,
358     // 2.Determine whether the current focus window has a safety sub window.
359     auto secSubWindowTargets = WIN_MGR->UpdateTarget(key);
360     for (const auto &item : secSubWindowTargets) {
361         key->ClearFlag(InputEvent::EVENT_FLAG_PRIVACY_MODE);
362         if (item.second.privacyMode == SecureFlag::PRIVACY_MODE) {
363             key->AddFlag(InputEvent::EVENT_FLAG_PRIVACY_MODE);
364         }
365         key->SetTargetWindowId(item.second.id);
366         key->SetAgentWindowId(item.second.agentWindowId);
367         ret = DispatchKeyEvent(item.first, udsServer, key);
368     }
369     return ret;
370 }
371 
DispatchKeyEvent(int32_t fd, UDSServer& udsServer, std::shared_ptr<KeyEvent> key)372 int32_t EventDispatchHandler::DispatchKeyEvent(int32_t fd, UDSServer& udsServer, std::shared_ptr<KeyEvent> key)
373 {
374     CALL_DEBUG_ENTER;
375     CHKPR(key, PARAM_INPUT_INVALID);
376     currentTime_ = key->GetActionTime();
377     if (fd < 0 && currentTime_ - eventTime_ > INTERVAL_TIME) {
378         eventTime_ = currentTime_;
379         MMI_HILOGE("Invalid fd, fd:%{public}d", fd);
380         DfxHisysevent::OnUpdateTargetKey(key, fd, OHOS::HiviewDFX::HiSysEvent::EventType::FAULT);
381         return RET_ERR;
382     }
383     MMI_HILOGD("Event dispatcher of server, KeyEvent:KeyCode:%{private}d, Action:%{public}d, EventType:%{public}d,"
384         "Fd:%{public}d", key->GetKeyCode(), key->GetAction(), key->GetEventType(), fd);
385     auto session = udsServer.GetSession(fd);
386     CHKPR(session, RET_ERR);
387     auto currentTime = GetSysClockTime();
388     if (ANRMgr->TriggerANR(ANR_DISPATCH, currentTime, session)) {
389         if (!EventLogHelper::IsBetaVersion()) {
390             MMI_HILOGW("The key event does not report normally, application not response."
391                 "KeyEvent(deviceid:%{public}d, key action:%{public}d)",
392                 key->GetDeviceId(), key->GetKeyAction());
393         } else {
394             MMI_HILOGW("The key event does not report normally, application not response."
395                 "KeyEvent(deviceid:%{public}d, keycode:%{private}d, key action:%{public}d)",
396                 key->GetDeviceId(), key->GetKeyCode(), key->GetKeyAction());
397         }
398         return RET_OK;
399     }
400 
401     NetPacket pkt(MmiMessageId::ON_KEY_EVENT);
402     InputEventDataTransformation::KeyEventToNetPacket(key, pkt);
403     BytraceAdapter::StartBytrace(key, BytraceAdapter::KEY_DISPATCH_EVENT);
404     pkt << fd;
405 
406 #ifdef OHOS_BUILD_ENABLE_SECURITY_COMPONENT
407     InputEventDataTransformation::MarshallingEnhanceData(key, pkt);
408 #endif // OHOS_BUILD_ENABLE_SECURITY_COMPONENT
409     if (pkt.ChkRWError()) {
410         MMI_HILOGE("Packet write structure of EventKeyboard failed");
411         return RET_ERR;
412     }
413     MMI_HILOGI("InputTracking id:%{public}d, SendMsg to %{public}s:pid:%{public}d",
414         key->GetId(), session->GetProgramName().c_str(), session->GetPid());
415     if (!udsServer.SendMsg(fd, pkt)) {
416         MMI_HILOGE("Sending structure of EventKeyboard failed! errCode:%{public}d", MSG_SEND_FAIL);
417         return MSG_SEND_FAIL;
418     }
419     if (session->GetPid() != AppDebugListener::GetInstance()->GetAppDebugPid()) {
420         MMI_HILOGD("Session pid:%{public}d", session->GetPid());
421         ANRMgr->AddTimer(ANR_DISPATCH, key->GetId(), currentTime, session);
422     }
423     return RET_OK;
424 }
425 #endif // OHOS_BUILD_ENABLE_KEYBOARD
426 } // namespace MMI
427 } // namespace OHOS
428