1
2 /*
3 * Copyright (c) 2024 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 #include <charconv>
17 #include <limits>
18
19 #include "ffrt_inner.h"
20 #include "ressched_event_listener.h"
21 #include "res_sched_client.h"
22 #include "res_type.h"
23 #include "rs_trace.h"
24
25 namespace OHOS {
26 namespace Rosen {
27
28 constexpr uint32_t DEFAULT_PID = 0;
29 constexpr uint32_t DEFAULT_TYPE = 0;
30 constexpr double EPSILON = 0.1;
31
32
33 std::once_flag ResschedEventListener::createFlag_;
34 sptr<ResschedEventListener> ResschedEventListener::instance_ = nullptr;
35 std::shared_ptr<ffrt::queue> ResschedEventListener::ffrtQueue_ = nullptr;
36 std::shared_ptr<ffrt::queue> ResschedEventListener::ffrtHighPriorityQueue_ = nullptr;
37 std::mutex ResschedEventListener::ffrtGetQueueMutex_;
38 std::mutex ResschedEventListener::ffrtGetHighFrequenceQueueMutex_;
39 constexpr uint64_t SAMPLE_TIME = 100000000;
40 const std::string RS_RESSCHED_LISTENER_QUEUE = "res_ressched_event_listener_queue";
41 const std::string RS_RESSCHED_LISTENER_QUEUE_HIGH_PRIOTITY = "res_ressched_event_listener_high_priotity_queue";
42
GetInstance()43 sptr<ResschedEventListener> ResschedEventListener::GetInstance() noexcept
44 {
45 std::call_once(createFlag_, []() {
46 instance_ = new ResschedEventListener();
47 });
48 return instance_;
49 }
50
OnReceiveEvent(uint32_t eventType,uint32_t eventValue,std::unordered_map<std::string,std::string> extInfo)51 void ResschedEventListener::OnReceiveEvent(uint32_t eventType, uint32_t eventValue,
52 std::unordered_map<std::string, std::string> extInfo)
53 {
54 if (eventType == ResourceSchedule::ResType::EventType::EVENT_DRAW_FRAME_REPORT) {
55 HandleDrawFrameEventReport(eventValue);
56 } else if (eventType == ResourceSchedule::ResType::EventType::EVENT_FRAME_RATE_STATISTICS) {
57 HandleFrameRateStatisticsReport(eventValue, extInfo);
58 }
59 }
60
HandleDrawFrameEventReport(uint32_t eventValue)61 void ResschedEventListener::HandleDrawFrameEventReport(uint32_t eventValue)
62 {
63 if (eventValue == ResourceSchedule::ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_START) {
64 isNeedReport_ = true;
65 isFirstReport_ = true;
66 } else if (eventValue == ResourceSchedule::ResType::EventValue::EVENT_VALUE_DRAW_FRAME_REPORT_STOP) {
67 isNeedReport_ = false;
68 isFirstReport_ = false;
69 }
70 }
71
72
ReportFrameToRSS()73 void ResschedEventListener::ReportFrameToRSS()
74 {
75 if (GetIsNeedReport()) {
76 uint64_t currTime = static_cast<uint64_t>(
77 std::chrono::duration_cast<std::chrono::nanoseconds>(
78 std::chrono::steady_clock::now().time_since_epoch()).count());
79 if (GetIsFirstReport() ||
80 lastReportTime_ == 0 || (currTime > lastReportTime_ &&
81 currTime - lastReportTime_ >= SAMPLE_TIME)) {
82 RS_TRACE_NAME("ReportFrameToRSS");
83 uint32_t type = OHOS::ResourceSchedule::ResType::RES_TYPE_SEND_FRAME_EVENT;
84 int64_t value = 0;
85 std::unordered_map<std::string, std::string> mapPayload;
86 OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(type, value, mapPayload);
87 SetIsFirstReport(false);
88 lastReportTime_ = static_cast<uint64_t>(
89 std::chrono::duration_cast<std::chrono::nanoseconds>(
90 std::chrono::steady_clock::now().time_since_epoch()).count());
91 }
92 }
93 }
94
GetIsNeedReport() const95 bool ResschedEventListener::GetIsNeedReport() const
96 {
97 return isNeedReport_.load();
98 }
99
GetIsFirstReport() const100 bool ResschedEventListener::GetIsFirstReport() const
101 {
102 return isFirstReport_.load();
103 }
104
SetIsFirstReport(bool value)105 void ResschedEventListener::SetIsFirstReport(bool value)
106 {
107 isFirstReport_ = value;
108 }
109
HandleFrameRateStatisticsReport(uint32_t eventValue,std::unordered_map<std::string,std::string> extInfo)110 void ResschedEventListener::HandleFrameRateStatisticsReport(uint32_t eventValue,
111 std::unordered_map<std::string, std::string> extInfo)
112 {
113 uint32_t pid;
114 uint32_t type;
115 auto resultPid =
116 std::from_chars(extInfo.at("pid").data(), extInfo.at("pid").data() + extInfo.at("pid").size(), pid);
117 auto resultType =
118 std::from_chars(extInfo.at("type").data(), extInfo.at("type").data() + extInfo.at("type").size(), type);
119 if (resultPid.ec != std::errc() || resultType.ec != std::errc()) {
120 return;
121 }
122
123 switch (eventValue) {
124 case ResourceSchedule::ResType::EventValue::EVENT_VALUE_FRAME_RATE_STATISTICS_START:
125 HandleFrameRateStatisticsBeginAsync(pid, type);
126 break;
127 case ResourceSchedule::ResType::EventValue::EVENT_VALUE_FRAME_RATE_STATISTICS_BREAK:
128 HandleFrameRateStatisticsBreakAsync(pid, type);
129 break;
130 case ResourceSchedule::ResType::EventValue::EVENT_VALUE_FRAME_RATE_STATISTICS_END:
131 HandleFrameRateStatisticsEndAsync(pid, type);
132 break;
133 }
134 }
135
ReportFrameRateToRSS(const std::unordered_map<std::string,std::string> & mapPayload)136 void ResschedEventListener::ReportFrameRateToRSS(const std::unordered_map<std::string, std::string>& mapPayload)
137 {
138 if (GetFfrtHighPriorityQueue()) {
139 ffrtHighPriorityQueue_->submit([mapPayload]() {
140 RS_TRACE_BEGIN("FrameRateStatistics ReportFrameRateToRSS");
141 uint32_t type = ResourceSchedule::ResType::RES_TYPE_FRAME_RATE_REPORT_FROM_RS;
142 int64_t value = ResourceSchedule::ResType::FrameRateReportState::FRAME_RATE_COMMON_REPORT;
143 OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(type, value, mapPayload);
144 RS_TRACE_END();
145 });
146 }
147 }
148
ReportFrameCountAsync(uint32_t pid)149 void ResschedEventListener::ReportFrameCountAsync(uint32_t pid)
150 {
151 if (GetFfrtQueue()) {
152 ffrtQueue_->submit([pid, this]() {
153 if (currentType_ == DEFAULT_TYPE) {
154 return;
155 }
156 if (pid != currentPid_.load()) {
157 return;
158 }
159 if (isFrameRateFirstReport_) {
160 isFrameRateFirstReport_ = false;
161 beginTimeStamp_ = std::chrono::steady_clock::now();
162 }
163 endTimeStamp_ = std::chrono::steady_clock::now();
164 frameCountNum_++;
165 });
166 }
167 }
168
HandleFrameRateStatisticsBeginAsync(uint32_t pid,uint32_t type)169 void ResschedEventListener::HandleFrameRateStatisticsBeginAsync(uint32_t pid, uint32_t type)
170 {
171 if (GetFfrtQueue()) {
172 ffrtQueue_->submit([pid, type, this]() {
173 RS_TRACE_BEGIN("HandleFrameRateStatisticsBeginAsync");
174 currentPid_.store(pid);
175 currentType_ = type;
176 frameCountNum_ = 0;
177 isFrameRateFirstReport_ = true;
178 RS_TRACE_END();
179 });
180 }
181 }
182
HandleFrameRateStatisticsBreakAsync(uint32_t pid,uint32_t type)183 void ResschedEventListener::HandleFrameRateStatisticsBreakAsync(uint32_t pid, uint32_t type)
184 {
185 if (pid == currentPid_.load() && GetFfrtQueue()) {
186 ffrtQueue_->submit([this]() {
187 RS_TRACE_BEGIN("HandleFrameRateStatisticsBreakAsync");
188 currentPid_.store(DEFAULT_PID);
189 currentType_ = DEFAULT_TYPE;
190 RS_TRACE_END();
191 });
192 }
193 }
194
HandleFrameRateStatisticsEndAsync(uint32_t pid,uint32_t type)195 void ResschedEventListener::HandleFrameRateStatisticsEndAsync(uint32_t pid, uint32_t type)
196 {
197 if (pid == currentPid_.load() && GetFfrtQueue()) {
198 ffrtQueue_->submit([this]() {
199 RS_TRACE_BEGIN("HandleFrameRateStatisticsEndAsync");
200 std::chrono::duration<double> durationTime = endTimeStamp_ - beginTimeStamp_;
201 if (std::fabs(durationTime.count()) > EPSILON) {
202 int32_t frameRate = static_cast<int32_t>(std::round(frameCountNum_/durationTime.count()));
203 std::unordered_map<std::string, std::string> mapPayload;
204 mapPayload["pid"] = std::to_string(currentPid_.load());
205 mapPayload["type"] = std::to_string(currentType_);
206 mapPayload["frameRate"] = std::to_string(frameRate);
207 ReportFrameRateToRSS(mapPayload);
208 }
209 currentPid_.store(DEFAULT_PID);
210 currentType_ = DEFAULT_TYPE;
211 RS_TRACE_END();
212 });
213 }
214 }
215
GetCurrentPid()216 uint32_t ResschedEventListener::GetCurrentPid()
217 {
218 return currentPid_.load();
219 }
220
GetFfrtQueue()221 bool ResschedEventListener::GetFfrtQueue()
222 {
223 if (ffrtQueue_ != nullptr) {
224 return true;
225 }
226 std::lock_guard<std::mutex> lock(ffrtGetQueueMutex_);
227 if (ffrtQueue_ == nullptr) {
228 ffrtQueue_ = std::make_shared<ffrt::queue>(RS_RESSCHED_LISTENER_QUEUE.c_str(),
229 ffrt::queue_attr().qos(ffrt::qos_default));
230 }
231 if (ffrtQueue_ == nullptr) {
232 RS_TRACE_NAME("FrameRateStatistics Init ffrtqueue failed!");
233 return false;
234 }
235 return true;
236 }
237
GetFfrtHighPriorityQueue()238 bool ResschedEventListener::GetFfrtHighPriorityQueue()
239 {
240 if (ffrtHighPriorityQueue_ != nullptr) {
241 return true;
242 }
243 std::lock_guard<std::mutex> lock(ffrtGetHighFrequenceQueueMutex_);
244 if (ffrtHighPriorityQueue_ == nullptr) {
245 ffrtHighPriorityQueue_ = std::make_shared<ffrt::queue>(
246 RS_RESSCHED_LISTENER_QUEUE_HIGH_PRIOTITY.c_str(), ffrt::queue_attr().qos(ffrt::qos_user_interactive));
247 }
248 if (ffrtHighPriorityQueue_ == nullptr) {
249 RS_TRACE_NAME("FrameRateStatistics Init HighPriority ffrtqueue failed!");
250 return false;
251 }
252 return true;
253 }
254 } // namespace Rosen
255 } // namespace OHOS
256