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