• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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_active_subscriber_handler.h"
17 #include <chrono>
18 #include <future>
19 #include <parameters.h>
20 #include "dfx_hisysevent.h"
21 #include "input_event_data_transformation.h"
22 #include "input_event_handler.h"
23 #include "util_ex.h"
24 
25 #undef MMI_LOG_DOMAIN
26 #define MMI_LOG_DOMAIN MMI_LOG_HANDLER
27 #undef MMI_LOG_TAG
28 #define MMI_LOG_TAG "InputActiveSubscriberHandler"
29 
30 namespace OHOS {
31 namespace MMI {
32 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
HandleKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)33 void InputActiveSubscriberHandler::HandleKeyEvent(const std::shared_ptr<KeyEvent> keyEvent)
34 {
35     CHKPV(keyEvent);
36     CHKPV(nextHandler_);
37     OnSubscribeInputActive(keyEvent);
38     nextHandler_->HandleKeyEvent(keyEvent);
39 }
40 #endif // OHOS_BUILD_ENABLE_KEYBOARD
41 
42 #ifdef OHOS_BUILD_ENABLE_POINTER
HandlePointerEvent(const std::shared_ptr<PointerEvent> pointerEvent)43 void InputActiveSubscriberHandler::HandlePointerEvent(const std::shared_ptr<PointerEvent> pointerEvent)
44 {
45     CHKPV(pointerEvent);
46     CHKPV(nextHandler_);
47     OnSubscribeInputActive(pointerEvent);
48     nextHandler_->HandlePointerEvent(pointerEvent);
49 }
50 #endif // OHOS_BUILD_ENABLE_POINTER
51 
52 #ifdef OHOS_BUILD_ENABLE_TOUCH
HandleTouchEvent(const std::shared_ptr<PointerEvent> pointerEvent)53 void InputActiveSubscriberHandler::HandleTouchEvent(const std::shared_ptr<PointerEvent> pointerEvent)
54 {
55     CHKPV(pointerEvent);
56     CHKPV(nextHandler_);
57     OnSubscribeInputActive(pointerEvent);
58     nextHandler_->HandleTouchEvent(pointerEvent);
59 }
60 #endif // OHOS_BUILD_ENABLE_TOUCH
61 
62 #ifdef OHOS_BUILD_ENABLE_SWITCH
HandleSwitchEvent(const std::shared_ptr<SwitchEvent> switchEvent)63 void InputActiveSubscriberHandler::HandleSwitchEvent(const std::shared_ptr<SwitchEvent> switchEvent)
64 {
65     CHKPV(switchEvent);
66     CHKPV(nextHandler_);
67     nextHandler_->HandleSwitchEvent(switchEvent);
68 }
69 #endif // OHOS_BUILD_ENABLE_SWITCH
70 
SubscribeInputActive(SessionPtr sess,int32_t subscribeId,int64_t interval)71 int32_t InputActiveSubscriberHandler::SubscribeInputActive(SessionPtr sess, int32_t subscribeId, int64_t interval)
72 {
73     CALL_INFO_TRACE;
74     if (subscribeId < 0) {
75         MMI_HILOGE("Invalid subscribeId");
76         return ERROR_INVALID_SUBSCRIBE_ID;
77     }
78     CHKPR(sess, ERROR_NULL_POINTER);
79     MMI_HILOGD("subscribeId: %{public}d interval: %{public}" PRId64, subscribeId, interval);
80     auto subscriber = std::make_shared<Subscriber>(subscribeId, sess, interval);
81     InsertSubscriber(subscriber);
82     InitSessionDeleteCallback();
83     return RET_OK;
84 }
85 
UnsubscribeInputActive(SessionPtr sess,int32_t subscribeId)86 int32_t InputActiveSubscriberHandler::UnsubscribeInputActive(SessionPtr sess, int32_t subscribeId)
87 {
88     CALL_INFO_TRACE;
89     MMI_HILOGD("subscribeId: %{public}d", subscribeId);
90     auto findResult = std::find_if(
91         subscribers_.begin(), subscribers_.end(), [subscribeId, sess](std::shared_ptr<Subscriber> subscribe) {
92             if (subscribe && subscribe->id_ == subscribeId && subscribe->sess_ == sess) {
93                 return true;
94             }
95             return false;
96         });
97     if (findResult != subscribers_.end()) {
98         subscribers_.erase(findResult);
99     } else {
100         MMI_HILOGE("UnsubscribeInputActive failed with subscribeId(%{public}d)", subscribeId);
101         return ERROR_FIND_SUBSCRIBEID_FAILED;
102     }
103     return RET_OK;
104 }
105 
IsImmediateNotifySubscriber(std::shared_ptr<Subscriber> subscriber,int64_t eventTime)106 bool InputActiveSubscriberHandler::IsImmediateNotifySubscriber(
107     std::shared_ptr<Subscriber> subscriber, int64_t eventTime)
108 {
109     if (subscriber->interval_ <= 0) {
110         return true;
111     }
112     if (subscriber->sendEventLastTime_ <= 0) {
113         return true;
114     }
115     if (subscriber->sendEventLastTime_ > eventTime) {
116         subscriber->sendEventLastTime_ = 0;
117         return true;
118     }
119     if (eventTime - subscriber->sendEventLastTime_ >= subscriber->interval_) {
120         return true;
121     }
122     return false;
123 }
124 
StartIntervalTimer(std::shared_ptr<Subscriber> subscriber,int64_t eventTime)125 void InputActiveSubscriberHandler::StartIntervalTimer(std::shared_ptr<Subscriber> subscriber, int64_t eventTime)
126 {
127     if (subscriber->timerId_ >= 0) {
128         return;
129     }
130     auto timerIntervalMs = subscriber->interval_ - (eventTime - subscriber->sendEventLastTime_);
131     auto timerId = TimerMgr->AddTimer(timerIntervalMs, 1, [this, subscriber] {
132         auto currentTime = GetMillisTime();
133         if (subscriber->lastEventType_ == EVENTTYPE_KEY) {
134             if (subscriber->keyEvent_) {
135                 NotifySubscriber(subscriber->keyEvent_, subscriber);
136             } else {
137                 currentTime = 0;
138                 MMI_HILOGE("lastKeyEvent is null");
139             }
140         } else if (subscriber->lastEventType_ == EVENTTYPE_POINTER) {
141             if (subscriber->pointerEvent_) {
142                 NotifySubscriber(subscriber->pointerEvent_, subscriber);
143             } else {
144                 currentTime = 0;
145                 MMI_HILOGE("lastPointerEvent is null");
146             }
147         } else {
148             currentTime = 0;
149             MMI_HILOGE("lastEventType_ is invalid");
150         }
151         subscriber->timerId_ = INVALID_TIMERID;
152         CleanSubscribeInfo(subscriber, currentTime);
153     }, "InputActiveSubscriberHandler");
154     if (timerId < 0) {
155         MMI_HILOGE("AddTimer fail, setting will not work");
156     } else {
157         subscriber->timerId_ = timerId;
158     }
159 }
160 
CleanSubscribeInfo(std::shared_ptr<Subscriber> subscriber,int64_t eventTime)161 void InputActiveSubscriberHandler::CleanSubscribeInfo(std::shared_ptr<Subscriber> subscriber, int64_t eventTime)
162 {
163     if (subscriber->timerId_ >= 0) {
164         TimerMgr->RemoveTimer(subscriber->timerId_);
165         subscriber->timerId_ = INVALID_TIMERID;
166     }
167     subscriber->lastEventType_ = EVENTTYPE_INVALID;
168     subscriber->keyEvent_ = nullptr;
169     subscriber->pointerEvent_ = nullptr;
170     subscriber->sendEventLastTime_ = eventTime;
171 }
172 
OnSubscribeInputActive(const std::shared_ptr<KeyEvent> keyEvent)173 void InputActiveSubscriberHandler::OnSubscribeInputActive(const std::shared_ptr<KeyEvent> keyEvent)
174 {
175     CHKPV(keyEvent);
176     MMI_HILOGD("The Subscribe InputActive keycode: %{private}d", keyEvent->GetKeyCode());
177     for (const auto &subscriber : subscribers_) {
178         if (!subscriber) {
179             MMI_HILOGE("subscriber is null");
180             continue;
181         }
182         MMI_HILOGD("subscriber interval = %{public}" PRId64 ", id = %{public}d, pid = %{public}d",
183             subscriber->interval_, subscriber->id_, subscriber->sess_ ? subscriber->sess_->GetPid() : -1);
184         auto currentTime = GetMillisTime();
185         if (IsImmediateNotifySubscriber(subscriber, currentTime)) {
186             CleanSubscribeInfo(subscriber, currentTime);
187             NotifySubscriber(keyEvent, subscriber);
188         } else {
189             subscriber->keyEvent_ = keyEvent;
190             subscriber->lastEventType_ = EVENTTYPE_KEY;
191             StartIntervalTimer(subscriber, currentTime);
192         }
193     }
194 }
195 
OnSubscribeInputActive(const std::shared_ptr<PointerEvent> pointerEvent)196 void InputActiveSubscriberHandler::OnSubscribeInputActive(const std::shared_ptr<PointerEvent> pointerEvent)
197 {
198     CHKPV(pointerEvent);
199     MMI_HILOGD("The Subscribe InputActive pointerId: %{private}d", pointerEvent->GetPointerId());
200     for (const auto &subscriber : subscribers_) {
201         if (!subscriber) {
202             MMI_HILOGE("subscriber is null");
203             continue;
204         }
205         MMI_HILOGD("subscriber interval = %{public}" PRId64 ", id = %{public}d, pid = %{public}d",
206             subscriber->interval_, subscriber->id_, subscriber->sess_ ? subscriber->sess_->GetPid() : -1);
207         auto currentTime = GetMillisTime();
208         if (IsImmediateNotifySubscriber(subscriber, currentTime)) {
209             CleanSubscribeInfo(subscriber, currentTime);
210             NotifySubscriber(pointerEvent, subscriber);
211         } else {
212             subscriber->pointerEvent_ = pointerEvent;
213             subscriber->lastEventType_ = EVENTTYPE_POINTER;
214             StartIntervalTimer(subscriber, currentTime);
215         }
216     }
217 }
218 
InsertSubscriber(std::shared_ptr<Subscriber> subscriber)219 void InputActiveSubscriberHandler::InsertSubscriber(std::shared_ptr<Subscriber> subscriber)
220 {
221     CALL_DEBUG_ENTER;
222     CHKPV(subscriber);
223     MMI_HILOGI("InsertSubscriber id = %{public}d", subscriber->id_);
224     auto findResult = std::find_if(
225         subscribers_.begin(), subscribers_.end(), [subscriber](std::shared_ptr<Subscriber> tmpSubscriber) {
226             if (tmpSubscriber && tmpSubscriber->id_ == subscriber->id_ && tmpSubscriber->sess_ == subscriber->sess_) {
227                 return true;
228             }
229             return false;
230         });
231     if (findResult != subscribers_.end()) {
232         MMI_HILOGW("Repeat registration id: %{public}d, desc:%{public}s", subscriber->id_,
233             subscriber->sess_ ? subscriber->sess_->GetDescript().c_str() : "invalid session");
234     } else {
235         subscribers_.push_back(subscriber);
236     }
237 }
238 
OnSessionDelete(SessionPtr sess)239 void InputActiveSubscriberHandler::OnSessionDelete(SessionPtr sess)
240 {
241     CALL_DEBUG_ENTER;
242     CHKPV(sess);
243     auto newEnd = std::remove_if(
244         subscribers_.begin(), subscribers_.end(), [sess](std::shared_ptr<Subscriber> subscribe) {
245             if (subscribe && subscribe->sess_ == sess) {
246                 return true;
247             }
248             return false;
249         });
250     subscribers_.erase(newEnd, subscribers_.end());
251 }
252 
NotifySubscriber(const std::shared_ptr<KeyEvent> keyEvent,const std::shared_ptr<Subscriber> subscriber)253 void InputActiveSubscriberHandler::NotifySubscriber(
254     const std::shared_ptr<KeyEvent> keyEvent, const std::shared_ptr<Subscriber> subscriber)
255 {
256     CALL_DEBUG_ENTER;
257     CHKPV(keyEvent);
258     CHKPV(subscriber);
259     CHKPV(InputHandler);
260     auto udsServerPtr = InputHandler->GetUDSServer();
261     CHKPV(udsServerPtr);
262     NetPacket pkt(MmiMessageId::ON_SUBSCRIBE_INPUT_ACTIVE);
263     pkt << HANDLE_EVENT_TYPE_KEY;
264     InputEventDataTransformation::KeyEventToNetPacket(keyEvent, pkt);
265     if (subscriber->sess_ == nullptr) {
266         MMI_HILOGE("Subscriber's sess is null");
267         return;
268     }
269     int32_t fd = subscriber->sess_->GetFd();
270     pkt << subscriber->id_;
271     MMI_HILOGI("Notify subscriber id: %{public}d, keycode:%{private}d, pid: %{public}d",
272         subscriber->id_, keyEvent->GetKeyCode(), subscriber->sess_->GetPid());
273     if (pkt.ChkRWError()) {
274         MMI_HILOGE("Packet write dispatch subscriber failed");
275         return;
276     }
277     if (!udsServerPtr->SendMsg(fd, pkt)) {
278         MMI_HILOGE("Leave, server dispatch subscriber failed");
279     }
280 }
281 
NotifySubscriber(const std::shared_ptr<PointerEvent> pointerEvent,const std::shared_ptr<Subscriber> subscriber)282 void InputActiveSubscriberHandler::NotifySubscriber(
283     const std::shared_ptr<PointerEvent> pointerEvent, const std::shared_ptr<Subscriber> subscriber)
284 {
285     CALL_DEBUG_ENTER;
286     CHKPV(pointerEvent);
287     CHKPV(subscriber);
288     CHKPV(InputHandler);
289     auto udsServerPtr = InputHandler->GetUDSServer();
290     CHKPV(udsServerPtr);
291     NetPacket pkt(MmiMessageId::ON_SUBSCRIBE_INPUT_ACTIVE);
292     pkt << HANDLE_EVENT_TYPE_POINTER;
293     InputEventDataTransformation::Marshalling(pointerEvent, pkt);
294     if (subscriber->sess_ == nullptr) {
295         MMI_HILOGE("Subscriber's sess is null");
296         return;
297     }
298     int32_t fd = subscriber->sess_->GetFd();
299     pkt << subscriber->id_;
300     MMI_HILOGI("%{public}d|%{public}d|%{public}d",
301         subscriber->id_, pointerEvent->GetPointerId(), subscriber->sess_->GetPid());
302     if (pkt.ChkRWError()) {
303         MMI_HILOGE("Packet write dispatch subscriber failed");
304         return;
305     }
306     if (!udsServerPtr->SendMsg(fd, pkt)) {
307         MMI_HILOGE("Leave, server dispatch subscriber failed");
308     }
309 }
310 
InitSessionDeleteCallback()311 bool InputActiveSubscriberHandler::InitSessionDeleteCallback()
312 {
313     CALL_DEBUG_ENTER;
314     if (callbackInitialized_) {
315         MMI_HILOGD("Session delete callback has already been initialized");
316         return true;
317     }
318     CHKPF(InputHandler);
319     auto udsServerPtr = InputHandler->GetUDSServer();
320     CHKPF(udsServerPtr);
321     std::function<void(SessionPtr)> callback =
322         [this] (SessionPtr sess) { return this->OnSessionDelete(sess); };
323     udsServerPtr->AddSessionDeletedCallback(callback);
324     callbackInitialized_ = true;
325     return true;
326 }
327 
Dump(int32_t fd,const std::vector<std::string> & args)328 void InputActiveSubscriberHandler::Dump(int32_t fd, const std::vector<std::string> &args)
329 {
330     CALL_DEBUG_ENTER;
331     mprintf(fd, "Subscriber information:\t");
332     mprintf(fd, "subscribers: count = %zu", subscribers_.size());
333     for (const auto& subscriber : subscribers_) {
334         if (subscriber == nullptr) {
335             continue;
336         }
337         SessionPtr session = subscriber->sess_;
338         if (session == nullptr) {
339             continue;
340         }
341         mprintf(fd, "subscriber id:%d | Pid:%d | Uid:%d | Fd:%d\t", subscriber->id_,
342             session->GetPid(), session->GetUid(), session->GetFd());
343     }
344 }
345 } // namespace MMI
346 } // namespace OHOS