1 /*
2 * Copyright (c) 2021 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 "frame_collector.h"
17
18 #include <chrono>
19 #include <mutex>
20 #include <map>
21 #include <string>
22
23 #include "hilog/log.h"
24 #include "hitrace_meter.h"
25 #include "parameter.h"
26
27 #include "frame_saver.h"
28
29 namespace OHOS {
30 namespace Rosen {
31 namespace {
32 constexpr ::OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, 0xD001400, "FrameCollector" };
33 constexpr int32_t uimarksStart = static_cast<int32_t>(FrameEventType::UIMarksStart);
34 constexpr int32_t uimarksEnd = static_cast<int32_t>(FrameEventType::UIMarksEnd) - 1;
35 constexpr int32_t loopEnd = static_cast<int32_t>(FrameEventType::LoopEnd) - 1;
36 constexpr int32_t vsyncStart = static_cast<int32_t>(FrameEventType::WaitVsyncStart);
37 constexpr int32_t vsyncEnd = static_cast<int32_t>(FrameEventType::WaitVsyncEnd);
38 } // namespace
39
GetInstance()40 FrameCollector &FrameCollector::GetInstance()
41 {
42 static FrameCollector instance;
43 return instance;
44 }
45
SetRepaintCallback(std::function<void ()> repaint)46 void FrameCollector::SetRepaintCallback(std::function<void()> repaint)
47 {
48 repaint_ = repaint;
49 }
50
LockGetFrameQueue()51 const FrameInfoQueue &FrameCollector::LockGetFrameQueue()
52 {
53 frameQueueMutex_.lock();
54 return frameQueue_;
55 }
56
UnlockFrameQueue()57 void FrameCollector::UnlockFrameQueue()
58 {
59 frameQueueMutex_.unlock();
60 }
61
IsEnabled() const62 bool FrameCollector::IsEnabled() const
63 {
64 return enabled_;
65 }
66
SetEnabled(bool enable)67 void FrameCollector::SetEnabled(bool enable)
68 {
69 enabled_ = enable;
70 }
71
MarkFrameEvent(const FrameEventType & type,int64_t timeNs)72 void FrameCollector::MarkFrameEvent(const FrameEventType &type, int64_t timeNs)
73 {
74 const auto &index = static_cast<int32_t>(type);
75 if (index >= static_cast<int32_t>(FrameEventType::Max)) {
76 ::OHOS::HiviewDFX::HiLog::Warn(LABEL,
77 "FrameCollector::MarkFrameEvent index(%{public}d) not exists", static_cast<int32_t>(index));
78 return;
79 }
80
81 if (timeNs == 0) {
82 timeNs = std::chrono::duration_cast<std::chrono::nanoseconds>(
83 std::chrono::steady_clock::now().time_since_epoch()).count();
84 }
85
86 if (usingSaver_) {
87 saver_->SaveFrameEvent(type, timeNs);
88 }
89
90 if (!enabled_) {
91 return;
92 }
93
94 ::OHOS::HiviewDFX::HiLog::Debug(LABEL, "FrameCollector::MarkFrameEvent "
95 "index(%{public}d) occur at %{public}s", index, std::to_string(timeNs).c_str());
96 ProcessFrameEvent(index, timeNs);
97 }
98
ProcessFrameEvent(int32_t index,int64_t timeNs)99 void FrameCollector::ProcessFrameEvent(int32_t index, int64_t timeNs)
100 {
101 std::lock_guard lockPending(pendingMutex_);
102 // lockFrameQueue: lock for {pbefore_, pafter_}
103 std::lock_guard lockFrameQueue(frameQueueMutex_);
104 if (ProcessUIMarkLocked(index, timeNs)) {
105 return;
106 }
107
108 if (index == vsyncStart) {
109 pbefore_ = &frameQueue_.Push(FrameInfo());
110 pbefore_->frameNumber = currentUIMarks_.frameNumber;
111 for (auto i = uimarksStart; i <= uimarksEnd; i++) {
112 pbefore_->times[i] = currentUIMarks_.times[i];
113 }
114 pbefore_->times[index] = timeNs;
115
116 if (haveAfterVsync_) {
117 pbefore_->skiped = true;
118 pbefore_->times[vsyncEnd] = pbefore_->times[vsyncStart];
119 } else {
120 StartAsyncTrace(HITRACE_TAG_GRAPHIC_AGP, GetAsyncNameByFrameEventType(index), pbefore_->frameNumber);
121 }
122 return;
123 }
124
125 if (!haveAfterVsync_) {
126 haveAfterVsync_ = true;
127 pafter_ = pbefore_;
128 }
129
130 if (pafter_ != nullptr) {
131 pafter_->times[index] = timeNs;
132
133 if (IsStartFrameEventType(index)) {
134 StartAsyncTrace(HITRACE_TAG_GRAPHIC_AGP, GetAsyncNameByFrameEventType(index), pafter_->frameNumber);
135 } else {
136 FinishAsyncTrace(HITRACE_TAG_GRAPHIC_AGP, GetAsyncNameByFrameEventType(index), pafter_->frameNumber);
137 }
138 }
139
140 if (index == loopEnd) {
141 haveAfterVsync_ = false;
142 }
143 }
144
ProcessUIMarkLocked(int32_t index,int64_t timeNs)145 bool FrameCollector::ProcessUIMarkLocked(int32_t index, int64_t timeNs)
146 {
147 if (index > uimarksEnd) {
148 return false;
149 }
150
151 if (IsStartFrameEventType(index)) {
152 StartAsyncTrace(HITRACE_TAG_GRAPHIC_AGP, GetAsyncNameByFrameEventType(index), currentFrameNumber_);
153 } else {
154 FinishAsyncTrace(HITRACE_TAG_GRAPHIC_AGP, GetAsyncNameByFrameEventType(index), currentFrameNumber_);
155 }
156
157 if (index < uimarksEnd) {
158 pendingUIMarks_.times[index] = timeNs;
159 return true;
160 }
161
162 // index == uimarksEnd
163 pendingUIMarks_.times[index] = timeNs;
164 currentUIMarks_ = pendingUIMarks_;
165 pendingUIMarks_.frameNumber = ++currentFrameNumber_;
166 return true;
167 }
168
ClearEvents()169 void FrameCollector::ClearEvents()
170 {
171 std::lock_guard lock(frameQueueMutex_);
172 frameQueue_.Clear();
173 }
174
FrameCollector()175 FrameCollector::FrameCollector()
176 {
177 char value[0x20];
178 GetParameter(switchRenderingText, "disable", value, sizeof(value));
179 SwitchFunction(switchRenderingText, value, this);
180 WatchParameter(switchRenderingText, SwitchFunction, this);
181 }
182
SwitchFunction(const char * key,const char * value,void * context)183 void FrameCollector::SwitchFunction(const char *key, const char *value, void *context)
184 {
185 auto &that = *reinterpret_cast<FrameCollector *>(context);
186 auto oldEnable = that.enabled_;
187 std::string str = value;
188 if (str == switchRenderingPaintText) {
189 that.ClearEvents();
190 that.usingSaver_ = false;
191 that.enabled_ = true;
192 }
193
194 if (str == switchRenderingSaverText) {
195 that.ClearEvents();
196 that.usingSaver_ = true;
197 that.enabled_ = false;
198 that.saver_ = std::make_unique<FrameSaver>();
199 }
200
201 if (str == switchRenderingDisableText) {
202 that.usingSaver_ = false;
203 that.enabled_ = false;
204 }
205
206 if (that.enabled_ != oldEnable && that.repaint_ != nullptr) {
207 that.repaint_();
208 }
209 }
210 } // namespace Rosen
211 } // namespace OHOS
212