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 "event_monitor_handler.h"
17
18 #include "anr_manager.h"
19 #include "bytrace_adapter.h"
20 #include "define_multimodal.h"
21 #include "input_event_data_transformation.h"
22 #include "input_event_handler.h"
23 #include "mmi_log.h"
24 #include "napi_constants.h"
25 #include "net_packet.h"
26 #include "proto.h"
27 #include "util_ex.h"
28
29 namespace OHOS {
30 namespace MMI {
31 namespace {
32 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MMI_LOG_DOMAIN, "EventMonitorHandler" };
33 } // namespace
34
35 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
HandleKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)36 void EventMonitorHandler::HandleKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)
37 {
38 CHKPV(keyEvent);
39 OnHandleEvent(keyEvent);
40 CHKPV(nextHandler_);
41 nextHandler_->HandleKeyEvent(keyEvent);
42 }
43 #endif // OHOS_BUILD_ENABLE_KEYBOARD
44
45 #ifdef OHOS_BUILD_ENABLE_POINTER
HandlePointerEvent(const std::shared_ptr<PointerEvent> pointerEvent)46 void EventMonitorHandler::HandlePointerEvent(const std::shared_ptr<PointerEvent> pointerEvent)
47 {
48 CHKPV(pointerEvent);
49 if (OnHandleEvent(pointerEvent)) {
50 BytraceAdapter::StartBytrace(pointerEvent, BytraceAdapter::TRACE_STOP);
51 MMI_HILOGD("Monitor is succeeded");
52 return;
53 }
54 CHKPV(nextHandler_);
55 nextHandler_->HandlePointerEvent(pointerEvent);
56 }
57 #endif // OHOS_BUILD_ENABLE_POINTER
58
59 #ifdef OHOS_BUILD_ENABLE_TOUCH
HandleTouchEvent(const std::shared_ptr<PointerEvent> pointerEvent)60 void EventMonitorHandler::HandleTouchEvent(const std::shared_ptr<PointerEvent> pointerEvent)
61 {
62 CHKPV(pointerEvent);
63 if (OnHandleEvent(pointerEvent)) {
64 BytraceAdapter::StartBytrace(pointerEvent, BytraceAdapter::TRACE_STOP);
65 MMI_HILOGD("Monitor is succeeded");
66 return;
67 }
68 CHKPV(nextHandler_);
69 nextHandler_->HandleTouchEvent(pointerEvent);
70 }
71 #endif // OHOS_BUILD_ENABLE_TOUCH
72
AddInputHandler(InputHandlerType handlerType,HandleEventType eventType,SessionPtr session)73 int32_t EventMonitorHandler::AddInputHandler(InputHandlerType handlerType,
74 HandleEventType eventType, SessionPtr session)
75 {
76 CALL_INFO_TRACE;
77 CHKPR(session, RET_ERR);
78 if ((eventType & HANDLE_EVENT_TYPE_ALL) == HANDLE_EVENT_TYPE_NONE) {
79 MMI_HILOGE("Invalid event type");
80 return RET_ERR;
81 }
82 InitSessionLostCallback();
83 SessionHandler mon { handlerType, eventType, session };
84 return monitors_.AddMonitor(mon);
85 }
86
RemoveInputHandler(InputHandlerType handlerType,HandleEventType eventType,SessionPtr session)87 void EventMonitorHandler::RemoveInputHandler(InputHandlerType handlerType, HandleEventType eventType,
88 SessionPtr session)
89 {
90 CALL_INFO_TRACE;
91 if (handlerType == InputHandlerType::MONITOR) {
92 SessionHandler monitor { handlerType, eventType, session };
93 monitors_.RemoveMonitor(monitor);
94 }
95 }
96
MarkConsumed(int32_t eventId,SessionPtr session)97 void EventMonitorHandler::MarkConsumed(int32_t eventId, SessionPtr session)
98 {
99 monitors_.MarkConsumed(eventId, session);
100 }
101
102 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
OnHandleEvent(std::shared_ptr<KeyEvent> keyEvent)103 bool EventMonitorHandler::OnHandleEvent(std::shared_ptr<KeyEvent> keyEvent)
104 {
105 MMI_HILOGD("Handle KeyEvent");
106 CHKPF(keyEvent);
107 if (keyEvent->HasFlag(InputEvent::EVENT_FLAG_NO_MONITOR)) {
108 MMI_HILOGD("This event has been tagged as not to be monitored");
109 } else {
110 if (monitors_.HandleEvent(keyEvent)) {
111 MMI_HILOGD("Key event was consumed");
112 return true;
113 }
114 }
115 return false;
116 }
117 #endif // OHOS_BUILD_ENABLE_KEYBOARD
118
119 #if defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH)
OnHandleEvent(std::shared_ptr<PointerEvent> pointerEvent)120 bool EventMonitorHandler::OnHandleEvent(std::shared_ptr<PointerEvent> pointerEvent)
121 {
122 CHKPF(pointerEvent);
123 if (pointerEvent->HasFlag(InputEvent::EVENT_FLAG_NO_MONITOR)) {
124 MMI_HILOGD("This event has been tagged as not to be monitored");
125 } else {
126 if (monitors_.HandleEvent(pointerEvent)) {
127 MMI_HILOGD("Pointer event was monitor");
128 return true;
129 }
130 }
131 MMI_HILOGD("Interception and monitor failed");
132 return false;
133 }
134 #endif // OHOS_BUILD_ENABLE_POINTER || OHOS_BUILD_ENABLE_TOUCH
135
InitSessionLostCallback()136 void EventMonitorHandler::InitSessionLostCallback()
137 {
138 if (sessionLostCallbackInitialized_) {
139 return;
140 }
141 auto udsServerPtr = InputHandler->GetUDSServer();
142 CHKPV(udsServerPtr);
143 udsServerPtr->AddSessionDeletedCallback(std::bind(
144 &EventMonitorHandler::OnSessionLost, this, std::placeholders::_1));
145 sessionLostCallbackInitialized_ = true;
146 MMI_HILOGD("The callback on session deleted is registered successfully");
147 }
148
OnSessionLost(SessionPtr session)149 void EventMonitorHandler::OnSessionLost(SessionPtr session)
150 {
151 monitors_.OnSessionLost(session);
152 }
153
SendToClient(std::shared_ptr<KeyEvent> keyEvent) const154 void EventMonitorHandler::SessionHandler::SendToClient(std::shared_ptr<KeyEvent> keyEvent) const
155 {
156 CHKPV(keyEvent);
157 NetPacket pkt(MmiMessageId::REPORT_KEY_EVENT);
158 pkt << handlerType_;
159 if (pkt.ChkRWError()) {
160 MMI_HILOGE("Packet write key event failed");
161 return;
162 }
163 if (InputEventDataTransformation::KeyEventToNetPacket(keyEvent, pkt) != RET_OK) {
164 MMI_HILOGE("Packet key event failed, errCode:%{public}d", STREAM_BUF_WRITE_FAIL);
165 return;
166 }
167 if (!session_->SendMsg(pkt)) {
168 MMI_HILOGE("Send message failed, errCode:%{public}d", MSG_SEND_FAIL);
169 return;
170 }
171 }
172
SendToClient(std::shared_ptr<PointerEvent> pointerEvent) const173 void EventMonitorHandler::SessionHandler::SendToClient(std::shared_ptr<PointerEvent> pointerEvent) const
174 {
175 CHKPV(pointerEvent);
176 CHKPV(session_);
177 NetPacket pkt(MmiMessageId::REPORT_POINTER_EVENT);
178 MMI_HILOGD("Service SendToClient InputHandlerType:%{public}d,TokenType:%{public}d, pid:%{public}d",
179 handlerType_, session_->GetTokenType(), session_->GetPid());
180 auto currentTime = GetSysClockTime();
181 if (pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
182 if (ANRMgr->TriggerANR(ANR_MONITOR, currentTime, session_)) {
183 MMI_HILOGW("The pointer event does not report normally, application not response");
184 return;
185 }
186 }
187 pkt << handlerType_;
188 if (pkt.ChkRWError()) {
189 MMI_HILOGE("Packet write pointer event failed");
190 return;
191 }
192 if (InputEventDataTransformation::Marshalling(pointerEvent, pkt) != RET_OK) {
193 MMI_HILOGE("Marshalling pointer event failed, errCode:%{public}d", STREAM_BUF_WRITE_FAIL);
194 return;
195 }
196 if (!session_->SendMsg(pkt)) {
197 MMI_HILOGE("Send message failed, errCode:%{public}d", MSG_SEND_FAIL);
198 return;
199 }
200 if (pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
201 ANRMgr->AddTimer(ANR_MONITOR, pointerEvent->GetId(), currentTime, session_);
202 }
203 }
204
AddMonitor(const SessionHandler & monitor)205 int32_t EventMonitorHandler::MonitorCollection::AddMonitor(const SessionHandler& monitor)
206 {
207 if (monitors_.size() >= MAX_N_INPUT_MONITORS) {
208 MMI_HILOGE("The number of monitors exceeds the maximum:%{public}zu,monitors,errCode:%{public}d",
209 monitors_.size(), INVALID_MONITOR_MON);
210 return RET_ERR;
211 }
212 bool isFound = false;
213 auto iter = monitors_.find(monitor);
214 if (iter != monitors_.end()) {
215 if (iter->eventType_ == monitor.eventType_) {
216 MMI_HILOGD("Monitor with event type (%{public}u) already exists", monitor.eventType_);
217 return RET_OK;
218 }
219 isFound = true;
220 monitors_.erase(iter);
221 }
222
223 auto [sIter, isOk] = monitors_.insert(monitor);
224 if (!isOk) {
225 if (isFound) {
226 MMI_HILOGE("Internal error: monitor has been removed");
227 } else {
228 MMI_HILOGE("Failed to add monitor");
229 }
230 return RET_ERR;
231 }
232
233 if (isFound) {
234 MMI_HILOGD("Event type is updated:%{public}u", monitor.eventType_);
235 } else {
236 MMI_HILOGD("Service Add Monitor Success");
237 }
238 return RET_OK;
239 }
240
RemoveMonitor(const SessionHandler & monitor)241 void EventMonitorHandler::MonitorCollection::RemoveMonitor(const SessionHandler& monitor)
242 {
243 auto iter = monitors_.find(monitor);
244 if (iter == monitors_.cend()) {
245 MMI_HILOGE("Monitor does not exist");
246 return;
247 }
248
249 monitors_.erase(iter);
250 if (monitor.eventType_ == HANDLE_EVENT_TYPE_NONE) {
251 MMI_HILOGD("Unregister monitor successfully");
252 return;
253 }
254
255 auto [sIter, isOk] = monitors_.insert(monitor);
256 if (!isOk) {
257 MMI_HILOGE("Internal error, monitor has been removed");
258 return;
259 }
260 MMI_HILOGD("Event type is updated:%{public}u", monitor.eventType_);
261 }
262
MarkConsumed(int32_t eventId,SessionPtr session)263 void EventMonitorHandler::MonitorCollection::MarkConsumed(int32_t eventId, SessionPtr session)
264 {
265 if (!HasMonitor(session)) {
266 MMI_HILOGW("Specified monitor does not exist");
267 return;
268 }
269 auto tIter = states_.begin();
270 for (; tIter != states_.end(); ++tIter) {
271 const auto &eventIds = tIter->second.eventIds_;
272 if (eventIds.find(eventId) != eventIds.cend()) {
273 break;
274 }
275 }
276 if (tIter == states_.end()) {
277 MMI_HILOGE("No operation corresponding to this event");
278 return;
279 }
280 ConsumptionState &state = tIter->second;
281
282 if (state.isMonitorConsumed_) {
283 MMI_HILOGE("Corresponding operation has been marked as consumed");
284 return;
285 }
286 state.isMonitorConsumed_ = true;
287 if (state.lastPointerEvent_ == nullptr) {
288 MMI_HILOGE("No former touch event");
289 return;
290 }
291 #ifdef OHOS_BUILD_ENABLE_TOUCH
292 MMI_HILOGD("Cancel operation");
293 auto pointerEvent = std::make_shared<PointerEvent>(*state.lastPointerEvent_);
294 pointerEvent->SetPointerAction(PointerEvent::POINTER_ACTION_CANCEL);
295 pointerEvent->SetActionTime(GetSysClockTime());
296 pointerEvent->UpdateId();
297 pointerEvent->AddFlag(InputEvent::EVENT_FLAG_NO_INTERCEPT | InputEvent::EVENT_FLAG_NO_MONITOR);
298 auto inputEventNormalizeHandler = InputHandler->GetEventNormalizeHandler();
299 CHKPV(inputEventNormalizeHandler);
300 inputEventNormalizeHandler->HandleTouchEvent(pointerEvent);
301 #endif // OHOS_BUILD_ENABLE_TOUCH
302 }
303
304 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
HandleEvent(std::shared_ptr<KeyEvent> keyEvent)305 bool EventMonitorHandler::MonitorCollection::HandleEvent(std::shared_ptr<KeyEvent> keyEvent)
306 {
307 CHKPF(keyEvent);
308 MMI_HILOGD("There are currently %{public}zu monitors", monitors_.size());
309 for (const auto &mon : monitors_) {
310 if ((mon.eventType_ & HANDLE_EVENT_TYPE_KEY) == HANDLE_EVENT_TYPE_KEY) {
311 mon.SendToClient(keyEvent);
312 }
313 }
314 return false;
315 }
316 #endif // OHOS_BUILD_ENABLE_KEYBOARD
317
318 #if defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH)
HandleEvent(std::shared_ptr<PointerEvent> pointerEvent)319 bool EventMonitorHandler::MonitorCollection::HandleEvent(std::shared_ptr<PointerEvent> pointerEvent)
320 {
321 CHKPF(pointerEvent);
322 #ifdef OHOS_BUILD_ENABLE_TOUCH
323 UpdateConsumptionState(pointerEvent);
324 #endif // OHOS_BUILD_ENABLE_TOUCH
325 Monitor(pointerEvent);
326 if (pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
327 auto iter = states_.find(pointerEvent->GetDeviceId());
328 return (iter != states_.end() ? iter->second.isMonitorConsumed_ : false);
329 }
330 MMI_HILOGI("This is not a touch-screen event");
331 return false;
332 }
333 #endif // OHOS_BUILD_ENABLE_POINTER || OHOS_BUILD_ENABLE_TOUCH
334
HasMonitor(SessionPtr session)335 bool EventMonitorHandler::MonitorCollection::HasMonitor(SessionPtr session)
336 {
337 SessionHandler monitor { InputHandlerType::MONITOR, HANDLE_EVENT_TYPE_ALL, session };
338 return (monitors_.find(monitor) != monitors_.end());
339 }
340
341 #ifdef OHOS_BUILD_ENABLE_TOUCH
UpdateConsumptionState(std::shared_ptr<PointerEvent> pointerEvent)342 void EventMonitorHandler::MonitorCollection::UpdateConsumptionState(std::shared_ptr<PointerEvent> pointerEvent)
343 {
344 CALL_DEBUG_ENTER;
345 CHKPV(pointerEvent);
346 if (pointerEvent->GetSourceType() != PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
347 return;
348 }
349 auto sIter = states_.find(pointerEvent->GetDeviceId());
350 if (sIter == states_.end()) {
351 auto [tIter, isOk] = states_.emplace(pointerEvent->GetDeviceId(), ConsumptionState());
352 if (!isOk) {
353 MMI_HILOGE("Failed to emplace consumption state");
354 return;
355 }
356 sIter = tIter;
357 }
358 ConsumptionState &state = sIter->second;
359 auto [tIter, isOk] = state.eventIds_.emplace(pointerEvent->GetId());
360 if (!isOk) {
361 MMI_HILOGW("Failed to stash event");
362 }
363 state.lastPointerEvent_ = pointerEvent;
364
365 if (pointerEvent->GetPointerIds().size() != 1) {
366 MMI_HILOGD("In intermediate process");
367 return;
368 }
369 if (pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_DOWN) {
370 MMI_HILOGD("First press down");
371 state.eventIds_.clear();
372 auto [tIter, isOk] = state.eventIds_.emplace(pointerEvent->GetId());
373 if (!isOk) {
374 MMI_HILOGW("Event number is duplicated");
375 }
376 state.isMonitorConsumed_ = false;
377 } else if (pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_UP) {
378 MMI_HILOGD("Last lift up");
379 state.eventIds_.clear();
380 }
381 }
382 #endif // OHOS_BUILD_ENABLE_TOUCH
383
384 #if defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH)
Monitor(std::shared_ptr<PointerEvent> pointerEvent)385 void EventMonitorHandler::MonitorCollection::Monitor(std::shared_ptr<PointerEvent> pointerEvent)
386 {
387 CHKPV(pointerEvent);
388 MMI_HILOGD("There are currently %{public}zu monitors", monitors_.size());
389 for (const auto &monitor : monitors_) {
390 if ((monitor.eventType_ & HANDLE_EVENT_TYPE_POINTER) == HANDLE_EVENT_TYPE_POINTER) {
391 monitor.SendToClient(pointerEvent);
392 }
393 }
394 }
395 #endif // OHOS_BUILD_ENABLE_POINTER || OHOS_BUILD_ENABLE_TOUCH
396
OnSessionLost(SessionPtr session)397 void EventMonitorHandler::MonitorCollection::OnSessionLost(SessionPtr session)
398 {
399 CALL_INFO_TRACE;
400 std::set<SessionHandler>::const_iterator cItr = monitors_.cbegin();
401 while (cItr != monitors_.cend()) {
402 if (cItr->session_ != session) {
403 ++cItr;
404 } else {
405 cItr = monitors_.erase(cItr);
406 }
407 }
408 }
409
Dump(int32_t fd,const std::vector<std::string> & args)410 void EventMonitorHandler::Dump(int32_t fd, const std::vector<std::string> &args)
411 {
412 return monitors_.Dump(fd, args);
413 }
414
Dump(int32_t fd,const std::vector<std::string> & args)415 void EventMonitorHandler::MonitorCollection::Dump(int32_t fd, const std::vector<std::string> &args)
416 {
417 CALL_DEBUG_ENTER;
418 mprintf(fd, "Monitor information:\t");
419 mprintf(fd, "monitors: count=%d", monitors_.size());
420 for (const auto &item : monitors_) {
421 SessionPtr session = item.session_;
422 CHKPV(session);
423 mprintf(fd,
424 "handlerType:%d | Pid:%d | Uid:%d | Fd:%d "
425 "| EarliestEventTime:%" PRId64 " | Descript:%s \t",
426 item.handlerType_, session->GetPid(),
427 session->GetUid(), session->GetFd(),
428 session->GetEarliestEventTime(), session->GetDescript().c_str());
429 }
430 }
431 } // namespace MMI
432 } // namespace OHOS
433