• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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