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