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