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