1 /*
2 * Copyright (c) 2022-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 "event_interceptor_handler.h"
17
18 #include "bytrace_adapter.h"
19 #include "define_multimodal.h"
20 #include "dfx_hisysevent.h"
21 #include "event_dispatch_handler.h"
22 #include "input_device_manager.h"
23 #include "input_event_data_transformation.h"
24 #include "input_event_handler.h"
25 #include "mmi_log.h"
26 #include "net_packet.h"
27 #include "proto.h"
28 #include "util_ex.h"
29 #include "init_param.h"
30
31 #undef MMI_LOG_DOMAIN
32 #define MMI_LOG_DOMAIN MMI_LOG_HANDLER
33 #undef MMI_LOG_TAG
34 #define MMI_LOG_TAG "EventInterceptorHandler"
35
36 namespace OHOS {
37 namespace MMI {
38 namespace {
39 constexpr int32_t ACCESSIBILITY_UID { 1103 };
40 const std::string DEFAULT_KEYEVENT_INTERCEPT_WHITELIST = "2722;41;40;0;22;17;16;23;2841;9;2089;2083;";
41 } // namespace
42
43 std::unique_ptr<std::string> EventInterceptorHandler::keyevent_intercept_whitelist = nullptr;
44
45 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
HandleKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)46 void EventInterceptorHandler::HandleKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)
47 {
48 CHKPV(keyEvent);
49 if (TouchPadKnuckleDoubleClickHandle(keyEvent)) {
50 return;
51 }
52
53 if (keyevent_intercept_whitelist == nullptr) {
54 uint32_t size = 0;
55 int ret = SystemReadParam("const.multimodalinput.keyevent_intercept_whitelist", NULL, &size);
56 std::string intercept_whitelist = "";
57 if (ret == 0) {
58 std::vector<char> value(size + 1);
59 ret = SystemReadParam("const.multimodalinput.keyevent_intercept_whitelist",
60 value.data(), &size);
61 if (ret == 0) {
62 intercept_whitelist = std::string(value.data());
63 } else {
64 intercept_whitelist = DEFAULT_KEYEVENT_INTERCEPT_WHITELIST;
65 }
66 }
67
68 keyevent_intercept_whitelist = std::make_unique<std::string>(intercept_whitelist);
69 MMI_HILOGD("Initialize interception white list is %{public}s",
70 keyevent_intercept_whitelist->c_str());
71 }
72 std::string keyString = std::to_string(keyEvent->GetKeyCode());
73 keyString += ";";
74 bool isIntercept = keyevent_intercept_whitelist->find(keyString) == std::string::npos;
75 MMI_HILOGD("Received key event is %{public}s isIntercept is %{public}d",
76 keyString.c_str(), isIntercept);
77
78 if (isIntercept && OnHandleEvent(keyEvent)) {
79 MMI_HILOGD("KeyEvent filter find a keyEvent from Original event keyCode:%{private}d",
80 keyEvent->GetKeyCode());
81 BytraceAdapter::StartBytrace(keyEvent, BytraceAdapter::KEY_INTERCEPT_EVENT);
82 DfxHisysevent::ReportKeyEvent("intercept");
83 return;
84 }
85 CHKPV(nextHandler_);
86 nextHandler_->HandleKeyEvent(keyEvent);
87 }
88 #endif // OHOS_BUILD_ENABLE_KEYBOARD
89
90 #ifdef OHOS_BUILD_ENABLE_POINTER
HandlePointerEvent(const std::shared_ptr<PointerEvent> pointerEvent)91 void EventInterceptorHandler::HandlePointerEvent(const std::shared_ptr<PointerEvent> pointerEvent)
92 {
93 CHKPV(pointerEvent);
94 if (OnHandleEvent(pointerEvent)) {
95 BytraceAdapter::StartBytrace(pointerEvent, BytraceAdapter::TRACE_STOP);
96 MMI_HILOGD("Interception is succeeded");
97 return;
98 }
99 CHKPV(nextHandler_);
100 nextHandler_->HandlePointerEvent(pointerEvent);
101 }
102 #endif // OHOS_BUILD_ENABLE_POINTER
103
104 #ifdef OHOS_BUILD_ENABLE_TOUCH
HandleTouchEvent(const std::shared_ptr<PointerEvent> pointerEvent)105 void EventInterceptorHandler::HandleTouchEvent(const std::shared_ptr<PointerEvent> pointerEvent)
106 {
107 CHKPV(pointerEvent);
108 if (OnHandleEvent(pointerEvent)) {
109 BytraceAdapter::StartBytrace(pointerEvent, BytraceAdapter::TRACE_STOP);
110 MMI_HILOGD("Interception is succeeded");
111 return;
112 }
113 CHKPV(nextHandler_);
114 nextHandler_->HandleTouchEvent(pointerEvent);
115 }
116 #endif // OHOS_BUILD_ENABLE_TOUCH
117
AddInputHandler(InputHandlerType handlerType,HandleEventType eventType,int32_t priority,uint32_t deviceTags,SessionPtr session)118 int32_t EventInterceptorHandler::AddInputHandler(InputHandlerType handlerType,
119 HandleEventType eventType, int32_t priority, uint32_t deviceTags, SessionPtr session)
120 {
121 CALL_INFO_TRACE;
122 CHKPR(session, RET_ERR);
123 if ((eventType & HANDLE_EVENT_TYPE_ALL) == HANDLE_EVENT_TYPE_NONE) {
124 MMI_HILOGE("Invalid event type");
125 return RET_ERR;
126 }
127 InitSessionLostCallback();
128 SessionHandler interceptor { handlerType, eventType, priority, deviceTags, session };
129 MMI_HILOGD("The handlerType:%{public}d, eventType:%{public}d, deviceTags:%{public}d, priority:%{public}d",
130 handlerType, eventType, deviceTags, priority);
131 return interceptors_.AddInterceptor(interceptor);
132 }
133
RemoveInputHandler(InputHandlerType handlerType,HandleEventType eventType,int32_t priority,uint32_t deviceTags,SessionPtr session)134 void EventInterceptorHandler::RemoveInputHandler(InputHandlerType handlerType,
135 HandleEventType eventType, int32_t priority, uint32_t deviceTags, SessionPtr session)
136 {
137 CALL_INFO_TRACE;
138 CHKPV(session);
139 if (handlerType == InputHandlerType::INTERCEPTOR) {
140 SessionHandler interceptor { handlerType, eventType, priority, deviceTags, session };
141 MMI_HILOGD("The handlerType:%{public}d, eventType:%{public}d, deviceTags:%{public}d, priority:%{public}d",
142 handlerType, eventType, deviceTags, priority);
143 interceptors_.RemoveInterceptor(interceptor);
144 }
145 }
146 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
OnHandleEvent(std::shared_ptr<KeyEvent> keyEvent)147 bool EventInterceptorHandler::OnHandleEvent(std::shared_ptr<KeyEvent> keyEvent)
148 {
149 MMI_HILOGD("Handle KeyEvent");
150 CHKPF(keyEvent);
151 if (keyEvent->HasFlag(InputEvent::EVENT_FLAG_NO_INTERCEPT)) {
152 MMI_HILOGW("This event has been tagged as not to be intercepted");
153 return false;
154 }
155 return interceptors_.HandleEvent(keyEvent);
156 }
157 #endif // OHOS_BUILD_ENABLE_KEYBOARD
158
159 #if defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH)
OnHandleEvent(std::shared_ptr<PointerEvent> pointerEvent)160 bool EventInterceptorHandler::OnHandleEvent(std::shared_ptr<PointerEvent> pointerEvent)
161 {
162 CHKPF(pointerEvent);
163 if (pointerEvent->HasFlag(InputEvent::EVENT_FLAG_NO_INTERCEPT)) {
164 MMI_HILOGW("This event has been tagged as not to be intercepted");
165 return false;
166 }
167 return interceptors_.HandleEvent(pointerEvent);
168 }
169 #endif // OHOS_BUILD_ENABLE_POINTER || OHOS_BUILD_ENABLE_TOUCH
170
InitSessionLostCallback()171 void EventInterceptorHandler::InitSessionLostCallback()
172 {
173 if (sessionLostCallbackInitialized_) {
174 MMI_HILOGE("Init session is failed");
175 return;
176 }
177 auto udsServerPtr = InputHandler->GetUDSServer();
178 CHKPV(udsServerPtr);
179 udsServerPtr->AddSessionDeletedCallback([this] (SessionPtr session) { this->OnSessionLost(session); });
180 sessionLostCallbackInitialized_ = true;
181 MMI_HILOGD("The callback on session deleted is registered successfully");
182 }
183
OnSessionLost(SessionPtr session)184 void EventInterceptorHandler::OnSessionLost(SessionPtr session)
185 {
186 interceptors_.OnSessionLost(session);
187 }
188
CheckInputDeviceSource(const std::shared_ptr<PointerEvent> pointerEvent,uint32_t deviceTags)189 bool EventInterceptorHandler::CheckInputDeviceSource(
190 const std::shared_ptr<PointerEvent> pointerEvent, uint32_t deviceTags)
191 {
192 if ((pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_TOUCHSCREEN) &&
193 ((deviceTags & CapabilityToTags(InputDeviceCapability::INPUT_DEV_CAP_TOUCH)) ||
194 (deviceTags & CapabilityToTags(InputDeviceCapability::INPUT_DEV_CAP_TABLET_TOOL)))) {
195 return true;
196 } else if ((pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_MOUSE) &&
197 (deviceTags & CapabilityToTags(InputDeviceCapability::INPUT_DEV_CAP_POINTER))) {
198 return true;
199 } else if ((pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_TOUCHPAD) &&
200 (deviceTags & CapabilityToTags(InputDeviceCapability::INPUT_DEV_CAP_POINTER))) {
201 return true;
202 }
203 return false;
204 }
205
SendToClient(std::shared_ptr<KeyEvent> keyEvent) const206 void EventInterceptorHandler::SessionHandler::SendToClient(std::shared_ptr<KeyEvent> keyEvent) const
207 {
208 CHKPV(keyEvent);
209 NetPacket pkt(MmiMessageId::REPORT_KEY_EVENT);
210 pkt << handlerType_ << deviceTags_;
211 if (pkt.ChkRWError()) {
212 MMI_HILOGE("Packet write key event failed");
213 return;
214 }
215 if (InputEventDataTransformation::KeyEventToNetPacket(keyEvent, pkt) != RET_OK) {
216 MMI_HILOGE("Packet key event failed, errCode:%{public}d", STREAM_BUF_WRITE_FAIL);
217 return;
218 }
219 if (!session_->SendMsg(pkt)) {
220 MMI_HILOGE("Send message failed, errCode:%{public}d", MSG_SEND_FAIL);
221 return;
222 }
223 }
224
SendToClient(std::shared_ptr<PointerEvent> pointerEvent) const225 void EventInterceptorHandler::SessionHandler::SendToClient(std::shared_ptr<PointerEvent> pointerEvent) const
226 {
227 CHKPV(pointerEvent);
228 CHKPV(session_);
229 if (session_->GetUid() == ACCESSIBILITY_UID) {
230 pointerEvent->AddFlag(InputEvent::EVENT_FLAG_ACCESSIBILITY);
231 }
232 NetPacket pkt(MmiMessageId::REPORT_POINTER_EVENT);
233 MMI_HILOGD("Service send to client InputHandlerType:%{public}d", handlerType_);
234 pkt << handlerType_ << deviceTags_;
235 if (pkt.ChkRWError()) {
236 MMI_HILOGE("Packet write pointer event failed");
237 return;
238 }
239 if (InputEventDataTransformation::Marshalling(pointerEvent, pkt) != RET_OK) {
240 MMI_HILOGE("Marshalling pointer event failed, errCode:%{public}d", STREAM_BUF_WRITE_FAIL);
241 return;
242 }
243 if (!session_->SendMsg(pkt)) {
244 MMI_HILOGE("Send message failed, errCode:%{public}d", MSG_SEND_FAIL);
245 return;
246 }
247 }
248
249 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
HandleEvent(std::shared_ptr<KeyEvent> keyEvent)250 bool EventInterceptorHandler::InterceptorCollection::HandleEvent(std::shared_ptr<KeyEvent> keyEvent)
251 {
252 CHKPF(keyEvent);
253 if (interceptors_.empty()) {
254 MMI_HILOGD("Key interceptors is empty");
255 return false;
256 }
257 MMI_HILOGD("There are currently:%{public}zu interceptors", interceptors_.size());
258 bool isInterceptor = false;
259 std::vector<KeyEvent::KeyItem> keyItems = keyEvent->GetKeyItems();
260 if (keyItems.empty()) {
261 MMI_HILOGE("keyItems is empty");
262 DfxHisysevent::ReportFailHandleKey("InterceptorCollection::HandleEvent", keyEvent->GetKeyCode(),
263 DfxHisysevent::KEY_ERROR_CODE::INVALID_PARAMETER);
264 return false;
265 }
266 std::shared_ptr<InputDevice> inputDevice = INPUT_DEV_MGR->GetInputDevice(keyItems.front().GetDeviceId());
267 CHKPF(inputDevice);
268 uint32_t capKeyboard = CapabilityToTags(InputDeviceCapability::INPUT_DEV_CAP_KEYBOARD);
269 for (const auto &interceptor : interceptors_) {
270 MMI_HILOGD("The eventType:%{public}d, deviceTags:%{public}d",
271 interceptor.eventType_, interceptor.deviceTags_);
272 if ((capKeyboard & interceptor.deviceTags_) == 0) {
273 MMI_HILOGD("Interceptor cap does not have keyboard");
274 continue;
275 }
276 if (!inputDevice->HasCapability(interceptor.deviceTags_)) {
277 continue;
278 }
279 auto session = interceptor.session_;
280 if (session != nullptr) {
281 int32_t tokenType = session->GetTokenType();
282 int32_t pid = session->GetPid();
283 if (tokenType == TokenType::TOKEN_HAP && !IInputWindowsManager::GetInstance()->CheckAppFocused(pid)) {
284 MMI_HILOGD("Token hap is not focus, no need interceptor key");
285 continue;
286 }
287 }
288 if ((interceptor.eventType_ & HANDLE_EVENT_TYPE_KEY) == HANDLE_EVENT_TYPE_KEY) {
289 interceptor.SendToClient(keyEvent);
290 MMI_HILOGD("Key event was intercepted");
291 isInterceptor = true;
292 break;
293 }
294 }
295 return isInterceptor;
296 }
297 #endif // OHOS_BUILD_ENABLE_KEYBOARD
298
299 #if defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH)
HandleEvent(std::shared_ptr<PointerEvent> pointerEvent)300 bool EventInterceptorHandler::InterceptorCollection::HandleEvent(std::shared_ptr<PointerEvent> pointerEvent)
301 {
302 CHKPF(pointerEvent);
303 if (interceptors_.empty()) {
304 MMI_HILOGD("Interceptors are empty");
305 return false;
306 }
307 MMI_HILOGD("There are currently:%{public}zu interceptors", interceptors_.size());
308 bool isInterceptor = false;
309 PointerEvent::PointerItem pointerItem;
310 int32_t pointerId = pointerEvent->GetPointerId();
311 if (!pointerEvent->GetPointerItem(pointerId, pointerItem)) {
312 MMI_HILOGE("GetPointerItem:%{public}d fail", pointerId);
313 return false;
314 }
315 std::shared_ptr<InputDevice> inputDevice = INPUT_DEV_MGR->GetInputDevice(pointerItem.GetDeviceId(), false);
316 CHKPF(inputDevice);
317 uint32_t capPointer = CapabilityToTags(InputDeviceCapability::INPUT_DEV_CAP_POINTER);
318 uint32_t capTouch = CapabilityToTags(InputDeviceCapability::INPUT_DEV_CAP_TOUCH);
319 for (const auto &interceptor : interceptors_) {
320 MMI_HILOGD("The eventType:%{public}d, deviceTags:%{public}d",
321 interceptor.eventType_, interceptor.deviceTags_);
322 if (((capPointer | capTouch) & interceptor.deviceTags_) == 0) {
323 MMI_HILOGD("Interceptor cap does not have pointer or touch");
324 continue;
325 }
326 if (!EventInterceptorHandler::CheckInputDeviceSource(pointerEvent, interceptor.deviceTags_)) {
327 continue;
328 }
329 #ifndef OHOS_BUILD_EMULATOR
330 if (!inputDevice->HasCapability(interceptor.deviceTags_)) {
331 continue;
332 }
333 #endif // OHOS_BUILD_EMULATOR
334 auto session = interceptor.session_;
335 if (session != nullptr) {
336 int32_t tokenType = session->GetTokenType();
337 if ((tokenType == TokenType::TOKEN_HAP) &&
338 (IInputWindowsManager::GetInstance()->GetWindowPid(pointerEvent->GetTargetWindowId()) !=
339 session->GetPid())) {
340 MMI_HILOGD("Token hap is not hit, no need interceptor pointer");
341 continue;
342 }
343 }
344 if ((interceptor.eventType_ & HANDLE_EVENT_TYPE_POINTER) == HANDLE_EVENT_TYPE_POINTER) {
345 interceptor.SendToClient(pointerEvent);
346 if (pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_PULL_UP ||
347 pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_BUTTON_UP) {
348 MMI_HILOGI("Action:%{public}d event was intercepted", pointerEvent->GetPointerAction());
349 }
350 MMI_HILOGD("Pointer event was intercepted");
351 isInterceptor = true;
352 break;
353 }
354 }
355 return isInterceptor;
356 }
357 #endif // OHOS_BUILD_ENABLE_POINTER || OHOS_BUILD_ENABLE_TOUCH
358
AddInterceptor(const SessionHandler & interceptor)359 int32_t EventInterceptorHandler::InterceptorCollection::AddInterceptor(const SessionHandler& interceptor)
360 {
361 for (auto iter = interceptors_.begin(); iter != interceptors_.end(); ++iter) {
362 if (iter->session_ == interceptor.session_) {
363 interceptors_.erase(iter);
364 break;
365 }
366 }
367
368 if (interceptors_.size() >= MAX_N_INPUT_INTERCEPTORS) {
369 MMI_HILOGE("The number of interceptors exceeds limit");
370 return RET_ERR;
371 }
372
373 auto iterIndex = interceptors_.cbegin();
374 for (; iterIndex != interceptors_.cend(); ++iterIndex) {
375 if (interceptor.priority_ < iterIndex->priority_) {
376 break;
377 }
378 }
379 auto sIter = interceptors_.emplace(iterIndex, interceptor);
380 if (sIter == interceptors_.end()) {
381 MMI_HILOGE("Failed to add interceptor");
382 return RET_ERR;
383 }
384 return RET_OK;
385 }
386
RemoveInterceptor(const SessionHandler & interceptor)387 void EventInterceptorHandler::InterceptorCollection::RemoveInterceptor(const SessionHandler& interceptor)
388 {
389 for (auto iter = interceptors_.begin(); iter != interceptors_.end(); ++iter) {
390 if (iter->session_ == interceptor.session_) {
391 interceptors_.erase(iter);
392 break;
393 }
394 }
395 if (interceptor.eventType_ == HANDLE_EVENT_TYPE_NONE) {
396 MMI_HILOGD("Unregister interceptor successfully");
397 return;
398 }
399
400 auto iterIndex = interceptors_.cbegin();
401 for (; iterIndex != interceptors_.cend(); ++iterIndex) {
402 if (interceptor.priority_ < iterIndex->priority_) {
403 break;
404 }
405 }
406 auto sIter = interceptors_.emplace(iterIndex, interceptor);
407 if (sIter == interceptors_.end()) {
408 MMI_HILOGE("Internal error, interceptor has been removed");
409 return;
410 }
411 MMI_HILOGD("Event type is updated:%{public}u", interceptor.eventType_);
412 }
413
OnSessionLost(SessionPtr session)414 void EventInterceptorHandler::InterceptorCollection::OnSessionLost(SessionPtr session)
415 {
416 CALL_INFO_TRACE;
417 auto iter = interceptors_.cbegin();
418 while (iter != interceptors_.cend()) {
419 if (iter->session_ != session) {
420 ++iter;
421 } else {
422 iter = interceptors_.erase(iter);
423 }
424 }
425 }
426
Dump(int32_t fd,const std::vector<std::string> & args)427 void EventInterceptorHandler::Dump(int32_t fd, const std::vector<std::string> &args)
428 {
429 return interceptors_.Dump(fd, args);
430 }
431
Dump(int32_t fd,const std::vector<std::string> & args)432 void EventInterceptorHandler::InterceptorCollection::Dump(int32_t fd, const std::vector<std::string> &args)
433 {
434 CALL_DEBUG_ENTER;
435 mprintf(fd, "Interceptor information:\t");
436 mprintf(fd, "interceptors: count=%zu", interceptors_.size());
437 for (const auto &item : interceptors_) {
438 SessionPtr session = item.session_;
439 CHKPV(session);
440 mprintf(fd,
441 "handlerType:%d | eventType:%u | Pid:%d | Uid:%d | Fd:%d "
442 "| EarliestEventTime:%" PRId64 " | Descript:%s | ProgramName:%s \t",
443 item.handlerType_, item.eventType_,
444 session->GetPid(), session->GetUid(),
445 session->GetFd(),
446 session->GetEarliestEventTime(), session->GetDescript().c_str(),
447 session->GetProgramName().c_str());
448 }
449 }
450
451 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
TouchPadKnuckleDoubleClickHandle(std::shared_ptr<KeyEvent> event)452 bool EventInterceptorHandler::TouchPadKnuckleDoubleClickHandle(std::shared_ptr<KeyEvent> event)
453 {
454 CHKPF(event);
455 CHKPF(nextHandler_);
456 if (event->GetKeyAction() != KNUCKLE_1F_DOUBLE_CLICK &&
457 event->GetKeyAction() != KNUCKLE_2F_DOUBLE_CLICK) {
458 return false;
459 }
460 MMI_HILOGI("Current is touchPad knuckle double click action");
461 nextHandler_->HandleKeyEvent(event);
462 return true;
463 }
464 #endif // OHOS_BUILD_ENABLE_KEYBOARD
465 } // namespace MMI
466 } // namespace OHOS
467