• 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 <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