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