1 
2 /*
3  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "event_queue_base.h"
18 
19 #include <algorithm>
20 #include <chrono>
21 #include <iterator>
22 #include <mutex>
23 
24 #include "deamon_io_waiter.h"
25 #include "event_handler.h"
26 #include "event_handler_utils.h"
27 #include "event_logger.h"
28 #include "inner_event.h"
29 #include "none_io_waiter.h"
30 #include "event_hitrace_meter_adapter.h"
31 
32 namespace OHOS {
33 namespace AppExecFwk {
34 namespace {
35 
36 DEFINE_EH_HILOG_LABEL("EventQueueBase");
37 constexpr uint32_t MAX_DUMP_SIZE = 500;
38 constexpr int64_t GC_TIME_OUT = 300;
39 constexpr std::string_view STAGE_BEFORE_WAITING = "BEFORE_WAITING";
40 constexpr std::string_view STAGE_AFTER_WAITING = "AFTER_WAITING";
41 // Help to insert events into the event queue sorted by handle time.
InsertEventsLocked(std::list<InnerEvent::Pointer> & events,InnerEvent::Pointer & event,EventInsertType insertType)42 void InsertEventsLocked(std::list<InnerEvent::Pointer> &events, InnerEvent::Pointer &event,
43     EventInsertType insertType)
44 {
45     if (insertType == EventInsertType::AT_FRONT) {
46         if (!events.empty()) {
47             // Ensure that events queue is in ordered
48             auto headEvent = events.begin();
49             if ((*headEvent)->GetHandleTime() < event->GetHandleTime()) {
50                 event->SetHandleTime((*headEvent)->GetHandleTime());
51             }
52         }
53         events.emplace_front(std::move(event));
54         return;
55     }
56 
57     auto f = [](const InnerEvent::Pointer &first, const InnerEvent::Pointer &second) {
58         if (!first || !second) {
59             return false;
60         }
61         return first->GetHandleTime() < second->GetHandleTime();
62     };
63     auto it = std::upper_bound(events.begin(), events.end(), event, f);
64     events.insert(it, std::move(event));
65 }
66 
67 // Help to check whether there is a valid event in list and update wake up time.
CheckEventInListLocked(const std::list<InnerEvent::Pointer> & events,const InnerEvent::TimePoint & now,InnerEvent::TimePoint & nextWakeUpTime)68 inline bool CheckEventInListLocked(const std::list<InnerEvent::Pointer> &events, const InnerEvent::TimePoint &now,
69     InnerEvent::TimePoint &nextWakeUpTime)
70 {
71     if (!events.empty()) {
72         const auto &handleTime = events.front()->GetHandleTime();
73         if (handleTime < nextWakeUpTime) {
74             nextWakeUpTime = handleTime;
75             return handleTime <= now;
76         }
77     }
78 
79     return false;
80 }
81 
PopFrontEventFromListLocked(std::list<InnerEvent::Pointer> & events)82 inline InnerEvent::Pointer PopFrontEventFromListLocked(std::list<InnerEvent::Pointer> &events)
83 {
84     InnerEvent::Pointer event = std::move(events.front());
85     events.pop_front();
86     return event;
87 }
88 }  // unnamed namespace
89 
EventQueueBase()90 EventQueueBase::EventQueueBase() : EventQueue(), historyEvents_(std::vector<HistoryEvent>(HISTORY_EVENT_NUM_POWER))
91 {
92     HILOGD("enter");
93 }
94 
EventQueueBase(const std::shared_ptr<IoWaiter> & ioWaiter)95 EventQueueBase::EventQueueBase(const std::shared_ptr<IoWaiter> &ioWaiter)
96     : EventQueue(ioWaiter), historyEvents_(std::vector<HistoryEvent>(HISTORY_EVENT_NUM_POWER))
97 {
98     HILOGD("enter");
99 }
100 
~EventQueueBase()101 EventQueueBase::~EventQueueBase()
102 {
103     std::lock_guard<std::mutex> lock(queueLock_);
104     usable_.store(false);
105     ioWaiter_ = nullptr;
106     ClearObserver();
107     EH_LOGI_LIMIT("EventQueueBase is unavailable hence");
108 }
109 
Insert(InnerEvent::Pointer & event,Priority priority,EventInsertType insertType)110 void EventQueueBase::Insert(InnerEvent::Pointer &event, Priority priority, EventInsertType insertType)
111 {
112     if (!event) {
113         HILOGE("Could not insert an invalid event");
114         return;
115     }
116     HILOGD("Insert task: %{public}s %{public}d.", (event->GetEventUniqueId()).c_str(), insertType);
117     std::lock_guard<std::mutex> lock(queueLock_);
118     if (!usable_.load()) {
119         HILOGW("EventQueue is unavailable.");
120         return;
121     }
122     bool needNotify = false;
123     event->SetEventPriority(static_cast<int32_t>(priority));
124     switch (priority) {
125         case Priority::VIP:
126         case Priority::IMMEDIATE:
127         case Priority::HIGH:
128         case Priority::LOW: {
129             needNotify = (event->GetHandleTime() < wakeUpTime_);
130             InsertEventsLocked(subEventQueues_[static_cast<uint32_t>(priority)].queue, event, insertType);
131             break;
132         }
133         case Priority::IDLE: {
134             // Never wake up thread if insert an idle event.
135             InsertEventsLocked(idleEvents_, event, insertType);
136             break;
137         }
138         default:
139             break;
140     }
141 
142     if (needNotify) {
143         ioWaiter_->NotifyOne();
144     }
145 }
146 
RemoveOrphan()147 void EventQueueBase::RemoveOrphan()
148 {
149     HILOGD("enter");
150     // Remove all events which lost its owner.
151     auto filter = [](const InnerEvent::Pointer &p) { return p->GetWeakOwner().expired(); };
152 
153     RemoveOrphan(filter);
154 
155     std::lock_guard<std::mutex> lock(queueLock_);
156     if (!usable_.load()) {
157         HILOGW("EventQueueBase is unavailable.");
158         return;
159     }
160     RemoveInvalidFileDescriptor();
161 }
162 
163 
RemoveAll()164 void EventQueueBase::RemoveAll()
165 {
166     HILOGD("enter");
167     std::lock_guard<std::mutex> lock(queueLock_);
168     if (!usable_.load()) {
169         HILOGW("EventQueueBase is unavailable.");
170         return;
171     }
172     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
173         subEventQueues_[i].queue.clear();
174     }
175     idleEvents_.clear();
176 }
177 
Remove(const std::shared_ptr<EventHandler> & owner)178 void EventQueueBase::Remove(const std::shared_ptr<EventHandler> &owner)
179 {
180     HILOGD("enter");
181     if (!owner) {
182         HILOGE("Invalid owner");
183         return;
184     }
185 
186     auto filter = [&owner](const InnerEvent::Pointer &p) { return (p->GetOwner() == owner); };
187 
188     Remove(filter);
189 }
190 
Remove(const std::shared_ptr<EventHandler> & owner,uint32_t innerEventId)191 void EventQueueBase::Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId)
192 {
193     HILOGD("enter");
194     if (!owner) {
195         HILOGE("Invalid owner");
196         return;
197     }
198     auto filter = [&owner, innerEventId](const InnerEvent::Pointer &p) {
199         return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId);
200     };
201 
202     Remove(filter);
203 }
204 
Remove(const std::shared_ptr<EventHandler> & owner,uint32_t innerEventId,int64_t param)205 void EventQueueBase::Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId, int64_t param)
206 {
207     HILOGD("enter");
208     if (!owner) {
209         HILOGE("Invalid owner");
210         return;
211     }
212 
213     auto filter = [&owner, innerEventId, param](const InnerEvent::Pointer &p) {
214         return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId) &&
215                (p->GetParam() == param);
216     };
217 
218     Remove(filter);
219 }
220 
Remove(const std::shared_ptr<EventHandler> & owner,const std::string & name)221 bool EventQueueBase::Remove(const std::shared_ptr<EventHandler> &owner, const std::string &name)
222 {
223     HILOGD("enter");
224     if ((!owner) || (name.empty())) {
225         HILOGE("Invalid owner or task name");
226         return false;
227     }
228 
229     bool removed = false;
230     auto filter = [&owner, &name, &removed](const InnerEvent::Pointer &p) {
231         if (p == nullptr) {
232             return false;
233         }
234         bool ret = (p->HasTask()) && (p->GetOwner() == owner) && (p->GetTaskName() == name);
235         if (!removed) {
236             removed = ret;
237         }
238         return ret;
239     };
240 
241     Remove(filter);
242     return removed;
243 }
244 
Remove(const RemoveFilter & filter)245 void EventQueueBase::Remove(const RemoveFilter &filter)
246 {
247     HILOGD("enter");
248     std::lock_guard<std::mutex> lock(queueLock_);
249     if (!usable_.load()) {
250         HILOGW("EventQueueBase is unavailable.");
251         return;
252     }
253     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
254         subEventQueues_[i].queue.remove_if(filter);
255     }
256     idleEvents_.remove_if(filter);
257 }
258 
RemoveOrphan(const RemoveFilter & filter)259 void EventQueueBase::RemoveOrphan(const RemoveFilter &filter)
260 {
261     std::list<InnerEvent::Pointer> releaseIdleEvents;
262     std::array<SubEventQueue, SUB_EVENT_QUEUE_NUM> releaseEventsQueue;
263     {
264         std::lock_guard<std::mutex> lock(queueLock_);
265         if (!usable_.load()) {
266             HILOGW("EventQueueBase is unavailable.");
267             return;
268         }
269         for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
270             auto it = std::stable_partition(subEventQueues_[i].queue.begin(), subEventQueues_[i].queue.end(), filter);
271             std::move(subEventQueues_[i].queue.begin(), it, std::back_inserter(releaseEventsQueue[i].queue));
272             subEventQueues_[i].queue.erase(subEventQueues_[i].queue.begin(), it);
273         }
274         auto idleEventIt = std::stable_partition(idleEvents_.begin(), idleEvents_.end(), filter);
275         std::move(idleEvents_.begin(), idleEventIt, std::back_inserter(releaseIdleEvents));
276         idleEvents_.erase(idleEvents_.begin(), idleEventIt);
277     }
278 }
279 
HasInnerEvent(const std::shared_ptr<EventHandler> & owner,uint32_t innerEventId)280 bool EventQueueBase::HasInnerEvent(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId)
281 {
282     if (!owner) {
283         HILOGE("Invalid owner");
284         return false;
285     }
286     auto filter = [&owner, innerEventId](const InnerEvent::Pointer &p) {
287         return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId);
288     };
289     return HasInnerEvent(filter);
290 }
291 
HasInnerEvent(const std::shared_ptr<EventHandler> & owner,int64_t param)292 bool EventQueueBase::HasInnerEvent(const std::shared_ptr<EventHandler> &owner, int64_t param)
293 {
294     if (!owner) {
295         HILOGE("Invalid owner");
296         return false;
297     }
298     auto filter = [&owner, param](const InnerEvent::Pointer &p) {
299         return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetParam() == param);
300     };
301     return HasInnerEvent(filter);
302 }
303 
HasInnerEvent(const HasFilter & filter)304 bool EventQueueBase::HasInnerEvent(const HasFilter &filter)
305 {
306     std::lock_guard<std::mutex> lock(queueLock_);
307     if (!usable_.load()) {
308         HILOGW("EventQueueBase is unavailable.");
309         return false;
310     }
311     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
312         std::list<InnerEvent::Pointer>::iterator iter =
313             std::find_if(subEventQueues_[i].queue.begin(), subEventQueues_[i].queue.end(), filter);
314         if (iter != subEventQueues_[i].queue.end()) {
315             return true;
316         }
317     }
318     if (std::find_if(idleEvents_.begin(), idleEvents_.end(), filter) != idleEvents_.end()) {
319         return true;
320     }
321     return false;
322 }
323 
PickEventLocked(const InnerEvent::TimePoint & now,InnerEvent::TimePoint & nextWakeUpTime)324 InnerEvent::Pointer EventQueueBase::PickEventLocked(const InnerEvent::TimePoint &now,
325     InnerEvent::TimePoint &nextWakeUpTime)
326 {
327     uint32_t priorityIndex = SUB_EVENT_QUEUE_NUM;
328     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
329         // Check whether any event need to be distributed.
330         if (!CheckEventInListLocked(subEventQueues_[i].queue, now, nextWakeUpTime)) {
331             continue;
332         }
333 
334         // Check whether any event in higher priority need to be distributed.
335         if (priorityIndex < SUB_EVENT_QUEUE_NUM) {
336             SubEventQueue &subQueue = subEventQueues_[priorityIndex];
337             // Check whether enough events in higher priority queue are handled continuously.
338             if (subQueue.handledEventsCount < subQueue.maxHandledEventsCount) {
339                 subQueue.handledEventsCount++;
340                 break;
341             }
342         }
343 
344         // Try to pick event from this queue.
345         priorityIndex = i;
346     }
347 
348     if (priorityIndex >= SUB_EVENT_QUEUE_NUM) {
349         // If not found any event to distribute, return nullptr.
350         return InnerEvent::Pointer(nullptr, nullptr);
351     }
352 
353     // Reset handled event count for sub event queues in higher priority.
354     for (uint32_t i = 0; i < priorityIndex; ++i) {
355         subEventQueues_[i].handledEventsCount = 0;
356     }
357 
358     return PopFrontEventFromListLocked(subEventQueues_[priorityIndex].queue);
359 }
360 
GetExpiredEventLocked(InnerEvent::TimePoint & nextExpiredTime)361 InnerEvent::Pointer EventQueueBase::GetExpiredEventLocked(InnerEvent::TimePoint &nextExpiredTime)
362 {
363     auto now = InnerEvent::Clock::now();
364     wakeUpTime_ = InnerEvent::TimePoint::max();
365     // Find an event which could be distributed right now.
366     InnerEvent::Pointer event = PickEventLocked(now, wakeUpTime_);
367     if (event) {
368         // Exit idle mode, if found an event to distribute.
369         isIdle_ = false;
370         currentRunningEvent_ = CurrentRunningEvent(now, event);
371         return event;
372     }
373 
374     // If found nothing, enter idle mode and make a time stamp.
375     if (!isIdle_) {
376         idleTimeStamp_ = now;
377         isIdle_ = true;
378     }
379 
380     if (!idleEvents_.empty()) {
381         const auto &idleEvent = idleEvents_.front();
382 
383         // Return the idle event that has been sent before time stamp and reaches its handle time.
384         if ((idleEvent->GetSendTime() <= idleTimeStamp_) && (idleEvent->GetHandleTime() <= now)) {
385             event = PopFrontEventFromListLocked(idleEvents_);
386             currentRunningEvent_ = CurrentRunningEvent(now, event);
387             return event;
388         }
389     }
390 
391     // Update wake up time.
392     nextExpiredTime = wakeUpTime_;
393     currentRunningEvent_ = CurrentRunningEvent();
394     return InnerEvent::Pointer(nullptr, nullptr);
395 }
396 
GetEvent()397 InnerEvent::Pointer EventQueueBase::GetEvent()
398 {
399     std::unique_lock<std::mutex> lock(queueLock_);
400     while (!finished_) {
401         InnerEvent::TimePoint nextWakeUpTime = InnerEvent::TimePoint::max();
402         InnerEvent::Pointer event = GetExpiredEventLocked(nextWakeUpTime);
403         if (event) {
404             return event;
405         }
406         TryExecuteObserverCallback(nextWakeUpTime, EventRunnerStage::STAGE_BEFORE_WAITING);
407         WaitUntilLocked(nextWakeUpTime, lock);
408         TryExecuteObserverCallback(nextWakeUpTime, EventRunnerStage::STAGE_AFTER_WAITING);
409     }
410 
411     HILOGD("Break out");
412     return InnerEvent::Pointer(nullptr, nullptr);
413 }
414 
TryExecuteObserverCallback(InnerEvent::TimePoint & nextExpiredTime,EventRunnerStage stage)415 void EventQueueBase::TryExecuteObserverCallback(InnerEvent::TimePoint &nextExpiredTime, EventRunnerStage stage)
416 {
417     uint32_t stageUint = static_cast<uint32_t>(stage);
418     if ((stageUint & observer_.stages) != stageUint) {
419         HILOGD("The observer does not subscribe to this type of notification");
420         return;
421     }
422     if (observer_.notifyCb == nullptr) {
423         HILOGD("notifyCb is nullptr");
424         return;
425     }
426     int64_t consumer = 0;
427     StageInfo info;
428     ObserverTrace obs;
429     obs.source = GetObserverTypeName(observer_.observer);
430     switch (stage) {
431         case EventRunnerStage::STAGE_BEFORE_WAITING:
432             info.sleepTime = NanosecondsToTimeout(TimePointToTimeOut(nextExpiredTime));
433             obs.stage = STAGE_BEFORE_WAITING.data();
434             consumer = ExecuteObserverCallback(obs, stage, info);
435             if (nextExpiredTime < InnerEvent::TimePoint::max()) {
436                 HILOGD("time consumer: %{public}lld", static_cast<long long>(consumer));
437                 nextExpiredTime = nextExpiredTime + std::chrono::milliseconds(consumer);
438             }
439             break;
440         case EventRunnerStage::STAGE_AFTER_WAITING:
441             obs.stage = STAGE_AFTER_WAITING.data();
442             consumer = ExecuteObserverCallback(obs, stage, info);
443             break;
444         default:
445             HILOGE("this branch is unreachable");
446             break;
447     }
448     if (consumer > GC_TIME_OUT) {
449         HILOGI("execute observer callback task consumer: %{public}lld, stage: %{public}u",
450             static_cast<long long>(consumer), stageUint);
451     }
452 }
453 
ExecuteObserverCallback(ObserverTrace obsTrace,EventRunnerStage stage,StageInfo & info)454 int64_t EventQueueBase::ExecuteObserverCallback(ObserverTrace obsTrace, EventRunnerStage stage, StageInfo &info)
455 {
456     auto start = std::chrono::high_resolution_clock::now();
457     info.timestamp = std::chrono::time_point_cast<std::chrono::milliseconds>(start).time_since_epoch().count();
458 
459     StartTraceObserver(obsTrace);
460     (observer_.notifyCb)(stage, &info);
461     FinishTraceAdapter();
462     auto end = std::chrono::high_resolution_clock::now();
463     auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end-start);
464     return duration.count();
465 }
466 
GetObserverTypeName(Observer observerType)467 std::string EventQueueBase::GetObserverTypeName(Observer observerType)
468 {
469     switch (observerType) {
470         case Observer::ARKTS_GC:
471             return "ARKTS_GC";
472         default :
473             return "UNKNOWN_TYPE";
474     }
475 }
476 
477 
ClearObserver()478 void EventQueueBase::ClearObserver()
479 {
480     observer_.stages = static_cast<uint32_t>(EventRunnerStage::STAGE_INVAILD);
481     observer_.notifyCb = nullptr;
482 }
483 
GetExpiredEvent(InnerEvent::TimePoint & nextExpiredTime)484 InnerEvent::Pointer EventQueueBase::GetExpiredEvent(InnerEvent::TimePoint &nextExpiredTime)
485 {
486     std::unique_lock<std::mutex> lock(queueLock_);
487     return GetExpiredEventLocked(nextExpiredTime);
488 }
489 
DumpCurrentRunningEventId(const InnerEvent::EventId & innerEventId,std::string & content)490 void EventQueueBase::DumpCurrentRunningEventId(const InnerEvent::EventId &innerEventId, std::string &content)
491 {
492     if (innerEventId.index() == TYPE_U32_INDEX) {
493         content.append(", id = " + std::to_string(std::get<uint32_t>(innerEventId)));
494     } else {
495         content.append(", id = " + std::get<std::string>(innerEventId));
496     }
497 }
498 
DumpCurrentRunning()499 std::string EventQueueBase::DumpCurrentRunning()
500 {
501     std::string content;
502     if (currentRunningEvent_.beginTime_ == InnerEvent::TimePoint::max()) {
503         content.append("{}");
504     } else {
505         content.append("start at " + InnerEvent::DumpTimeToString(currentRunningEvent_.beginTime_) + ", ");
506         content.append("Event { ");
507         if (!currentRunningEvent_.owner_.expired()) {
508             content.append("send thread = " + std::to_string(currentRunningEvent_.senderKernelThreadId_));
509             content.append(", send time = " + InnerEvent::DumpTimeToString(currentRunningEvent_.sendTime_));
510             content.append(", handle time = " + InnerEvent::DumpTimeToString(currentRunningEvent_.handleTime_));
511             content.append(", trigger time = " + InnerEvent::DumpTimeToString(currentRunningEvent_.triggerTime_));
512             if (currentRunningEvent_.hasTask_) {
513                 content.append(", task name = " + currentRunningEvent_.taskName_);
514             } else {
515                 DumpCurrentRunningEventId(currentRunningEvent_.innerEventId_, content);
516             }
517             if (currentRunningEvent_.param_ != 0) {
518                 content.append(", param = " + std::to_string(currentRunningEvent_.param_));
519             }
520             content.append(", caller = " + currentRunningEvent_.callerInfo_);
521         } else {
522             content.append("No handler");
523         }
524         content.append(" }");
525     }
526 
527     return content;
528 }
529 
DumpCurentQueueInfo(Dumper & dumper,uint32_t dumpMaxSize)530 void EventQueueBase::DumpCurentQueueInfo(Dumper &dumper, uint32_t dumpMaxSize)
531 {
532     std::string priority[] = {"VIP", "Immediate", "High", "Low"};
533     uint32_t total = 0;
534     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
535         uint32_t n = 0;
536         dumper.Dump(dumper.GetTag() + " " + priority[i] + " priority event queue information:" +
537             std::string(LINE_SEPARATOR));
538         for (auto it = subEventQueues_[i].queue.begin(); it != subEventQueues_[i].queue.end(); ++it) {
539             ++n;
540             if (total < dumpMaxSize) {
541                 dumper.Dump(dumper.GetTag() + " No." + std::to_string(n) + " : " + (*it)->Dump());
542             }
543             ++total;
544         }
545         dumper.Dump(dumper.GetTag() + " Total size of " + priority[i] + " events : " + std::to_string(n) +
546             std::string(LINE_SEPARATOR));
547     }
548     dumper.Dump(dumper.GetTag() + " Idle priority event queue information:" + std::string(LINE_SEPARATOR));
549     int n = 0;
550     for (auto it = idleEvents_.begin(); it != idleEvents_.end(); ++it) {
551         ++n;
552         if (total < dumpMaxSize) {
553             dumper.Dump(dumper.GetTag() + " No." + std::to_string(n) + " : " + (*it)->Dump());
554         }
555         ++total;
556     }
557     dumper.Dump(dumper.GetTag() + " Total size of Idle events : " + std::to_string(n) + std::string(LINE_SEPARATOR));
558     dumper.Dump(dumper.GetTag() + " Total event size : " + std::to_string(total) + std::string(LINE_SEPARATOR));
559 }
560 
Dump(Dumper & dumper)561 void EventQueueBase::Dump(Dumper &dumper)
562 {
563     std::lock_guard<std::mutex> lock(queueLock_);
564     if (!usable_.load()) {
565         HILOGW("EventQueueBase is unavailable.");
566         return;
567     }
568     dumper.Dump(dumper.GetTag() + " Current Running: " + DumpCurrentRunning() + std::string(LINE_SEPARATOR));
569     dumper.Dump(dumper.GetTag() + " History event queue information:" + std::string(LINE_SEPARATOR));
570     uint32_t dumpMaxSize = MAX_DUMP_SIZE;
571     for (uint8_t i = 0; i < HISTORY_EVENT_NUM_POWER; i++) {
572         if (historyEvents_[i].senderKernelThreadId == 0) {
573             continue;
574         }
575         --dumpMaxSize;
576         dumper.Dump(dumper.GetTag() + " No. " + std::to_string(i) + " : " + HistoryQueueDump(historyEvents_[i]));
577     }
578     DumpCurentQueueInfo(dumper, dumpMaxSize);
579 }
580 
DumpQueueInfo(std::string & queueInfo)581 void EventQueueBase::DumpQueueInfo(std::string& queueInfo)
582 {
583     std::lock_guard<std::mutex> lock(queueLock_);
584     if (!usable_.load()) {
585         HILOGW("EventQueueBase is unavailable.");
586         return;
587     }
588     std::string priority[] = {"VIP", "Immediate", "High", "Low"};
589     uint32_t total = 0;
590     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
591         uint32_t n = 0;
592         queueInfo +=  "            " + priority[i] + " priority event queue:" + std::string(LINE_SEPARATOR);
593         for (auto it = subEventQueues_[i].queue.begin(); it != subEventQueues_[i].queue.end(); ++it) {
594             ++n;
595             queueInfo +=  "            No." + std::to_string(n) + " : " + (*it)->Dump();
596             ++total;
597         }
598         queueInfo +=  "              Total size of " + priority[i] + " events : " + std::to_string(n) +
599             std::string(LINE_SEPARATOR);
600     }
601 
602     queueInfo += "            Idle priority event queue:" + std::string(LINE_SEPARATOR);
603 
604     int n = 0;
605     for (auto it = idleEvents_.begin(); it != idleEvents_.end(); ++it) {
606         ++n;
607         queueInfo += "            No." + std::to_string(n) + " : " + (*it)->Dump();
608         ++total;
609     }
610     queueInfo += "              Total size of Idle events : " + std::to_string(n) + std::string(LINE_SEPARATOR);
611     queueInfo += "            Total event size : " + std::to_string(total);
612 }
613 
IsIdle()614 bool EventQueueBase::IsIdle()
615 {
616     return isIdle_;
617 }
618 
IsQueueEmpty()619 bool EventQueueBase::IsQueueEmpty()
620 {
621     std::lock_guard<std::mutex> lock(queueLock_);
622     if (!usable_.load()) {
623         HILOGW("EventQueueBase is unavailable.");
624         return false;
625     }
626     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
627         uint32_t queueSize = subEventQueues_[i].queue.size();
628         if (queueSize != 0) {
629             return false;
630         }
631     }
632 
633     return idleEvents_.size() == 0;
634 }
635 
PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer & event)636 void EventQueueBase::PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer &event)
637 {
638     if (event == nullptr) {
639         HILOGW("event is nullptr.");
640         return;
641     }
642     historyEvents_[historyEventIndex_].senderKernelThreadId = event->GetSenderKernelThreadId();
643     historyEvents_[historyEventIndex_].sendTime = event->GetSendTime();
644     historyEvents_[historyEventIndex_].handleTime = event->GetHandleTime();
645     historyEvents_[historyEventIndex_].triggerTime = InnerEvent::Clock::now();
646     historyEvents_[historyEventIndex_].priority = event->GetEventPriority();
647     historyEvents_[historyEventIndex_].completeTime = InnerEvent::TimePoint::max();
648     currentRunningEvent_.triggerTime_ = InnerEvent::Clock::now();
649 
650     if (event->HasTask()) {
651         historyEvents_[historyEventIndex_].hasTask = true;
652         historyEvents_[historyEventIndex_].taskName = event->GetTaskName();
653     } else {
654         historyEvents_[historyEventIndex_].innerEventId = event->GetInnerEventIdEx();
655     }
656 }
657 
PushHistoryQueueAfterDistribute()658 void EventQueueBase::PushHistoryQueueAfterDistribute()
659 {
660     historyEvents_[historyEventIndex_].completeTime = InnerEvent::Clock::now();
661     historyEventIndex_++;
662     historyEventIndex_ = historyEventIndex_ & (HISTORY_EVENT_NUM_POWER - 1);
663 }
664 
HistoryQueueDump(const HistoryEvent & historyEvent)665 std::string EventQueueBase::HistoryQueueDump(const HistoryEvent &historyEvent)
666 {
667     std::string content;
668     std::vector<std::string> prioritys = {"VIP", "Immediate", "High", "Low", "IDEL"};
669 
670     content.append("Event { ");
671     content.append("send thread = " + std::to_string(historyEvent.senderKernelThreadId));
672     content.append(", send time = " + InnerEvent::DumpTimeToString(historyEvent.sendTime));
673     content.append(", handle time = " + InnerEvent::DumpTimeToString(historyEvent.handleTime));
674     content.append(", trigger time = " + InnerEvent::DumpTimeToString(historyEvent.triggerTime));
675 
676     if (historyEvent.completeTime == InnerEvent::TimePoint::max()) {
677         content.append(", completeTime time = ");
678     } else {
679         content.append(", completeTime time = " + InnerEvent::DumpTimeToString(historyEvent.completeTime));
680     }
681     if (historyEvent.priority >= 0 && historyEvent.priority < prioritys.size()) {
682         content.append(", priority = " + prioritys[historyEvent.priority]);
683     } else {
684         content.append(", priority = ");
685     }
686 
687     if (historyEvent.hasTask) {
688         content.append(", task name = " + historyEvent.taskName);
689     } else {
690         DumpCurrentRunningEventId(historyEvent.innerEventId, content);
691     }
692     content.append(" }" + std::string(LINE_SEPARATOR));
693 
694     return content;
695 }
696 
DumpCurrentQueueSize()697 std::string EventQueueBase::DumpCurrentQueueSize()
698 {
699     return "Current queue size: VIP = " +
700     std::to_string(subEventQueues_[static_cast<int>(Priority::VIP)].queue.size()) + ", IMMEDIATE = " +
701     std::to_string(subEventQueues_[static_cast<int>(Priority::IMMEDIATE)].queue.size()) + ", HIGH = " +
702     std::to_string(subEventQueues_[static_cast<int>(Priority::HIGH)].queue.size()) + ", LOW = " +
703     std::to_string(subEventQueues_[static_cast<int>(Priority::LOW)].queue.size()) + ", IDLE = " +
704     std::to_string(idleEvents_.size()) + " ; ";
705 }
706 
HasPreferEvent(int basePrio)707 bool EventQueueBase::HasPreferEvent(int basePrio)
708 {
709     for (int prio = 0; prio < basePrio; prio++) {
710         if (subEventQueues_[prio].queue.size() > 0) {
711             return true;
712         }
713     }
714     return false;
715 }
716 
QueryPendingTaskInfo(int32_t fileDescriptor)717 PendingTaskInfo EventQueueBase::QueryPendingTaskInfo(int32_t fileDescriptor)
718 {
719     PendingTaskInfo pendingTaskInfo;
720     std::shared_ptr<FileDescriptorInfo> fileDescriptorInfo = nullptr;
721     if (useDeamonIoWaiter_) {
722         fileDescriptorInfo = DeamonIoWaiter::GetInstance().GetFileDescriptorMap(fileDescriptor);
723     } else if (ioWaiter_) {
724         fileDescriptorInfo = ioWaiter_->GetFileDescriptorMap(fileDescriptor);
725     }
726     if (fileDescriptorInfo == nullptr) {
727         HILOGW("QueryPendingTaskInfo fileDescriptorInfo is unavailable.");
728         return pendingTaskInfo;
729     }
730 
731     std::lock_guard<std::mutex> lock(queueLock_);
732     if (!usable_.load()) {
733         HILOGW("QueryPendingTaskInfo event queue is unavailable.");
734         return pendingTaskInfo;
735     }
736 
737     auto now = InnerEvent::Clock::now();
738     for (auto it = subEventQueues_[0].queue.begin(); it != subEventQueues_[0].queue.end(); it++) {
739         if ((*it)->GetTaskName() == fileDescriptorInfo->taskName_) {
740             pendingTaskInfo.taskCount++;
741             InnerEvent::TimePoint handlerTime = (*it)->GetHandleTime();
742             if (handlerTime >= now) {
743                 continue;
744             }
745             auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now - handlerTime).count();
746             if (duration > pendingTaskInfo.MaxPendingTime) {
747                 pendingTaskInfo.MaxPendingTime = duration;
748             }
749         }
750     }
751     EH_LOGI_LIMIT("Pend task %{public}d %{public}d", pendingTaskInfo.taskCount, pendingTaskInfo.MaxPendingTime);
752     return PendingTaskInfo();
753 }
754 
CancelAndWait()755 void EventQueueBase::CancelAndWait()
756 {
757     HILOGD("EventQueueBase CancelAndWait enter.");
758 }
759 
CurrentRunningEvent()760 CurrentRunningEvent::CurrentRunningEvent()
761 {
762     beginTime_ = InnerEvent::TimePoint::max();
763 }
764 
CurrentRunningEvent(InnerEvent::TimePoint time,InnerEvent::Pointer & event)765 CurrentRunningEvent::CurrentRunningEvent(InnerEvent::TimePoint time, InnerEvent::Pointer &event)
766 {
767     beginTime_ = time;
768     owner_ = event->GetWeakOwner();
769     senderKernelThreadId_ = event->GetSenderKernelThreadId();
770     sendTime_ = event->GetSendTime();
771     handleTime_ = event->GetHandleTime();
772     param_ = event->GetParam();
773     callerInfo_ = (event->GetCaller()).ToString();
774     if (event->HasTask()) {
775         hasTask_ = true;
776         taskName_ = event->GetTaskName();
777     } else {
778         innerEventId_ = event->GetInnerEventIdEx();
779     }
780 }
781 
782 }  // namespace AppExecFwk
783 }  // namespace OHOS
784