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