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_handler.h"
17
18 #include <unistd.h>
19 #include "event_handler_utils.h"
20 #ifdef HAS_HICHECKER_NATIVE_PART
21 #include "hichecker.h"
22 #endif // HAS_HICHECKER_NATIVE_PART
23 #include "thread_local_data.h"
24
25 #ifdef _WIN32
26 #include <windows.h>
27 #define gettid GetCurrentThreadId
28 #define localtime_r(tm, time) localtime_s(time, tm)
29 #endif
30
31 #ifdef __APPLE__
32 #define gettid getpid
33 #endif
34
35 #ifdef __gnu_linux__
36 #include <sys/types.h>
37 #include <sys/syscall.h>
38 #define gettid []() -> int32_t { return static_cast<int32_t>(syscall(SYS_gettid)); }
39 #endif
40
41 DEFINE_HILOG_LABEL("EventHandler");
42
43 using namespace OHOS::HiviewDFX;
44 namespace OHOS {
45 namespace AppExecFwk {
46 static constexpr int DATETIME_STRING_LENGTH = 80;
47
48 thread_local std::weak_ptr<EventHandler> EventHandler::currentEventHandler;
49
Current()50 std::shared_ptr<EventHandler> EventHandler::Current()
51 {
52 return currentEventHandler.lock();
53 }
54
EventHandler(const std::shared_ptr<EventRunner> & runner)55 EventHandler::EventHandler(const std::shared_ptr<EventRunner> &runner) : eventRunner_(runner)
56 {}
57
~EventHandler()58 EventHandler::~EventHandler()
59 {
60 if (eventRunner_) {
61 /*
62 * This handler is finishing, need to remove all events belong to it.
63 * But events only have weak pointer of this handler,
64 * now weak pointer is invalid, so these events become orphans.
65 */
66 eventRunner_->GetEventQueue()->RemoveOrphan();
67 }
68 }
69
SendEvent(InnerEvent::Pointer & event,int64_t delayTime,Priority priority)70 bool EventHandler::SendEvent(InnerEvent::Pointer &event, int64_t delayTime, Priority priority)
71 {
72 if (!event) {
73 HILOGE("SendEvent: Could not send an invalid event");
74 return false;
75 }
76
77 if (!eventRunner_) {
78 HILOGE("SendEvent: MUST Set event runner before sending events");
79 return false;
80 }
81
82 InnerEvent::TimePoint now = InnerEvent::Clock::now();
83 event->SetSendTime(now);
84
85 if (delayTime > 0) {
86 event->SetHandleTime(now + std::chrono::milliseconds(delayTime));
87 } else {
88 event->SetHandleTime(now);
89 }
90
91 event->SetOwner(shared_from_this());
92
93 eventRunner_->GetEventQueue()->Insert(event, priority);
94 return true;
95 }
96
SendTimingEvent(InnerEvent::Pointer & event,int64_t taskTime,Priority priority)97 bool EventHandler::SendTimingEvent(InnerEvent::Pointer &event, int64_t taskTime, Priority priority)
98 {
99 InnerEvent::TimePoint nowSys = InnerEvent::Clock::now();
100 auto epoch = nowSys.time_since_epoch();
101 long nowSysTime = std::chrono::duration_cast<std::chrono::milliseconds>(epoch).count();
102 int64_t delayTime = taskTime - nowSysTime;
103 if (delayTime < 0) {
104 HILOGE("SendTimingEvent: SendTime is before now systime, change to 0 delaytime Event");
105 return SendEvent(event, 0, priority);
106 }
107
108 return SendEvent(event, delayTime, priority);
109 }
110
SendSyncEvent(InnerEvent::Pointer & event,Priority priority)111 bool EventHandler::SendSyncEvent(InnerEvent::Pointer &event, Priority priority)
112 {
113 if ((!event) || (priority == Priority::IDLE)) {
114 HILOGE("SendSyncEvent: Could not send an invalid event or idle event");
115 return false;
116 }
117
118 if ((!eventRunner_) || (!eventRunner_->IsRunning())) {
119 HILOGE("SendSyncEvent: MUST Set a running event runner before sending sync events");
120 return false;
121 }
122
123 // If send a sync event in same event runner, distribute here.
124 if (eventRunner_ == EventRunner::Current()) {
125 DistributeEvent(event);
126 return true;
127 }
128
129 // Create waiter, used to block.
130 auto waiter = event->CreateWaiter();
131 // Send this event as normal one.
132 if (!SendEvent(event, 0, priority)) {
133 return false;
134 }
135 // Wait until event is processed(recycled).
136 waiter->Wait();
137
138 return true;
139 }
140
RemoveAllEvents()141 void EventHandler::RemoveAllEvents()
142 {
143 if (!eventRunner_) {
144 HILOGE("RemoveAllEvents: MUST Set event runner before removing all events");
145 return;
146 }
147
148 eventRunner_->GetEventQueue()->Remove(shared_from_this());
149 }
150
RemoveEvent(uint32_t innerEventId)151 void EventHandler::RemoveEvent(uint32_t innerEventId)
152 {
153 if (!eventRunner_) {
154 HILOGE("RemoveEvent: MUST Set event runner before removing events by id");
155 return;
156 }
157
158 eventRunner_->GetEventQueue()->Remove(shared_from_this(), innerEventId);
159 }
160
RemoveEvent(uint32_t innerEventId,int64_t param)161 void EventHandler::RemoveEvent(uint32_t innerEventId, int64_t param)
162 {
163 if (!eventRunner_) {
164 HILOGE("RemoveEvent: MUST Set event runner before removing events by id and param");
165 return;
166 }
167
168 eventRunner_->GetEventQueue()->Remove(shared_from_this(), innerEventId, param);
169 }
170
RemoveTask(const std::string & name)171 void EventHandler::RemoveTask(const std::string &name)
172 {
173 if (!eventRunner_) {
174 HILOGE("RemoveTask: MUST Set event runner before removing events by task name");
175 return;
176 }
177
178 eventRunner_->GetEventQueue()->Remove(shared_from_this(), name);
179 }
180
AddFileDescriptorListener(int32_t fileDescriptor,uint32_t events,const std::shared_ptr<FileDescriptorListener> & listener)181 ErrCode EventHandler::AddFileDescriptorListener(
182 int32_t fileDescriptor, uint32_t events, const std::shared_ptr<FileDescriptorListener> &listener)
183 {
184 if ((fileDescriptor < 0) || ((events & FILE_DESCRIPTOR_EVENTS_MASK) == 0) || (!listener)) {
185 HILOGE("AddFileDescriptorListener(%{public}d, %{public}u, %{public}s): Invalid parameter",
186 fileDescriptor,
187 events,
188 listener ? "valid" : "null");
189 return EVENT_HANDLER_ERR_INVALID_PARAM;
190 }
191
192 if (!eventRunner_) {
193 HILOGE("AddFileDescriptorListener: MUST Set event runner before adding fd listener");
194 return EVENT_HANDLER_ERR_NO_EVENT_RUNNER;
195 }
196
197 listener->SetOwner(shared_from_this());
198 return eventRunner_->GetEventQueue()->AddFileDescriptorListener(fileDescriptor, events, listener);
199 }
200
RemoveAllFileDescriptorListeners()201 void EventHandler::RemoveAllFileDescriptorListeners()
202 {
203 if (!eventRunner_) {
204 HILOGE("RemoveAllFileDescriptorListeners: MUST Set event runner before removing all fd listener");
205 return;
206 }
207
208 eventRunner_->GetEventQueue()->RemoveFileDescriptorListener(shared_from_this());
209 }
210
RemoveFileDescriptorListener(int32_t fileDescriptor)211 void EventHandler::RemoveFileDescriptorListener(int32_t fileDescriptor)
212 {
213 if (fileDescriptor < 0) {
214 HILOGE("RemoveFileDescriptorListener(%{public}d): Invalid parameter", fileDescriptor);
215 return;
216 }
217
218 if (!eventRunner_) {
219 HILOGE("RemoveFileDescriptorListener: MUST Set event runner before removing fd listener by fd");
220 return;
221 }
222
223 eventRunner_->GetEventQueue()->RemoveFileDescriptorListener(fileDescriptor);
224 }
225
SetEventRunner(const std::shared_ptr<EventRunner> & runner)226 void EventHandler::SetEventRunner(const std::shared_ptr<EventRunner> &runner)
227 {
228 if (eventRunner_ == runner) {
229 return;
230 }
231
232 if (eventRunner_) {
233 HILOGW("SetEventRunner: It is not recommended to change the event runner dynamically");
234
235 // Remove all events and listeners from old event runner.
236 RemoveAllEvents();
237 RemoveAllFileDescriptorListeners();
238 }
239
240 // Switch event runner.
241 eventRunner_ = runner;
242 return;
243 }
244
DeliveryTimeAction(const InnerEvent::Pointer & event,InnerEvent::TimePoint nowStart)245 void EventHandler::DeliveryTimeAction(const InnerEvent::Pointer &event, InnerEvent::TimePoint nowStart)
246 {
247 #ifdef HAS_HICHECKER_NATIVE_PART
248 if (!HiChecker::NeedCheckSlowEvent()) {
249 return;
250 }
251 int64_t deliveryTimeout = eventRunner_->GetDeliveryTimeout();
252 if (deliveryTimeout > 0) {
253 std::string threadName = eventRunner_->GetRunnerThreadName();
254 std::string eventName = GetEventName(event);
255 int64_t threadId = gettid();
256 std::string threadIdCharacter = std::to_string(threadId);
257 std::chrono::duration<double> deliveryTime = nowStart - event->GetSendTime();
258 std::string deliveryTimeCharacter = std::to_string((deliveryTime).count());
259 std::string deliveryTimeoutCharacter = std::to_string(deliveryTimeout);
260 std::string handOutTag = "threadId: " + threadIdCharacter + "," + "threadName: " + threadName + "," +
261 "eventName: " + eventName + "," + "deliveryTime: " + deliveryTimeCharacter + "," +
262 "deliveryTimeout: " + deliveryTimeoutCharacter;
263 if ((nowStart - std::chrono::milliseconds(deliveryTimeout)) > event->GetHandleTime()) {
264 HiChecker::NotifySlowEvent(handOutTag);
265 if (deliveryTimeoutCallback_) {
266 deliveryTimeoutCallback_();
267 }
268 }
269 }
270 #endif // HAS_HICHECKER_NATIVE_PART
271 }
272
DistributeTimeAction(const InnerEvent::Pointer & event,InnerEvent::TimePoint nowStart)273 void EventHandler::DistributeTimeAction(const InnerEvent::Pointer &event, InnerEvent::TimePoint nowStart)
274 {
275 #ifdef HAS_HICHECKER_NATIVE_PART
276 if (!HiChecker::NeedCheckSlowEvent()) {
277 return;
278 }
279 int64_t distributeTimeout = eventRunner_->GetDistributeTimeout();
280 if (distributeTimeout > 0) {
281 std::string threadName = eventRunner_->GetRunnerThreadName();
282 std::string eventName = GetEventName(event);
283 int64_t threadId = gettid();
284 std::string threadIdCharacter = std::to_string(threadId);
285 InnerEvent::TimePoint nowEnd = InnerEvent::Clock::now();
286 std::chrono::duration<double> distributeTime = nowEnd - nowStart;
287 std::string distributeTimeCharacter = std::to_string((distributeTime).count());
288 std::string distributeTimeoutCharacter = std::to_string(distributeTimeout);
289 std::string executeTag = "threadId: " + threadIdCharacter + "," + "threadName: " + threadName + "," +
290 "eventName: " + eventName + "," + "distributeTime: " + distributeTimeCharacter + "," +
291 "distributeTimeout: " + distributeTimeoutCharacter;
292 if ((nowEnd - std::chrono::milliseconds(distributeTimeout)) > nowStart) {
293 HiChecker::NotifySlowEvent(executeTag);
294 if (distributeTimeoutCallback_) {
295 distributeTimeoutCallback_();
296 }
297 }
298 }
299 #endif // HAS_HICHECKER_NATIVE_PART
300 }
301
DistributeEvent(const InnerEvent::Pointer & event)302 void EventHandler::DistributeEvent(const InnerEvent::Pointer &event)
303 {
304 if (!event) {
305 HILOGE("DistributeEvent: Could not distribute an invalid event");
306 return;
307 }
308
309 currentEventHandler = shared_from_this();
310
311 InnerEvent::TimePoint nowStart = InnerEvent::Clock::now();
312 DeliveryTimeAction(event, nowStart);
313
314 if (event->HasTask()) {
315 // Call task callback directly if contains a task.
316 (event->GetTaskCallback())();
317 } else {
318 // Otherwise let developers to handle it.
319 ProcessEvent(event);
320 }
321
322 DistributeTimeAction(event, nowStart);
323 }
324
Dump(Dumper & dumper)325 void EventHandler::Dump(Dumper &dumper)
326 {
327 auto now = std::chrono::system_clock::now();
328 auto tp = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
329 auto tt = std::chrono::system_clock::to_time_t(now);
330 auto us = tp.time_since_epoch().count() % 1000;
331 struct tm curTime = {0};
332 localtime_r(&tt, &curTime);
333 char sysTime[DATETIME_STRING_LENGTH];
334 std::strftime(sysTime, sizeof(char) * DATETIME_STRING_LENGTH, "%Y%m%d %I:%M:%S.", &curTime);
335 auto message = dumper.GetTag() + " EventHandler dump begain curTime:" +
336 std::string(sysTime) + std::to_string(us) + LINE_SEPARATOR;
337 dumper.Dump(message);
338
339 if (eventRunner_ == nullptr) {
340 dumper.Dump(dumper.GetTag() + " event runner uninitialized!" + LINE_SEPARATOR);
341 } else {
342 eventRunner_->Dump(dumper);
343 }
344 }
345
HasInnerEvent(uint32_t innerEventId)346 bool EventHandler::HasInnerEvent(uint32_t innerEventId)
347 {
348 if (!eventRunner_) {
349 HILOGE("event runner uninitialized!");
350 return false;
351 }
352 return eventRunner_->GetEventQueue()->HasInnerEvent(shared_from_this(), innerEventId);
353 }
354
HasInnerEvent(int64_t param)355 bool EventHandler::HasInnerEvent(int64_t param)
356 {
357 if (!eventRunner_) {
358 HILOGE("event runner uninitialized!");
359 return false;
360 }
361 return eventRunner_->GetEventQueue()->HasInnerEvent(shared_from_this(), param);
362 }
363
GetEventName(const InnerEvent::Pointer & event)364 std::string EventHandler::GetEventName(const InnerEvent::Pointer &event)
365 {
366 std::string eventName;
367 if (!event) {
368 return eventName;
369 }
370
371 if (event->HasTask()) {
372 eventName = event->GetTaskName();
373 } else {
374 eventName = std::to_string(event->GetInnerEventId());
375 }
376 return eventName;
377 }
378
IsIdle()379 bool EventHandler::IsIdle()
380 {
381 return eventRunner_->GetEventQueue()->IsIdle();
382 }
383
ProcessEvent(const InnerEvent::Pointer &)384 void EventHandler::ProcessEvent(const InnerEvent::Pointer &)
385 {}
386 } // namespace AppExecFwk
387 } // namespace OHOS
388