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 "inner_event.h"
17
18 #include <chrono>
19 #include <condition_variable>
20 #include <mutex>
21 #include <vector>
22
23 #include "event_handler_utils.h"
24 #include "event_logger.h"
25 #include "singleton.h"
26
27 namespace OHOS {
28 namespace AppExecFwk {
29 namespace {
30 static constexpr int DATETIME_STRING_LENGTH = 80;
31 static constexpr int MAX_MS_LENGTH = 3;
32 static constexpr int MS_PER_SECOND = 1000;
33 DEFINE_EH_HILOG_LABEL("InnerEvent");
34
35 class WaiterImp final : public InnerEvent::Waiter {
36 public:
WaiterImp()37 WaiterImp(){};
~WaiterImp()38 ~WaiterImp() override{};
39 DISALLOW_COPY_AND_MOVE(WaiterImp);
40
Wait()41 void Wait() final
42 {
43 std::unique_lock<std::mutex> lock(mutex_);
44 while (!finished_) {
45 ++waitingCount_;
46 condition_.wait(lock);
47 --waitingCount_;
48 }
49 }
50
Notify()51 void Notify() final
52 {
53 std::lock_guard<std::mutex> lock(mutex_);
54 finished_ = true;
55 if (waitingCount_ > 0) {
56 condition_.notify_all();
57 }
58 }
59
60 private:
61 std::mutex mutex_;
62 std::condition_variable condition_;
63 uint32_t waitingCount_ {0};
64 bool finished_ {false};
65 };
66 } // unnamed namespace
67
68 // Implementation for event pool.
69 class InnerEventPool : public DelayedRefSingleton<InnerEventPool> {
70 DECLARE_DELAYED_REF_SINGLETON(InnerEventPool);
71
72 public:
73 DISALLOW_COPY_AND_MOVE(InnerEventPool);
74
Get()75 InnerEvent::Pointer Get()
76 {
77 // Allocate new memory, while pool is empty.
78 return InnerEvent::Pointer(new (std::nothrow) InnerEvent, Drop);
79 }
80
81 private:
Drop(InnerEvent * event)82 static void Drop(InnerEvent *event)
83 {
84 if (event == nullptr) {
85 return;
86 }
87
88 // Clear content of the event
89 event->ClearEvent();
90 if (event != nullptr) {
91 delete event;
92 }
93 }
94 };
95
InnerEventPool()96 InnerEventPool::InnerEventPool()
97 {
98 HILOGD("InnerEventPool enter");
99 }
100
~InnerEventPool()101 InnerEventPool::~InnerEventPool()
102 {
103 HILOGD("~InnerEventPool enter");
104 }
105
Get()106 InnerEvent::Pointer InnerEvent::Get()
107 {
108 auto event = InnerEventPool::GetInstance().Get();
109 return event;
110 }
111
Get(uint32_t innerEventId,int64_t param,const Caller & caller)112 InnerEvent::Pointer InnerEvent::Get(uint32_t innerEventId, int64_t param, const Caller &caller)
113 {
114 auto event = InnerEventPool::GetInstance().Get();
115 if (event != nullptr) {
116 event->innerEventId_ = innerEventId;
117 event->param_ = param;
118 event->caller_ = caller;
119 HILOGD("innerEventId is %{public}u, caller is %{public}s", innerEventId, caller.ToString().c_str());
120 }
121 return event;
122 }
123
Get(const EventId & innerEventId,int64_t param,const Caller & caller)124 InnerEvent::Pointer InnerEvent::Get(const EventId &innerEventId, int64_t param, const Caller &caller)
125 {
126 auto event = InnerEventPool::GetInstance().Get();
127 if (event != nullptr) {
128 event->innerEventId_ = innerEventId;
129 event->param_ = param;
130 event->caller_ = caller;
131 if (innerEventId.index() == TYPE_U32_INDEX) {
132 HILOGD("innerEventId is %{public}u, caller is %{public}s",
133 std::get<uint32_t>(innerEventId),
134 caller.ToString().c_str());
135 } else {
136 HILOGD("innerEventId is %{public}s, caller is %{public}s",
137 std::get<std::string>(innerEventId).c_str(),
138 caller.ToString().c_str());
139 }
140 }
141 return event;
142 }
143
Get(const Callback & callback,const std::string & name,const Caller & caller)144 InnerEvent::Pointer InnerEvent::Get(const Callback &callback, const std::string &name, const Caller &caller)
145 {
146 // Returns nullptr while callback is invalid.
147 if (!callback) {
148 HILOGW("Failed to create inner event with an invalid callback");
149 return InnerEvent::Pointer(nullptr, nullptr);
150 }
151
152 auto event = InnerEventPool::GetInstance().Get();
153 if (event != nullptr) {
154 event->taskCallback_ = callback;
155 event->taskName_ = name;
156 event->caller_ = caller;
157 HILOGD("event taskName is '%{public}s', caller is %{public}s", name.c_str(), caller.ToString().c_str());
158 }
159 return event;
160 }
161
ClearEvent()162 void InnerEvent::ClearEvent()
163 {
164 // Wake up all waiting threads.
165 if (waiter_) {
166 waiter_->Notify();
167 waiter_.reset();
168 }
169
170 if (HasTask()) {
171 // Clear members for task
172 taskName_.clear();
173 caller_.ClearCaller();
174 } else {
175 // Clear members for event
176 if (smartPtrDtor_) {
177 smartPtrDtor_(smartPtr_);
178 smartPtrDtor_ = nullptr;
179 smartPtr_ = nullptr;
180 smartPtrTypeId_ = 0;
181 }
182 }
183
184 if (hiTraceId_) {
185 hiTraceId_.reset();
186 }
187
188 // Clear owner
189 owner_.reset();
190 }
191
WarnSmartPtrCastMismatch()192 void InnerEvent::WarnSmartPtrCastMismatch()
193 {
194 HILOGD("Type of the shared_ptr, weak_ptr or unique_ptr mismatched");
195 }
196
CreateWaiter()197 const std::shared_ptr<InnerEvent::Waiter> &InnerEvent::CreateWaiter()
198 {
199 waiter_ = std::make_shared<WaiterImp>();
200 return waiter_;
201 }
202
HasWaiter() const203 bool InnerEvent::HasWaiter() const
204 {
205 return (waiter_ != nullptr);
206 }
207
GetOrCreateTraceId()208 const std::shared_ptr<HiTraceId> InnerEvent::GetOrCreateTraceId()
209 {
210 if (hiTraceId_) {
211 return hiTraceId_;
212 }
213
214 auto traceId = HiTraceChain::GetId();
215 if (!traceId.IsValid()) {
216 return nullptr;
217 }
218
219 hiTraceId_ = std::make_shared<HiTraceId>(HiTraceChain::CreateSpan());
220 return hiTraceId_;
221 }
222
GetTraceId()223 const std::shared_ptr<HiTraceId> InnerEvent::GetTraceId()
224 {
225 return hiTraceId_;
226 }
227
DumpTimeToString(const std::chrono::system_clock::time_point & time)228 std::string InnerEvent::DumpTimeToString(const std::chrono::system_clock::time_point &time)
229 {
230 auto tp = std::chrono::time_point_cast<std::chrono::milliseconds>(time);
231 auto tt = std::chrono::system_clock::to_time_t(time);
232 auto ms = tp.time_since_epoch().count() % MS_PER_SECOND;
233 auto msString = std::to_string(ms);
234 if (msString.length() < MAX_MS_LENGTH) {
235 msString = std::string(MAX_MS_LENGTH - msString.length(), '0') + msString;
236 }
237 struct tm curTime = {0};
238 localtime_r(&tt, &curTime);
239 char sysTime[DATETIME_STRING_LENGTH];
240 std::strftime(sysTime, sizeof(char) * DATETIME_STRING_LENGTH, "%Y-%m-%d %I:%M:%S.", &curTime);
241 return std::string(sysTime) + msString;
242 }
243
DumpTimeToString(const TimePoint & time)244 std::string InnerEvent::DumpTimeToString(const TimePoint &time)
245 {
246 auto tp = std::chrono::system_clock::now() +
247 std::chrono::duration_cast<std::chrono::milliseconds>(time - std::chrono::steady_clock::now());
248 return DumpTimeToString(tp);
249 }
250
Dump()251 std::string InnerEvent::Dump()
252 {
253 std::string content;
254
255 content.append("Event { ");
256 if (!owner_.expired()) {
257 content.append("send thread = " + std::to_string(senderKernelThreadId_));
258 content.append(", send time = " + DumpTimeToString(sendTime_));
259 content.append(", handle time = " + DumpTimeToString(handleTime_));
260 if (HasTask()) {
261 content.append(", task name = " + taskName_);
262 } else {
263 if (innerEventId_.index() == TYPE_U32_INDEX) {
264 content.append(", id = " + std::to_string(std::get<uint32_t>(innerEventId_)));
265 } else {
266 content.append(", id = " + std::get<std::string>(innerEventId_));
267 }
268 }
269 if (param_ != 0) {
270 content.append(", param = " + std::to_string(param_));
271 }
272 content.append(", caller = " + caller_.ToString());
273 } else {
274 content.append("No handler");
275 }
276 content.append(" }" + std::string(LINE_SEPARATOR));
277
278 return content;
279 }
280
TraceInfo()281 std::string InnerEvent::TraceInfo()
282 {
283 std::string content;
284
285 content.append("Et:");
286 if (!owner_.expired()) {
287 content.append(std::to_string(senderKernelThreadId_));
288 content.append("," + std::to_string(sendTime_.time_since_epoch().count()));
289 content.append("," + std::to_string(handleTime_.time_since_epoch().count()));
290 if (HasTask()) {
291 content.append("," + taskName_);
292 } else {
293 if (innerEventId_.index() == TYPE_U32_INDEX) {
294 content.append("," + std::to_string(std::get<uint32_t>(innerEventId_)));
295 } else {
296 content.append("," + std::get<std::string>(innerEventId_));
297 }
298 }
299 content.append("," + std::to_string(priority));
300 content.append("," + caller_.ToString());
301 } else {
302 content.append("NA");
303 }
304
305 return content;
306 }
307
SetEventUniqueId()308 void InnerEvent::SetEventUniqueId()
309 {
310 auto nowTime = std::chrono::duration_cast<std::chrono::nanoseconds>(
311 std::chrono::steady_clock::now().time_since_epoch()).count();
312 eventId = std::to_string(nowTime);
313 }
314
315 } // namespace AppExecFwk
316 } // namespace OHOS
317