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