• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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