• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ && eventRunner_->GetEventQueue()) {
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_ || !eventRunner_->GetEventQueue()) {
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     if (!waiter) {
137         return false;
138     }
139     waiter->Wait();
140 
141     return true;
142 }
143 
RemoveAllEvents()144 void EventHandler::RemoveAllEvents()
145 {
146     if (!eventRunner_ || !eventRunner_->GetEventQueue()) {
147         HILOGE("RemoveAllEvents: MUST Set event runner before removing all events");
148         return;
149     }
150 
151     eventRunner_->GetEventQueue()->Remove(shared_from_this());
152 }
153 
RemoveEvent(uint32_t innerEventId)154 void EventHandler::RemoveEvent(uint32_t innerEventId)
155 {
156     if (!eventRunner_ || !eventRunner_->GetEventQueue()) {
157         HILOGE("RemoveEvent: MUST Set event runner before removing events by id");
158         return;
159     }
160 
161     eventRunner_->GetEventQueue()->Remove(shared_from_this(), innerEventId);
162 }
163 
RemoveEvent(uint32_t innerEventId,int64_t param)164 void EventHandler::RemoveEvent(uint32_t innerEventId, int64_t param)
165 {
166     if (!eventRunner_ || !eventRunner_->GetEventQueue()) {
167         HILOGE("RemoveEvent: MUST Set event runner before removing events by id and param");
168         return;
169     }
170 
171     eventRunner_->GetEventQueue()->Remove(shared_from_this(), innerEventId, param);
172 }
173 
RemoveTask(const std::string & name)174 void EventHandler::RemoveTask(const std::string &name)
175 {
176     if (!eventRunner_ || !eventRunner_->GetEventQueue()) {
177         HILOGE("RemoveTask: MUST Set event runner before removing events by task name");
178         return;
179     }
180 
181     eventRunner_->GetEventQueue()->Remove(shared_from_this(), name);
182 }
183 
AddFileDescriptorListener(int32_t fileDescriptor,uint32_t events,const std::shared_ptr<FileDescriptorListener> & listener)184 ErrCode EventHandler::AddFileDescriptorListener(
185     int32_t fileDescriptor, uint32_t events, const std::shared_ptr<FileDescriptorListener> &listener)
186 {
187     if ((fileDescriptor < 0) || ((events & FILE_DESCRIPTOR_EVENTS_MASK) == 0) || (!listener)) {
188         HILOGE("AddFileDescriptorListener(%{public}d, %{public}u, %{public}s): Invalid parameter",
189             fileDescriptor,
190             events,
191             listener ? "valid" : "null");
192         return EVENT_HANDLER_ERR_INVALID_PARAM;
193     }
194 
195     if (!eventRunner_ || !eventRunner_->GetEventQueue()) {
196         HILOGE("AddFileDescriptorListener: MUST Set event runner before adding fd listener");
197         return EVENT_HANDLER_ERR_NO_EVENT_RUNNER;
198     }
199 
200     listener->SetOwner(shared_from_this());
201     return eventRunner_->GetEventQueue()->AddFileDescriptorListener(fileDescriptor, events, listener);
202 }
203 
RemoveAllFileDescriptorListeners()204 void EventHandler::RemoveAllFileDescriptorListeners()
205 {
206     if (!eventRunner_ || !eventRunner_->GetEventQueue()) {
207         HILOGE("RemoveAllFileDescriptorListeners: MUST Set event runner before removing all fd listener");
208         return;
209     }
210 
211     eventRunner_->GetEventQueue()->RemoveFileDescriptorListener(shared_from_this());
212 }
213 
RemoveFileDescriptorListener(int32_t fileDescriptor)214 void EventHandler::RemoveFileDescriptorListener(int32_t fileDescriptor)
215 {
216     if (fileDescriptor < 0) {
217         HILOGE("RemoveFileDescriptorListener(%{public}d): Invalid parameter", fileDescriptor);
218         return;
219     }
220 
221     if (!eventRunner_ || !eventRunner_->GetEventQueue()) {
222         HILOGE("RemoveFileDescriptorListener: MUST Set event runner before removing fd listener by fd");
223         return;
224     }
225 
226     eventRunner_->GetEventQueue()->RemoveFileDescriptorListener(fileDescriptor);
227 }
228 
SetEventRunner(const std::shared_ptr<EventRunner> & runner)229 void EventHandler::SetEventRunner(const std::shared_ptr<EventRunner> &runner)
230 {
231     if (eventRunner_ == runner) {
232         return;
233     }
234 
235     if (eventRunner_) {
236         HILOGW("SetEventRunner: It is not recommended to change the event runner dynamically");
237 
238         // Remove all events and listeners from old event runner.
239         RemoveAllEvents();
240         RemoveAllFileDescriptorListeners();
241     }
242 
243     // Switch event runner.
244     eventRunner_ = runner;
245     return;
246 }
247 
DeliveryTimeAction(const InnerEvent::Pointer & event,InnerEvent::TimePoint nowStart)248 void EventHandler::DeliveryTimeAction(const InnerEvent::Pointer &event, InnerEvent::TimePoint nowStart)
249 {
250 #ifdef HAS_HICHECKER_NATIVE_PART
251     if (!HiChecker::NeedCheckSlowEvent()) {
252         return;
253     }
254     if (!eventRunner_ || !event) {
255         return;
256     }
257     int64_t deliveryTimeout = eventRunner_->GetDeliveryTimeout();
258     if (deliveryTimeout > 0) {
259         std::string threadName = eventRunner_->GetRunnerThreadName();
260         std::string eventName = GetEventName(event);
261         int64_t threadId = gettid();
262         std::string threadIdCharacter = std::to_string(threadId);
263         std::chrono::duration<double> deliveryTime = nowStart - event->GetSendTime();
264         std::string deliveryTimeCharacter = std::to_string((deliveryTime).count());
265         std::string deliveryTimeoutCharacter = std::to_string(deliveryTimeout);
266         std::string handOutTag = "threadId: " + threadIdCharacter + "," + "threadName: " + threadName + "," +
267             "eventName: " + eventName + "," + "deliveryTime: " + deliveryTimeCharacter + "," +
268             "deliveryTimeout: " + deliveryTimeoutCharacter;
269         if ((nowStart - std::chrono::milliseconds(deliveryTimeout)) > event->GetHandleTime()) {
270             HiChecker::NotifySlowEvent(handOutTag);
271             if (deliveryTimeoutCallback_) {
272                 deliveryTimeoutCallback_();
273             }
274         }
275     }
276 #endif // HAS_HICHECKER_NATIVE_PART
277 }
278 
DistributeTimeAction(const InnerEvent::Pointer & event,InnerEvent::TimePoint nowStart)279 void EventHandler::DistributeTimeAction(const InnerEvent::Pointer &event, InnerEvent::TimePoint nowStart)
280 {
281 #ifdef HAS_HICHECKER_NATIVE_PART
282     if (!HiChecker::NeedCheckSlowEvent()) {
283         return;
284     }
285     if (!eventRunner_ || !event) {
286         return;
287     }
288     int64_t distributeTimeout = eventRunner_->GetDistributeTimeout();
289     if (distributeTimeout > 0) {
290         std::string threadName = eventRunner_->GetRunnerThreadName();
291         std::string eventName = GetEventName(event);
292         int64_t threadId = gettid();
293         std::string threadIdCharacter = std::to_string(threadId);
294         InnerEvent::TimePoint nowEnd = InnerEvent::Clock::now();
295         std::chrono::duration<double> distributeTime = nowEnd - nowStart;
296         std::string distributeTimeCharacter = std::to_string((distributeTime).count());
297         std::string distributeTimeoutCharacter = std::to_string(distributeTimeout);
298         std::string executeTag = "threadId: " + threadIdCharacter + "," + "threadName: " + threadName + "," +
299             "eventName: " + eventName + "," + "distributeTime: " + distributeTimeCharacter + "," +
300             "distributeTimeout: " + distributeTimeoutCharacter;
301         if ((nowEnd - std::chrono::milliseconds(distributeTimeout)) > nowStart) {
302             HiChecker::NotifySlowEvent(executeTag);
303             if (distributeTimeoutCallback_) {
304                 distributeTimeoutCallback_();
305             }
306         }
307     }
308 #endif // HAS_HICHECKER_NATIVE_PART
309 }
310 
DistributeEvent(const InnerEvent::Pointer & event)311 void EventHandler::DistributeEvent(const InnerEvent::Pointer &event)
312 {
313     if (!event) {
314         HILOGE("DistributeEvent: Could not distribute an invalid event");
315         return;
316     }
317 
318     currentEventHandler = shared_from_this();
319 
320     InnerEvent::TimePoint nowStart = InnerEvent::Clock::now();
321     DeliveryTimeAction(event, nowStart);
322 
323     if (event->HasTask()) {
324         // Call task callback directly if contains a task.
325         (event->GetTaskCallback())();
326     } else {
327         // Otherwise let developers to handle it.
328         ProcessEvent(event);
329     }
330 
331     DistributeTimeAction(event, nowStart);
332 }
333 
Dump(Dumper & dumper)334 void EventHandler::Dump(Dumper &dumper)
335 {
336     auto now = std::chrono::system_clock::now();
337     auto tp = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
338     auto tt = std::chrono::system_clock::to_time_t(now);
339     auto us = tp.time_since_epoch().count() % 1000;
340     struct tm curTime = {0};
341     localtime_r(&tt, &curTime);
342     char sysTime[DATETIME_STRING_LENGTH];
343     std::strftime(sysTime, sizeof(char) * DATETIME_STRING_LENGTH, "%Y%m%d %I:%M:%S.", &curTime);
344     auto message = dumper.GetTag() + " EventHandler dump begain curTime:" +
345                    std::string(sysTime) + std::to_string(us) + LINE_SEPARATOR;
346     dumper.Dump(message);
347 
348     if (eventRunner_ == nullptr) {
349         dumper.Dump(dumper.GetTag() + " event runner uninitialized!" + LINE_SEPARATOR);
350     } else {
351         eventRunner_->Dump(dumper);
352     }
353 }
354 
HasInnerEvent(uint32_t innerEventId)355 bool EventHandler::HasInnerEvent(uint32_t innerEventId)
356 {
357     if (!eventRunner_ || !eventRunner_->GetEventQueue()) {
358         HILOGE("event runner uninitialized!");
359         return false;
360     }
361     return eventRunner_->GetEventQueue()->HasInnerEvent(shared_from_this(), innerEventId);
362 }
363 
HasInnerEvent(int64_t param)364 bool EventHandler::HasInnerEvent(int64_t param)
365 {
366     if (!eventRunner_ || !eventRunner_->GetEventQueue()) {
367         HILOGE("event runner uninitialized!");
368         return false;
369     }
370     return eventRunner_->GetEventQueue()->HasInnerEvent(shared_from_this(), param);
371 }
372 
GetEventName(const InnerEvent::Pointer & event)373 std::string EventHandler::GetEventName(const InnerEvent::Pointer &event)
374 {
375     std::string eventName;
376     if (!event) {
377         return eventName;
378     }
379 
380     if (event->HasTask()) {
381         eventName = event->GetTaskName();
382     } else {
383         eventName = std::to_string(event->GetInnerEventId());
384     }
385     return eventName;
386 }
387 
IsIdle()388 bool EventHandler::IsIdle()
389 {
390     if (!eventRunner_ || !eventRunner_->GetEventQueue()) {
391         return false;
392     }
393     return eventRunner_->GetEventQueue()->IsIdle();
394 }
395 
ProcessEvent(const InnerEvent::Pointer &)396 void EventHandler::ProcessEvent(const InnerEvent::Pointer &)
397 {}
398 }  // namespace AppExecFwk
399 }  // namespace OHOS
400