1 /*
2 * Copyright (c) 2023-2024 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 "hgm_frame_rate_manager.h"
17
18 #include <algorithm>
19 #include <chrono>
20 #include <ctime>
21 #include "common/rs_common_hook.h"
22 #include "common/rs_optional_trace.h"
23 #include "common/rs_thread_handler.h"
24 #include "pipeline/rs_uni_render_judgement.h"
25 #include "hgm_config_callback_manager.h"
26 #include "hgm_core.h"
27 #include "hgm_energy_consumption_policy.h"
28 #include "hgm_hfbc_config.h"
29 #include "hgm_log.h"
30 #include "hgm_screen_info.h"
31 #include "parameters.h"
32 #include "rs_trace.h"
33 #include "sandbox_utils.h"
34 #include "frame_rate_report.h"
35 #include "hisysevent.h"
36 #include "hdi_device.h"
37 #include "pipeline/rs_surface_render_node.h"
38 #include "platform/common/rs_hisysevent.h"
39
40 namespace OHOS {
41 namespace Rosen {
42 namespace {
43 constexpr int32_t IDLE_TIMER_EXPIRED = 200; // ms
44 constexpr int32_t CHANGE_GENERATOR_RATE_VALID_TIMEOUT = 20; //ms
45 constexpr int64_t UNI_RENDER_VSYNC_OFFSET = 5000000; // ns
46 constexpr int64_t UNI_RENDER_VSYNC_OFFSET_DELAY_MODE = -3300000; // ns
47 constexpr uint32_t REPORT_VOTER_INFO_LIMIT = 20;
48 constexpr int32_t LAST_TOUCH_CNT = 1;
49
50 constexpr uint32_t FIRST_FRAME_TIME_OUT = 100; // 100ms
51 constexpr uint32_t DEFAULT_PRIORITY = 0;
52 constexpr uint32_t VOTER_SCENE_PRIORITY_BEFORE_PACKAGES = 1;
53 constexpr uint32_t VOTER_LTPO_PRIORITY_BEFORE_PACKAGES = 2;
54 constexpr uint64_t BUFFER_IDLE_TIME_OUT = 200000000; // 200ms
55 const static std::string UP_TIME_OUT_TASK_ID = "UP_TIME_OUT_TASK_ID";
56 const static std::string LOW_BRIGHT = "LowBright";
57 const static std::string STYLUS_PEN = "StylusPen";
58 // CAUTION: with priority
59 const std::string VOTER_NAME[] = {
60 "VOTER_THERMAL",
61 "VOTER_VIRTUALDISPLAY_FOR_CAR",
62 "VOTER_VIRTUALDISPLAY",
63 "VOTER_MUTIPHYSICALSCREEN",
64 "VOTER_MULTISELFOWNEDSCREEN",
65 "VOTER_POWER_MODE",
66 "VOTER_DISPLAY_ENGINE",
67 "VOTER_GAMES",
68 "VOTER_ANCO",
69
70 "VOTER_PAGE_URL",
71 "VOTER_PACKAGES",
72 "VOTER_LTPO",
73 "VOTER_TOUCH",
74 "VOTER_POINTER",
75 "VOTER_SCENE",
76 "VOTER_VIDEO",
77 "VOTER_IDLE"
78 };
79
80 constexpr int ADAPTIVE_SYNC_PROPERTY = 3;
81 constexpr int DISPLAY_SUCCESS = 1;
82
83 constexpr int32_t STYLUS_NO_LINK = 0;
84 constexpr int32_t STYLUS_LINK_UNUSED = 1;
85 constexpr int32_t STYLUS_LINK_WRITE = 2;
86 const std::unordered_map<std::string, int32_t> STYLUS_STATUS_MAP = {
87 {"STYLUS_NO_LINK", STYLUS_NO_LINK},
88 {"STYLUS_LINK_UNUSED", STYLUS_LINK_UNUSED},
89 {"STYLUS_LINK_WRITE", STYLUS_LINK_WRITE}};
90 constexpr uint32_t FRAME_RATE_REPORT_MAX_RETRY_TIMES = 3;
91 constexpr uint32_t FRAME_RATE_REPORT_DELAY_TIME = 20000;
92 }
93
HgmFrameRateManager()94 HgmFrameRateManager::HgmFrameRateManager()
95 : changeGeneratorRateValidTimer_("ChangeGeneratorRateValid",
96 std::chrono::milliseconds(CHANGE_GENERATOR_RATE_VALID_TIMEOUT), nullptr, [this] () {
97 changeGeneratorRateValid_ = true;
98 UpdateSoftVSync(false);
99 }),
__anon8fb7919d0302() 100 rsFrameRateTimer_("rsFrameRate", std::chrono::milliseconds(IDLE_TIMER_EXPIRED), nullptr, [this] () {
101 if (rsFrameRateLinker_ != nullptr) {
102 rsFrameRateLinker_->SetExpectedRange({});
103 UpdateSoftVSync(false);
104 }
105 }),
106 voters_(std::begin(VOTER_NAME), std::end(VOTER_NAME))
107 {
108 for (auto &voter : VOTER_NAME) {
109 voteRecord_[voter] = {{}, true};
110 }
111 }
112
Init(sptr<VSyncController> rsController,sptr<VSyncController> appController,sptr<VSyncGenerator> vsyncGenerator)113 void HgmFrameRateManager::Init(sptr<VSyncController> rsController,
114 sptr<VSyncController> appController, sptr<VSyncGenerator> vsyncGenerator)
115 {
116 auto& hgmCore = HgmCore::Instance();
117 curRefreshRateMode_ = hgmCore.GetCurrentRefreshRateMode();
118 multiAppStrategy_.UpdateXmlConfigCache();
119 UpdateEnergyConsumptionConfig();
120
121 // hgm warning: get non active screenId in non-folding devices(from sceneboard)
122 auto screenList = hgmCore.GetScreenIds();
123 curScreenId_.store(screenList.empty() ? 0 : screenList.front());
124 auto& hgmScreenInfo = HgmScreenInfo::GetInstance();
125 isLtpo_ = hgmScreenInfo.IsLtpoType(hgmScreenInfo.GetScreenType(curScreenId_.load()));
126 std::string curScreenName = "screen" + std::to_string(curScreenId_.load()) + "_" + (isLtpo_ ? "LTPO" : "LTPS");
127 auto configData = hgmCore.GetPolicyConfigData();
128 if (configData != nullptr) {
129 if (configData->screenStrategyConfigs_.find(curScreenName) != configData->screenStrategyConfigs_.end()) {
130 curScreenStrategyId_ = configData->screenStrategyConfigs_[curScreenName];
131 }
132 if (curScreenStrategyId_.empty()) {
133 curScreenStrategyId_ = "LTPO-DEFAULT";
134 }
135 if (curRefreshRateMode_ != HGM_REFRESHRATE_MODE_AUTO && configData->xmlCompatibleMode_) {
136 curRefreshRateMode_ = configData->SettingModeId2XmlModeId(curRefreshRateMode_);
137 }
138 multiAppStrategy_.UpdateXmlConfigCache();
139 GetLowBrightVec(configData);
140 GetStylusVec(configData);
141 UpdateEnergyConsumptionConfig();
142 multiAppStrategy_.CalcVote();
143 HandleIdleEvent(ADD_VOTE);
144 }
145
146 RegisterCoreCallbacksAndInitController(rsController, appController, vsyncGenerator);
147 multiAppStrategy_.RegisterStrategyChangeCallback([this] (const PolicyConfigData::StrategyConfig& strategy) {
148 DeliverRefreshRateVote({"VOTER_PACKAGES", strategy.min, strategy.max}, ADD_VOTE);
149 idleFps_ = strategy.idleFps;
150 HandleIdleEvent(true);
151 });
152 InitTouchManager();
153 hgmCore.SetLtpoConfig();
154 multiAppStrategy_.CalcVote();
155 appPageUrlStrategy_.RegisterPageUrlVoterCallback([this] (pid_t pid,
156 std::string strategy, const bool isAddVoter) {
157 ProcessPageUrlVote(pid, strategy, isAddVoter);
158 });
159 FrameRateReportTask(FRAME_RATE_REPORT_MAX_RETRY_TIMES);
160 }
161
RegisterCoreCallbacksAndInitController(sptr<VSyncController> rsController,sptr<VSyncController> appController,sptr<VSyncGenerator> vsyncGenerator)162 void HgmFrameRateManager::RegisterCoreCallbacksAndInitController(sptr<VSyncController> rsController,
163 sptr<VSyncController> appController, sptr<VSyncGenerator> vsyncGenerator)
164 {
165 if (rsController == nullptr || appController == nullptr) {
166 HGM_LOGE("HgmFrameRateManager::rsController or appController is nullptr");
167 return;
168 }
169 auto& hgmCore = HgmCore::Instance();
170 hgmCore.RegisterRefreshRateModeChangeCallback([rsController, appController](int32_t mode) {
171 if (HgmCore::Instance().IsLTPOSwitchOn()) {
172 rsController->SetPhaseOffset(0);
173 appController->SetPhaseOffset(0);
174 CreateVSyncGenerator()->SetVSyncMode(VSYNC_MODE_LTPO);
175 } else {
176 if (RSUniRenderJudgement::IsUniRender()) {
177 int64_t offset = HgmCore::Instance().IsDelayMode() ?
178 UNI_RENDER_VSYNC_OFFSET_DELAY_MODE : UNI_RENDER_VSYNC_OFFSET;
179 rsController->SetPhaseOffset(offset);
180 appController->SetPhaseOffset(offset);
181 }
182 CreateVSyncGenerator()->SetVSyncMode(VSYNC_MODE_LTPS);
183 }
184 });
185
186 hgmCore.RegisterRefreshRateUpdateCallback([](int32_t refreshRate) {
187 HgmTaskHandleThread::Instance().PostTask([refreshRate] () {
188 HgmConfigCallbackManager::GetInstance()->SyncRefreshRateUpdateCallback(refreshRate);
189 });
190 });
191
192 controller_ = std::make_shared<HgmVSyncGeneratorController>(rsController, appController, vsyncGenerator);
193 }
194
InitTouchManager()195 void HgmFrameRateManager::InitTouchManager()
196 {
197 static std::once_flag createFlag;
198 std::call_once(createFlag, [this]() {
199 auto updateTouchToMultiAppStrategy = [this](TouchState newState) {
200 HgmMultiAppStrategy::TouchInfo touchInfo = {
201 .pkgName = touchManager_.GetPkgName(),
202 .touchState = newState,
203 };
204 HgmEnergyConsumptionPolicy::Instance().SetTouchState(newState);
205 multiAppStrategy_.HandleTouchInfo(touchInfo);
206 UpdateSoftVSync(false);
207 };
208 touchManager_.RegisterEventCallback(TouchEvent::UP_TIMEOUT_EVENT, [this] (TouchEvent event) {
209 SetSchedulerPreferredFps(OLED_60_HZ);
210 SetIsNeedUpdateAppOffset(true);
211 touchManager_.ChangeState(TouchState::IDLE_STATE);
212 });
213 touchManager_.RegisterEventCallback(TouchEvent::DOWN_EVENT, [this] (TouchEvent event) {
214 SetSchedulerPreferredFps(OLED_120_HZ);
215 touchManager_.ChangeState(TouchState::DOWN_STATE);
216 });
217 touchManager_.RegisterEnterStateCallback(TouchState::DOWN_STATE,
218 [this, updateTouchToMultiAppStrategy] (TouchState lastState, TouchState newState) {
219 updateTouchToMultiAppStrategy(newState);
220 startCheck_.store(false);
221 voterTouchEffective_.store(true);
222 forceUpdateCallback_(false, true);
223 });
224 touchManager_.RegisterEnterStateCallback(TouchState::IDLE_STATE,
225 [this, updateTouchToMultiAppStrategy] (TouchState lastState, TouchState newState) {
226 startCheck_.store(false);
227 updateTouchToMultiAppStrategy(newState);
228 voterTouchEffective_.store(false);
229 });
230 touchManager_.RegisterEnterStateCallback(TouchState::UP_STATE,
231 [this, updateTouchToMultiAppStrategy] (TouchState lastState, TouchState newState) {
232 HgmTaskHandleThread::Instance().PostEvent(UP_TIME_OUT_TASK_ID, [this] () {
233 startCheck_.store(true);
234 UpdateSoftVSync(false);
235 }, FIRST_FRAME_TIME_OUT);
236 updateTouchToMultiAppStrategy(newState);
237 });
238 touchManager_.RegisterExitStateCallback(TouchState::UP_STATE,
239 [this] (TouchState lastState, TouchState newState) {
240 HgmTaskHandleThread::Instance().RemoveEvent(UP_TIME_OUT_TASK_ID);
241 startCheck_.store(false);
242 });
243 });
244 }
245
246
ProcessPendingRefreshRate(uint64_t timestamp,int64_t vsyncId,uint32_t rsRate,bool isUiDvsyncOn)247 void HgmFrameRateManager::ProcessPendingRefreshRate(
248 uint64_t timestamp, int64_t vsyncId, uint32_t rsRate, bool isUiDvsyncOn)
249 {
250 std::lock_guard<std::mutex> lock(pendingMutex_);
251 // ensure that vsync switching takes effect in this frame
252 if (vsyncId < vsyncCountOfChangeGeneratorRate_) {
253 return;
254 }
255 auto &hgmCore = HgmCore::Instance();
256 hgmCore.SetTimestamp(timestamp);
257 if (pendingRefreshRate_ != nullptr) {
258 hgmCore.SetPendingConstraintRelativeTime(pendingConstraintRelativeTime_);
259 lastPendingConstraintRelativeTime_ = pendingConstraintRelativeTime_;
260 pendingConstraintRelativeTime_ = 0;
261
262 hgmCore.SetPendingScreenRefreshRate(*pendingRefreshRate_);
263 lastPendingRefreshRate_ = *pendingRefreshRate_;
264 pendingRefreshRate_.reset();
265 RS_TRACE_NAME_FMT("ProcessHgmFrameRate pendingRefreshRate: %d", lastPendingRefreshRate_);
266 } else {
267 if (lastPendingConstraintRelativeTime_ != 0) {
268 hgmCore.SetPendingConstraintRelativeTime(lastPendingConstraintRelativeTime_);
269 }
270 if (lastPendingRefreshRate_ != 0) {
271 hgmCore.SetPendingScreenRefreshRate(lastPendingRefreshRate_);
272 RS_TRACE_NAME_FMT("ProcessHgmFrameRate pendingRefreshRate: %d", lastPendingRefreshRate_);
273 }
274 }
275
276 if (hgmCore.GetLtpoEnabled() && isLtpo_ && rsRate > OLED_10_HZ &&
277 isUiDvsyncOn && GetCurScreenStrategyId().find("LTPO") != std::string::npos) {
278 hgmCore.SetPendingScreenRefreshRate(rsRate);
279 RS_TRACE_NAME_FMT("ProcessHgmFrameRate pendingRefreshRate: %d ui-dvsync", rsRate);
280 }
281 SetChangeGeneratorRateValid(true);
282 }
283
UpdateSurfaceTime(const std::string & surfaceName,pid_t pid,UIFWKType uiFwkType)284 void HgmFrameRateManager::UpdateSurfaceTime(const std::string& surfaceName, pid_t pid, UIFWKType uiFwkType)
285 {
286 HgmEnergyConsumptionPolicy::Instance().StatisticsVideoCallBufferCount(pid, surfaceName);
287 if (!voterTouchEffective_) {
288 return;
289 }
290 surfaceData_.emplace_back(std::tuple<std::string, pid_t, UIFWKType>({surfaceName, pid, uiFwkType}));
291 }
292
UpdateAppSupportedState()293 void HgmFrameRateManager::UpdateAppSupportedState()
294 {
295 PolicyConfigData::StrategyConfig config;
296 if (multiAppStrategy_.GetFocusAppStrategyConfig(config) == EXEC_SUCCESS &&
297 config.dynamicMode == DynamicModeType::TOUCH_EXT_ENABLED) {
298 idleDetector_.SetAppSupportedState(true);
299 } else {
300 idleDetector_.SetAppSupportedState(false);
301 }
302 idleDetector_.SetBufferFpsMap(std::move(config.bufferFpsMap));
303 }
304
SetAceAnimatorVote(const std::shared_ptr<RSRenderFrameRateLinker> & linker)305 void HgmFrameRateManager::SetAceAnimatorVote(const std::shared_ptr<RSRenderFrameRateLinker>& linker)
306 {
307 if (linker == nullptr) {
308 return;
309 }
310 if (linker->GetAceAnimatorExpectedFrameRate() >= 0) {
311 RS_TRACE_NAME_FMT("SetAceAnimatorVote PID = [%d] linkerId = [%" PRIu64 "] SetAceAnimatorIdleState[false] "
312 "AnimatorExpectedFrameRate = [%d]", ExtractPid(linker->GetId()), linker->GetId(),
313 linker->GetAceAnimatorExpectedFrameRate());
314 idleDetector_.SetAceAnimatorIdleState(false);
315 idleDetector_.UpdateAceAnimatorExpectedFrameRate(linker->GetAceAnimatorExpectedFrameRate());
316 }
317 }
318
UpdateGuaranteedPlanVote(uint64_t timestamp)319 void HgmFrameRateManager::UpdateGuaranteedPlanVote(uint64_t timestamp)
320 {
321 if (!idleDetector_.GetAppSupportedState()) {
322 return;
323 }
324 idleDetector_.UpdateSurfaceState(timestamp);
325 RS_TRACE_NAME_FMT("HgmFrameRateManager:: TouchState = [%d] SurFaceIdleState = [%d] AceAnimatorIdleState = [%d]",
326 touchManager_.GetState(), idleDetector_.GetSurfaceIdleState(), idleDetector_.GetAceAnimatorIdleState());
327
328 // After touch up, wait FIRST_FRAME_TIME_OUT ms
329 if (!startCheck_.load() || touchManager_.GetState() == TouchState::IDLE_STATE) {
330 lastTouchUpExpectFps_ = 0;
331 return;
332 }
333
334 // remove the touch vote if third framework idle, otherwise vote the touch up fps
335 if (idleDetector_.GetSurfaceIdleState() && idleDetector_.GetAceAnimatorIdleState()) {
336 RS_TRACE_NAME_FMT("UpdateGuaranteedPlanVote:: Surface And Animator Idle, remove touch vote");
337 DeliverRefreshRateVote({"VOTER_TOUCH"}, REMOVE_VOTE);
338 lastTouchUpExpectFps_ = 0;
339 } else {
340 int32_t currTouchUpExpectedFPS = idleDetector_.GetTouchUpExpectedFPS();
341 if (currTouchUpExpectedFPS == lastTouchUpExpectFps_) {
342 return;
343 }
344
345 lastTouchUpExpectFps_ = currTouchUpExpectedFPS;
346 HgmMultiAppStrategy::TouchInfo touchInfo = {
347 .touchState = TouchState::UP_STATE,
348 .upExpectFps = currTouchUpExpectedFPS,
349 };
350 multiAppStrategy_.HandleTouchInfo(touchInfo);
351 }
352 }
353
ProcessLtpoVote(const FrameRateRange & finalRange)354 void HgmFrameRateManager::ProcessLtpoVote(const FrameRateRange& finalRange)
355 {
356 if (finalRange.IsValid()) {
357 auto refreshRate = CalcRefreshRate(curScreenId_.load(), finalRange);
358 DeliverRefreshRateVote(
359 {"VOTER_LTPO", refreshRate, refreshRate, DEFAULT_PID, finalRange.GetExtInfo()}, ADD_VOTE);
360 } else {
361 DeliverRefreshRateVote({.voterName = "VOTER_LTPO"}, REMOVE_VOTE);
362 }
363 }
364
UniProcessDataForLtpo(uint64_t timestamp,std::shared_ptr<RSRenderFrameRateLinker> rsFrameRateLinker,const FrameRateLinkerMap & appFrameRateLinkers,const std::map<uint64_t,int> & vRatesMap)365 void HgmFrameRateManager::UniProcessDataForLtpo(uint64_t timestamp,
366 std::shared_ptr<RSRenderFrameRateLinker> rsFrameRateLinker, const FrameRateLinkerMap& appFrameRateLinkers,
367 const std::map<uint64_t, int>& vRatesMap)
368 {
369 RS_TRACE_FUNC();
370 timestamp_ = timestamp;
371 rsFrameRateLinker_ = rsFrameRateLinker;
372 appFrameRateLinkers_ = appFrameRateLinkers;
373
374 vRatesMap_ = vRatesMap;
375 UpdateSoftVSync(true);
376 }
377
UpdateSoftVSync(bool followRs)378 void HgmFrameRateManager::UpdateSoftVSync(bool followRs)
379 {
380 if (rsFrameRateLinker_ == nullptr) {
381 return;
382 }
383 Reset();
384 FrameRateRange finalRange = rsFrameRateLinker_->GetExpectedRange();
385 HgmEnergyConsumptionPolicy::Instance().GetAnimationIdleFps(finalRange);
386 rsFrameRateLinker_->SetExpectedRange(finalRange);
387 idleDetector_.SetAceAnimatorIdleState(true);
388 for (auto linker : appFrameRateLinkers_) {
389 if (linker.second == nullptr || !multiAppStrategy_.CheckPidValid(ExtractPid(linker.first))) {
390 continue;
391 }
392 SetAceAnimatorVote(linker.second);
393 auto expectedRange = linker.second->GetExpectedRange();
394 if (!HgmEnergyConsumptionPolicy::Instance().GetUiIdleFps(expectedRange) &&
395 (expectedRange.type_ & ANIMATION_STATE_FIRST_FRAME) != 0 &&
396 expectedRange.preferred_ < static_cast<int32_t>(currRefreshRate_)) {
397 expectedRange.Set(currRefreshRate_, currRefreshRate_, currRefreshRate_);
398 }
399 finalRange.Merge(expectedRange);
400 }
401 HgmEnergyConsumptionPolicy::Instance().PrintEnergyConsumptionLog(finalRange);
402 ProcessLtpoVote(finalRange);
403
404 UpdateGuaranteedPlanVote(timestamp_);
405 idleDetector_.ResetAceAnimatorExpectedFrameRate();
406 // changeGenerator only once in a single vsync period
407 if (!changeGeneratorRateValid_.load()) {
408 return;
409 }
410 // max used here
411 finalRange = {lastVoteInfo_.max, lastVoteInfo_.max, lastVoteInfo_.max};
412 RS_TRACE_NAME_FMT("VoteRes: %s[%d, %d]", lastVoteInfo_.voterName.c_str(), lastVoteInfo_.min, lastVoteInfo_.max);
413 auto refreshRate = CalcRefreshRate(curScreenId_.load(), finalRange);
414 if (currRefreshRate_.load() != refreshRate) {
415 currRefreshRate_.store(refreshRate);
416 schedulePreferredFpsChange_ = true;
417 FrameRateReport();
418 }
419
420 bool frameRateChanged = CollectFrameRateChange(finalRange, rsFrameRateLinker_, appFrameRateLinkers_);
421 CheckRefreshRateChange(followRs, frameRateChanged, refreshRate);
422 ReportHiSysEvent(lastVoteInfo_);
423 }
424
CollectVRateChange(uint64_t linkerId,FrameRateRange & finalRange)425 void HgmFrameRateManager::CollectVRateChange(uint64_t linkerId, FrameRateRange& finalRange)
426 {
427 auto iter = vRatesMap_.find(linkerId);
428 if (iter == vRatesMap_.end()) {
429 RS_OPTIONAL_TRACE_NAME_FMT("CollectVRateChange not find pid = %d linkerId = %" PRIu64 " return",
430 ExtractPid(linkerId), linkerId);
431 HGM_LOGD("CollectVRateChange not find pid = %{public}d linkerId = %{public}" PRIu64 " return",
432 ExtractPid(linkerId), linkerId);
433 return;
434 }
435 if (iter->second == 1 || iter->second == 0) {
436 RS_OPTIONAL_TRACE_NAME_FMT("CollectVRateChange pid = %d , linkerId = %" PRIu64 ", vrate = %d return",
437 ExtractPid(linkerId), linkerId, iter->second);
438 HGM_LOGD("CollectVRateChange linkerId = %{public}" PRIu64 ",vrate = %{public}d return",
439 linkerId, iter->second);
440 return;
441 }
442 int32_t& appFrameRate = finalRange.preferred_;
443 // finalRange.preferred_ is 0 means that the appframerate want to be changed by self.
444 if (appFrameRate != 0) {
445 RS_OPTIONAL_TRACE_NAME_FMT("CollectVRateChange pid = %d , linkerId = %" PRIu64 ", vrate = %d "
446 "return because changed by self", ExtractPid(linkerId), linkerId, iter->second);
447 HGM_LOGD("CollectVRateChange linkerId = %{public}" PRIu64 ",vrate = %{public}d return because changed by self",
448 linkerId, iter->second);
449 return;
450 }
451
452 appFrameRate = static_cast<int>(controllerRate_) / iter->second;
453 // vrate is int::max means app need not refreshing
454 if (appFrameRate == 0) {
455 //appFrameRate value is 1 means that not refreshing.
456 appFrameRate = 1;
457 }
458 finalRange.min_ = OLED_NULL_HZ;
459 finalRange.max_ = OLED_144_HZ;
460 RS_TRACE_NAME_FMT("CollectVRateChange modification pid = %d , linkerIdS = %" PRIu64 ",appFrameRate = %d,"
461 " vrate = %d, rsFrameRate = %u", ExtractPid(linkerId), linkerId, appFrameRate, iter->second, controllerRate_);
462 HGM_LOGD("CollectVRateChange modification linkerId = %{public}" PRIu64 ",appFrameRate = %{public}d,"
463 " vrate = %{public}d, rsFrameRate = %{public}u", linkerId, appFrameRate, iter->second, controllerRate_);
464 }
465
ReportHiSysEvent(const VoteInfo & frameRateVoteInfo)466 void HgmFrameRateManager::ReportHiSysEvent(const VoteInfo& frameRateVoteInfo)
467 {
468 if (frameRateVoteInfo.voterName.empty()) {
469 return;
470 }
471 bool needAdd = frameRateVoteInfoVec_.empty() || frameRateVoteInfoVec_.back().second != frameRateVoteInfo;
472 if (frameRateVoteInfoVec_.size() >= REPORT_VOTER_INFO_LIMIT) {
473 std::string msg;
474 for (auto& [timestamp, voteInfo] : frameRateVoteInfoVec_) {
475 msg += voteInfo.ToString(timestamp);
476 }
477 RS_TRACE_NAME("HgmFrameRateManager::ReportHiSysEvent HiSysEventWrite");
478 RSHiSysEvent::EventWrite(RSEventName::HGM_VOTER_INFO, RSEventType::RS_STATISTIC, "MSG", msg);
479 frameRateVoteInfoVec_.clear();
480 }
481 if (needAdd) {
482 auto currentTime = std::chrono::time_point_cast<std::chrono::milliseconds>(
483 std::chrono::system_clock::now()).time_since_epoch().count();
484 frameRateVoteInfoVec_.push_back({currentTime, frameRateVoteInfo});
485 HGM_LOGD("ReportHiSysEvent: %{public}s", frameRateVoteInfo.ToString(currentTime).c_str());
486 }
487 }
488
FrameRateReport()489 void HgmFrameRateManager::FrameRateReport()
490 {
491 if (!schedulePreferredFpsChange_) {
492 return;
493 }
494 std::unordered_map<pid_t, uint32_t> rates;
495 rates[GetRealPid()] = currRefreshRate_;
496 if (curRefreshRateMode_ != HGM_REFRESHRATE_MODE_AUTO) {
497 rates[UNI_APP_PID] = currRefreshRate_;
498 } else if (schedulePreferredFps_ == OLED_60_HZ && currRefreshRate_ == OLED_60_HZ) {
499 rates[UNI_APP_PID] = OLED_60_HZ;
500 } else {
501 rates[UNI_APP_PID] = OLED_120_HZ;
502 }
503 HGM_LOGD("FrameRateReport: RS(%{public}d) = %{public}d, APP(%{public}d) = %{public}d",
504 GetRealPid(), rates[GetRealPid()], UNI_APP_PID, rates[UNI_APP_PID]);
505 RS_TRACE_NAME_FMT("FrameRateReport: RS(%d) = %d, APP(%d) = %d",
506 GetRealPid(), rates[GetRealPid()], UNI_APP_PID, rates[UNI_APP_PID]);
507 FRAME_TRACE::FrameRateReport::GetInstance().SendFrameRates(rates);
508 FRAME_TRACE::FrameRateReport::GetInstance().SendFrameRatesToRss(rates);
509 schedulePreferredFpsChange_ = false;
510 }
511
CollectFrameRateChange(FrameRateRange finalRange,std::shared_ptr<RSRenderFrameRateLinker> rsFrameRateLinker,const FrameRateLinkerMap & appFrameRateLinkers)512 bool HgmFrameRateManager::CollectFrameRateChange(FrameRateRange finalRange,
513 std::shared_ptr<RSRenderFrameRateLinker> rsFrameRateLinker,
514 const FrameRateLinkerMap& appFrameRateLinkers)
515 {
516 if (controller_ == nullptr) {
517 HGM_LOGE("no valid controller, cannot work correctly, maybe Init() wasn't executed correctly.");
518 return false;
519 }
520 bool frameRateChanged = false;
521 bool controllerRateChanged = false;
522 auto rsFrameRate = GetDrawingFrameRate(currRefreshRate_, finalRange);
523 controllerRate_ = rsFrameRate > 0 ? rsFrameRate : controller_->GetCurrentRate();
524 if (controllerRate_ != controller_->GetCurrentRate()) {
525 rsFrameRateLinker->SetFrameRate(controllerRate_);
526 controllerRateChanged = true;
527 frameRateChanged = true;
528 }
529
530 auto& hgmCore = HgmCore::Instance();
531 auto screenCurrentRefreshRate = hgmCore.GetScreenCurrentRefreshRate(hgmCore.GetActiveScreenId());
532 RS_TRACE_NAME_FMT("CollectFrameRateChange refreshRate: %d, rsFrameRate: %d, finalRange = (%d, %d, %d)",
533 screenCurrentRefreshRate, rsFrameRate, finalRange.min_, finalRange.max_, finalRange.preferred_);
534 RS_TRACE_INT("PreferredFrameRate", static_cast<int>(finalRange.preferred_));
535
536 appChangeData_.clear();
537 for (auto linker : appFrameRateLinkers) {
538 if (linker.second == nullptr) {
539 continue;
540 }
541 auto expectedRange = linker.second->GetExpectedRange();
542 HgmEnergyConsumptionPolicy::Instance().GetVideoCallFrameRate(
543 ExtractPid(linker.first), linker.second->GetVsyncName(), expectedRange);
544 CollectVRateChange(linker.first, expectedRange);
545 auto appFrameRate = touchManager_.GetState() == TouchState::IDLE_STATE ?
546 GetDrawingFrameRate(currRefreshRate_, expectedRange) : OLED_NULL_HZ;
547 if (appFrameRate != linker.second->GetFrameRate() || controllerRateChanged) {
548 linker.second->SetFrameRate(appFrameRate);
549 appChangeData_.emplace_back(linker.second->GetId(), appFrameRate);
550 HGM_LOGD("HgmFrameRateManager: appChangeData linkerId = %{public}" PRIu64 ", %{public}d",
551 linker.second->GetId(), appFrameRate);
552 frameRateChanged = true;
553 }
554 if (expectedRange.min_ == OLED_NULL_HZ && expectedRange.preferred_ == OLED_NULL_HZ &&
555 (expectedRange.max_ == OLED_144_HZ || expectedRange.max_ == OLED_NULL_HZ)) {
556 continue;
557 }
558 RS_TRACE_NAME_FMT("HgmFrameRateManager::UniProcessData multiAppFrameRate: pid = %d, linkerId = %ld, "\
559 "appFrameRate = %d, appRange = (%d, %d, %d)", ExtractPid(linker.first), linker.second->GetId(),
560 appFrameRate, expectedRange.min_, expectedRange.max_, expectedRange.preferred_);
561 }
562 return frameRateChanged;
563 }
564
HandleFrameRateChangeForLTPO(uint64_t timestamp,bool followRs)565 void HgmFrameRateManager::HandleFrameRateChangeForLTPO(uint64_t timestamp, bool followRs)
566 {
567 std::lock_guard<std::mutex> lock(pendingMutex_);
568 auto& hgmCore = HgmCore::Instance();
569 auto lastRefreshRate = hgmCore.GetPendingScreenRefreshRate();
570 uint64_t targetTime = 0;
571 // low refresh rate switch to high refresh rate immediately.
572 if (lastRefreshRate < OLED_60_HZ && currRefreshRate_ > lastRefreshRate) {
573 hgmCore.SetPendingScreenRefreshRate(currRefreshRate_);
574 pendingRefreshRate_ = std::make_shared<uint32_t>(currRefreshRate_);
575 hgmCore.SetScreenRefreshRateImme(currRefreshRate_);
576 if (hgmCore.IsLowRateToHighQuickEnabled() && controller_) {
577 targetTime = controller_->CalcVSyncQuickTriggerTime(timestamp, lastRefreshRate);
578 if (targetTime > timestamp && targetTime > 0) {
579 pendingConstraintRelativeTime_ = targetTime - timestamp;
580 } else {
581 pendingConstraintRelativeTime_ = 0;
582 }
583 hgmCore.SetPendingConstraintRelativeTime(pendingConstraintRelativeTime_);
584 pendingConstraintRelativeTime_ = 0;
585 }
586 // ChangeGeneratorRate delay 1 frame
587 if (!followRs) {
588 changeGeneratorRateValidTimer_.Start();
589 return;
590 }
591 }
592
593 // Start of DVSync
594 int64_t delayTime = CreateVSyncGenerator()->SetCurrentRefreshRate(controllerRate_, lastRefreshRate);
595 if (delayTime != 0) {
596 int64_t controllerRate = controllerRate_;
597 std::vector<std::pair<FrameRateLinkerId, uint32_t>> appChangeData = appChangeData_;
598 bool needUpdate = isNeedUpdateAppOffset_;
599 RSTaskMessage::RSTask task = [this, targetTime, controllerRate, appChangeData, needUpdate]() {
600 if (controller_) {
601 vsyncCountOfChangeGeneratorRate_ = controller_->ChangeGeneratorRate(controllerRate,
602 appChangeData, targetTime, needUpdate);
603 }
604 CreateVSyncGenerator()->SetCurrentRefreshRate(0, 0);
605 };
606 HgmTaskHandleThread::Instance().PostTask(task, delayTime);
607 } else if (controller_) {
608 vsyncCountOfChangeGeneratorRate_ = controller_->ChangeGeneratorRate(
609 controllerRate_, appChangeData_, targetTime, isNeedUpdateAppOffset_);
610 }
611 // End of DVSync
612 isNeedUpdateAppOffset_ = false;
613 pendingRefreshRate_ = std::make_shared<uint32_t>(currRefreshRate_);
614 SetChangeGeneratorRateValid(false);
615 }
616
GetLowBrightVec(const std::shared_ptr<PolicyConfigData> & configData)617 void HgmFrameRateManager::GetLowBrightVec(const std::shared_ptr<PolicyConfigData>& configData)
618 {
619 isAmbientEffect_ = false;
620 multiAppStrategy_.HandleLowAmbientStatus(isAmbientEffect_);
621 if (!configData) {
622 return;
623 }
624
625 // obtain the refresh rate supported in low ambient light
626 if (configData->supportedModeConfigs_.find(curScreenStrategyId_) == configData->supportedModeConfigs_.end()) {
627 return;
628 }
629 auto supportedModeConfig = configData->supportedModeConfigs_[curScreenStrategyId_];
630 auto iter = supportedModeConfig.find(LOW_BRIGHT);
631 if (iter == supportedModeConfig.end() || iter->second.empty()) {
632 return;
633 }
634 auto supportRefreshRateVec = HgmCore::Instance().GetScreenSupportedRefreshRates(curScreenId_.load());
635 lowBrightVec_.clear();
636 for (auto rate : iter->second) {
637 auto it = std::find(supportRefreshRateVec.begin(), supportRefreshRateVec.end(), rate);
638 if (it != supportRefreshRateVec.end()) {
639 lowBrightVec_.push_back(*it);
640 }
641 }
642
643 if (lowBrightVec_.empty()) {
644 return;
645 }
646 isAmbientEffect_ = true;
647 multiAppStrategy_.HandleLowAmbientStatus(isAmbientEffect_);
648 }
649
GetStylusVec(const std::shared_ptr<PolicyConfigData> & configData)650 void HgmFrameRateManager::GetStylusVec(const std::shared_ptr<PolicyConfigData>& configData)
651 {
652 if (!configData) {
653 return;
654 }
655
656 // refresh rate for stylus pen
657 if (configData->supportedModeConfigs_.find(curScreenStrategyId_) == configData->supportedModeConfigs_.end()) {
658 return;
659 }
660 auto supportedModeConfig = configData->supportedModeConfigs_[curScreenStrategyId_];
661 auto iter = supportedModeConfig.find(STYLUS_PEN);
662 if (iter == supportedModeConfig.end() || iter->second.empty()) {
663 return;
664 }
665 auto supportRefreshRateVec = HgmCore::Instance().GetScreenSupportedRefreshRates(curScreenId_.load());
666 stylusVec_.clear();
667 for (auto rate : iter->second) {
668 auto it = std::find(supportRefreshRateVec.begin(), supportRefreshRateVec.end(), rate);
669 if (it != supportRefreshRateVec.end()) {
670 stylusVec_.push_back(rate);
671 }
672 }
673 }
674
CalcRefreshRate(const ScreenId id,const FrameRateRange & range) const675 uint32_t HgmFrameRateManager::CalcRefreshRate(const ScreenId id, const FrameRateRange& range) const
676 {
677 // Find current refreshRate by FrameRateRange. For example:
678 // 1. FrameRateRange[min, max, preferred] is [24, 48, 48], supported refreshRates
679 // of current screen are {30, 60, 90}, the result should be 30, not 60.
680 // 2. FrameRateRange[min, max, preferred] is [150, 150, 150], supported refreshRates
681 // of current screen are {30, 60, 90}, the result will be 90.
682 uint32_t refreshRate = currRefreshRate_;
683 std::vector<uint32_t> supportRefreshRateVec;
684 bool stylusFlag = (stylusMode_ == STYLUS_LINK_WRITE && !stylusVec_.empty());
685 if ((isLtpo_ && isAmbientStatus_ == LightFactorStatus::NORMAL_LOW && isAmbientEffect_) ||
686 (!isLtpo_ && isAmbientEffect_ && isAmbientStatus_ != LightFactorStatus::HIGH_LEVEL)) {
687 supportRefreshRateVec = lowBrightVec_;
688 } else if (stylusFlag) {
689 supportRefreshRateVec = stylusVec_;
690 HGM_LOGD("stylusVec size = %{public}zu", stylusVec_.size());
691 } else {
692 supportRefreshRateVec = HgmCore::Instance().GetScreenSupportedRefreshRates(id);
693 }
694 if (supportRefreshRateVec.empty()) {
695 return refreshRate;
696 }
697 std::sort(supportRefreshRateVec.begin(), supportRefreshRateVec.end());
698 auto iter = std::lower_bound(supportRefreshRateVec.begin(), supportRefreshRateVec.end(), range.preferred_);
699 if (iter != supportRefreshRateVec.end()) {
700 refreshRate = *iter;
701 if (stylusFlag) {
702 return refreshRate;
703 }
704 if (refreshRate > static_cast<uint32_t>(range.max_) &&
705 (iter - supportRefreshRateVec.begin()) > 0) {
706 iter--;
707 if (*iter >= static_cast<uint32_t>(range.min_) &&
708 *iter <= static_cast<uint32_t>(range.max_)) {
709 refreshRate = *iter;
710 }
711 }
712 } else {
713 refreshRate = supportRefreshRateVec.back();
714 }
715 return refreshRate;
716 }
717
GetDrawingFrameRate(const uint32_t refreshRate,const FrameRateRange & range)718 uint32_t HgmFrameRateManager::GetDrawingFrameRate(const uint32_t refreshRate, const FrameRateRange& range)
719 {
720 if (refreshRate == 0 || range.preferred_ <= 0) {
721 return 0;
722 }
723
724 uint32_t preferredFps = static_cast<uint32_t>(range.preferred_);
725 if (!range.IsValid() || preferredFps > refreshRate) {
726 return refreshRate;
727 }
728
729 // find the smallest value in range of [preferredFps, refreshRate], which can exactly divide refreshRate
730 uint32_t divisor = refreshRate / preferredFps;
731 while (divisor > 1) {
732 if (refreshRate % divisor == 0) {
733 break;
734 }
735 divisor--;
736 }
737 return refreshRate / divisor;
738 }
739
Reset()740 void HgmFrameRateManager::Reset()
741 {
742 controllerRate_ = 0;
743 appChangeData_.clear();
744 }
745
GetExpectedFrameRate(const RSPropertyUnit unit,float velocityPx,int32_t areaPx,int32_t lengthPx) const746 int32_t HgmFrameRateManager::GetExpectedFrameRate(const RSPropertyUnit unit, float velocityPx,
747 int32_t areaPx, int32_t lengthPx) const
748 {
749 static const std::map<RSPropertyUnit, std::string> typeMap = {
750 {RSPropertyUnit::PIXEL_POSITION, "translate"},
751 {RSPropertyUnit::PIXEL_SIZE, "scale"},
752 {RSPropertyUnit::RATIO_SCALE, "scale"},
753 {RSPropertyUnit::ANGLE_ROTATION, "rotation"}
754 };
755 if (auto it = typeMap.find(unit); it != typeMap.end()) {
756 return GetPreferredFps(it->second, PixelToMM(velocityPx), SqrPixelToSqrMM(areaPx), PixelToMM(lengthPx));
757 }
758 return 0;
759 }
760
GetPreferredFps(const std::string & type,float velocityMM,float areaSqrMM,float lengthMM) const761 int32_t HgmFrameRateManager::GetPreferredFps(const std::string& type, float velocityMM,
762 float areaSqrMM, float lengthMM) const
763 {
764 auto &configData = HgmCore::Instance().GetPolicyConfigData();
765 if (!configData) {
766 return 0;
767 }
768 if (ROSEN_EQ(velocityMM, 0.f)) {
769 return 0;
770 }
771 const auto curScreenStrategyId = curScreenStrategyId_;
772 const std::string settingMode = std::to_string(curRefreshRateMode_);
773 if (configData->screenConfigs_.find(curScreenStrategyId) == configData->screenConfigs_.end() ||
774 configData->screenConfigs_[curScreenStrategyId].find(settingMode) ==
775 configData->screenConfigs_[curScreenStrategyId].end()) {
776 return 0;
777 }
778 auto& screenSetting = configData->screenConfigs_[curScreenStrategyId][settingMode];
779 auto matchFunc = [velocityMM](const auto& pair) {
780 return velocityMM >= pair.second.min && (velocityMM < pair.second.max || pair.second.max == -1);
781 };
782
783 // find result if it's small size animation
784 bool needCheck = screenSetting.smallSizeArea > 0 && screenSetting.smallSizeLength > 0;
785 bool matchArea = areaSqrMM > 0 && areaSqrMM < screenSetting.smallSizeArea;
786 bool matchLength = lengthMM > 0 && lengthMM < screenSetting.smallSizeLength;
787 if (needCheck && matchArea && matchLength &&
788 screenSetting.smallSizeAnimationDynamicSettings.find(type) !=
789 screenSetting.smallSizeAnimationDynamicSettings.end()) {
790 auto& config = screenSetting.smallSizeAnimationDynamicSettings[type];
791 auto iter = std::find_if(config.begin(), config.end(), matchFunc);
792 if (iter != config.end()) {
793 RS_OPTIONAL_TRACE_NAME_FMT("GetPreferredFps (small size): type: %s, speed: %f, area: %f, length: %f,"
794 "rate: %d", type.c_str(), velocityMM, areaSqrMM, lengthMM, iter->second.preferred_fps);
795 return iter->second.preferred_fps;
796 }
797 }
798
799 // it's not a small size animation or current small size config don't cover it, find result in normal config
800 if (screenSetting.animationDynamicSettings.find(type) != screenSetting.animationDynamicSettings.end()) {
801 auto& config = screenSetting.animationDynamicSettings[type];
802 auto iter = std::find_if(config.begin(), config.end(), matchFunc);
803 if (iter != config.end()) {
804 RS_OPTIONAL_TRACE_NAME_FMT("GetPreferredFps: type: %s, speed: %f, area: %f, length: %f, rate: %d",
805 type.c_str(), velocityMM, areaSqrMM, lengthMM, iter->second.preferred_fps);
806 return iter->second.preferred_fps;
807 }
808 }
809 return 0;
810 }
811
812 template<typename T>
PixelToMM(T pixel)813 float HgmFrameRateManager::PixelToMM(T pixel)
814 {
815 auto& hgmCore = HgmCore::Instance();
816 sptr<HgmScreen> hgmScreen = hgmCore.GetScreen(hgmCore.GetActiveScreenId());
817 if (hgmScreen && hgmScreen->GetPpi() > 0.f) {
818 return pixel / hgmScreen->GetPpi() * INCH_2_MM;
819 }
820 return 0.f;
821 }
822
823 template<typename T>
SqrPixelToSqrMM(T sqrPixel)824 float HgmFrameRateManager::SqrPixelToSqrMM(T sqrPixel)
825 {
826 return PixelToMM(PixelToMM(sqrPixel));
827 }
828
HandleLightFactorStatus(pid_t pid,int32_t state)829 void HgmFrameRateManager::HandleLightFactorStatus(pid_t pid, int32_t state)
830 {
831 // based on the light determine whether allowed to reduce the screen refresh rate to avoid screen flicker
832 // 1.normal strategy : there are two states {NORMAL_HIGH, NORMAL_LOW}
833 // NORMAL_HIGH : allowed to reduce the screen refresh rate; NORMAL_LOW : not allowed
834 // 2.brightness level strategy : there are three states {LOW_LEVEL, MIDDLE_LEVEL, HIGH_LEVEL}
835 // LOW_LEVEL : not allowed to reduce the screen refresh rate, up to 90Hz;
836 // MIDDLE_LEVEL : allowed to reduce the screen refresh rate, up to 90Hz;
837 // HIGH_LEVEL : allowed to reduce the screen refresh rate, up to 120Hz
838 HGM_LOGI("HandleLightFactorStatus status:%{public}d", state);
839 if (pid != DEFAULT_PID) {
840 cleanPidCallback_[pid].insert(CleanPidCallbackType::LIGHT_FACTOR);
841 }
842 multiAppStrategy_.SetScreenType(isLtpo_);
843 multiAppStrategy_.HandleLightFactorStatus(state);
844 isAmbientStatus_ = state;
845 MarkVoteChange();
846 }
847
HandlePackageEvent(pid_t pid,const std::vector<std::string> & packageList)848 void HgmFrameRateManager::HandlePackageEvent(pid_t pid, const std::vector<std::string>& packageList)
849 {
850 if (pid != DEFAULT_PID) {
851 cleanPidCallback_[pid].insert(CleanPidCallbackType::PACKAGE_EVENT);
852 }
853 // check whether to enable HFBC
854 HgmHfbcConfig::HandleHfbcConfig(packageList);
855 if (multiAppStrategy_.HandlePkgsEvent(packageList) == EXEC_SUCCESS) {
856 auto sceneListConfig = multiAppStrategy_.GetScreenSetting().sceneList;
857 for (auto scenePid = sceneStack_.begin(); scenePid != sceneStack_.end();) {
858 if (auto iter = sceneListConfig.find(scenePid->first);
859 iter != sceneListConfig.end() && iter->second.doNotAutoClear) {
860 ++scenePid;
861 continue;
862 }
863 gameScenes_.erase(scenePid->first);
864 ancoScenes_.erase(scenePid->first);
865 scenePid = sceneStack_.erase(scenePid);
866 }
867 }
868 MarkVoteChange("VOTER_SCENE");
869 UpdateAppSupportedState();
870 }
871
HandleRefreshRateEvent(pid_t pid,const EventInfo & eventInfo)872 void HgmFrameRateManager::HandleRefreshRateEvent(pid_t pid, const EventInfo& eventInfo)
873 {
874 std::string eventName = eventInfo.eventName;
875 if (eventName == "VOTER_VIDEO_CALL") {
876 HgmEnergyConsumptionPolicy::Instance().SetVideoCallSceneInfo(eventInfo);
877 return;
878 }
879 auto event = std::find(voters_.begin(), voters_.end(), eventName);
880 if (event == voters_.end()) {
881 HGM_LOGW("HgmFrameRateManager:unknown event, eventName is %{public}s", eventName.c_str());
882 return;
883 }
884
885 HGM_LOGD("%{public}s(%{public}d) %{public}s", eventName.c_str(), pid, eventInfo.description.c_str());
886 if (eventName == "VOTER_SCENE") {
887 HandleSceneEvent(pid, eventInfo);
888 } else if (eventName == "VOTER_VIRTUALDISPLAY") {
889 HandleVirtualDisplayEvent(pid, eventInfo);
890 } else if (eventName == "VOTER_GAMES") {
891 HandleGamesEvent(pid, eventInfo);
892 } else if (eventName == "VOTER_MULTISELFOWNEDSCREEN") {
893 HandleMultiSelfOwnedScreenEvent(pid, eventInfo);
894 } else {
895 DeliverRefreshRateVote({eventName, eventInfo.minRefreshRate, eventInfo.maxRefreshRate, pid},
896 eventInfo.eventStatus);
897 }
898 }
899
HandleTouchEvent(pid_t pid,int32_t touchStatus,int32_t touchCnt)900 void HgmFrameRateManager::HandleTouchEvent(pid_t pid, int32_t touchStatus, int32_t touchCnt)
901 {
902 HGM_LOGD("HandleTouchEvent status:%{public}d", touchStatus);
903 if (voterGamesEffective_ && touchManager_.GetState() == TouchState::DOWN_STATE) {
904 return;
905 }
906 if (voterGamesEffective_ &&
907 (touchStatus == TOUCH_MOVE || touchStatus == TOUCH_BUTTON_DOWN || touchStatus == TOUCH_BUTTON_UP)) {
908 return;
909 }
910 HgmTaskHandleThread::Instance().PostTask([this, pid, touchStatus, touchCnt] () {
911 if (touchStatus == TOUCH_MOVE || touchStatus == TOUCH_BUTTON_DOWN || touchStatus == TOUCH_BUTTON_UP) {
912 HandlePointerTask(pid, touchStatus, touchCnt);
913 } else {
914 HandleTouchTask(pid, touchStatus, touchCnt);
915 }
916 });
917 }
918
HandleTouchTask(pid_t pid,int32_t touchStatus,int32_t touchCnt)919 void HgmFrameRateManager::HandleTouchTask(pid_t pid, int32_t touchStatus, int32_t touchCnt)
920 {
921 if (pid != DEFAULT_PID) {
922 cleanPidCallback_[pid].insert(CleanPidCallbackType::TOUCH_EVENT);
923 }
924
925 if (touchStatus == TOUCH_DOWN || touchStatus == TOUCH_PULL_DOWN) {
926 HGM_LOGD("[touch manager] down");
927 PolicyConfigData::StrategyConfig strategyRes;
928 touchManager_.HandleTouchEvent(TouchEvent::DOWN_EVENT, "");
929 } else if (touchStatus == TOUCH_UP || touchStatus == TOUCH_PULL_UP) {
930 if (touchCnt != LAST_TOUCH_CNT) {
931 return;
932 }
933 if (auto iter = voteRecord_.find("VOTER_GAMES"); iter != voteRecord_.end() && !iter->second.first.empty() &&
934 gameScenes_.empty() && multiAppStrategy_.CheckPidValid(iter->second.first.front().pid)) {
935 HGM_LOGD("[touch manager] keep down in games");
936 return;
937 }
938 if (touchCnt == LAST_TOUCH_CNT) {
939 HGM_LOGD("[touch manager] up");
940 touchManager_.HandleTouchEvent(TouchEvent::UP_EVENT, "");
941 }
942 } else {
943 HGM_LOGD("[touch manager] other touch status not support");
944 }
945 }
946
HandlePointerTask(pid_t pid,int32_t pointerStatus,int32_t pointerCnt)947 void HgmFrameRateManager::HandlePointerTask(pid_t pid, int32_t pointerStatus, int32_t pointerCnt)
948 {
949 if (pid != DEFAULT_PID) {
950 cleanPidCallback_[pid].insert(CleanPidCallbackType::TOUCH_EVENT);
951 }
952
953 if (pointerStatus == TOUCH_MOVE || pointerStatus == TOUCH_BUTTON_DOWN || pointerStatus == TOUCH_BUTTON_UP) {
954 PolicyConfigData::StrategyConfig strategyRes;
955 if (multiAppStrategy_.GetFocusAppStrategyConfig(strategyRes) == EXEC_SUCCESS &&
956 strategyRes.pointerMode != PointerModeType::POINTER_DISENABLED) {
957 HGM_LOGD("[pointer manager] active");
958 pointerManager_.HandleTimerReset();
959 pointerManager_.HandlePointerEvent(PointerEvent::POINTER_ACTIVE_EVENT, "");
960 }
961 }
962 }
963
HandleDynamicModeEvent(bool enableDynamicModeEvent)964 void HgmFrameRateManager::HandleDynamicModeEvent(bool enableDynamicModeEvent)
965 {
966 HGM_LOGE("HandleDynamicModeEvent status:%{public}u", enableDynamicModeEvent);
967 HgmCore::Instance().SetEnableDynamicMode(enableDynamicModeEvent);
968 multiAppStrategy_.CalcVote();
969 }
970
HandleIdleEvent(bool isIdle)971 void HgmFrameRateManager::HandleIdleEvent(bool isIdle)
972 {
973 if (isIdle) {
974 HGM_LOGD("HandleIdleEvent status:%{public}u", isIdle);
975 DeliverRefreshRateVote({"VOTER_IDLE", idleFps_, idleFps_}, ADD_VOTE);
976 } else {
977 DeliverRefreshRateVote({"VOTER_IDLE"}, REMOVE_VOTE);
978 }
979 }
980
HandleRefreshRateMode(int32_t refreshRateMode)981 void HgmFrameRateManager::HandleRefreshRateMode(int32_t refreshRateMode)
982 {
983 HGM_LOGI("HandleRefreshRateMode curMode:%{public}d", refreshRateMode);
984 if (curRefreshRateMode_ == refreshRateMode) {
985 return;
986 }
987
988 curRefreshRateMode_ = refreshRateMode;
989 DeliverRefreshRateVote({"VOTER_LTPO"}, REMOVE_VOTE);
990 multiAppStrategy_.UpdateXmlConfigCache();
991 UpdateEnergyConsumptionConfig();
992 HandlePageUrlEvent();
993 multiAppStrategy_.CalcVote();
994 HgmCore::Instance().SetLtpoConfig();
995 HgmConfigCallbackManager::GetInstance()->SyncHgmConfigChangeCallback();
996 UpdateAppSupportedState(); // sync app state config when RefreshRateMode changed
997 }
998
HandleScreenPowerStatus(ScreenId id,ScreenPowerStatus status)999 void HgmFrameRateManager::HandleScreenPowerStatus(ScreenId id, ScreenPowerStatus status)
1000 {
1001 // hgm warning: strategy for screen off
1002 HGM_LOGI("curScreen:%{public}d status:%{public}d", static_cast<int>(id), static_cast<int>(status));
1003 if (status == ScreenPowerStatus::POWER_STATUS_ON) {
1004 ReportHiSysEvent({.voterName = "SCREEN_POWER", .extInfo = "ON"});
1005 } else if (status == ScreenPowerStatus::POWER_STATUS_SUSPEND) {
1006 ReportHiSysEvent({.voterName = "SCREEN_POWER", .extInfo = "OFF"});
1007 }
1008 if (status != ScreenPowerStatus::POWER_STATUS_ON || curScreenId_.load() == id) {
1009 return;
1010 }
1011
1012 auto& hgmCore = HgmCore::Instance();
1013 auto screen = hgmCore.GetScreen(id);
1014 if (!screen || !screen->GetSelfOwnedScreenFlag()) {
1015 return;
1016 }
1017 if (hgmCore.GetMultiSelfOwnedScreenEnable()) {
1018 return;
1019 }
1020 auto& hgmScreenInfo = HgmScreenInfo::GetInstance();
1021 auto isLtpo = hgmScreenInfo.IsLtpoType(hgmScreenInfo.GetScreenType(id));
1022 std::string curScreenName = "screen" + std::to_string(id) + "_" + (isLtpo ? "LTPO" : "LTPS");
1023
1024 isLtpo_ = isLtpo;
1025 lastCurScreenId_.store(curScreenId_.load());
1026 curScreenId_.store(id);
1027 hgmCore.SetActiveScreenId(curScreenId_.load());
1028 HGM_LOGD("curScreen change:%{public}d", static_cast<int>(curScreenId_.load()));
1029
1030 HandleScreenFrameRate(curScreenName);
1031 HandlePageUrlEvent();
1032 }
1033
HandleScreenRectFrameRate(ScreenId id,const GraphicIRect & activeRect)1034 void HgmFrameRateManager::HandleScreenRectFrameRate(ScreenId id, const GraphicIRect& activeRect)
1035 {
1036 RS_TRACE_NAME_FMT("HgmFrameRateManager::HandleScreenRectFrameRate screenId:%d activeRect(%d, %d, %d, %d)",
1037 id, activeRect.x, activeRect.y, activeRect.w, activeRect.h);
1038 auto& hgmScreenInfo = HgmScreenInfo::GetInstance();
1039 auto& hgmCore = HgmCore::Instance();
1040 auto screen = hgmCore.GetScreen(id);
1041 if (!screen || !screen->GetSelfOwnedScreenFlag()) {
1042 return;
1043 }
1044
1045 auto isLtpo = hgmScreenInfo.IsLtpoType(hgmScreenInfo.GetScreenType(id));
1046
1047 std::string curScreenName = "screen" + std::to_string(id) + "_" + (isLtpo ? "LTPO" : "LTPS");
1048 curScreenName += "_" + std::to_string(activeRect.x);
1049 curScreenName += "_" + std::to_string(activeRect.y);
1050 curScreenName += "_" + std::to_string(activeRect.w);
1051 curScreenName += "_" + std::to_string(activeRect.h);
1052
1053 HandleScreenFrameRate(curScreenName);
1054 }
1055
HandleScreenFrameRate(std::string curScreenName)1056 void HgmFrameRateManager::HandleScreenFrameRate(std::string curScreenName)
1057 {
1058 auto& hgmCore = HgmCore::Instance();
1059 auto configData = hgmCore.GetPolicyConfigData();
1060 if (configData == nullptr) {
1061 return;
1062 }
1063
1064 if (configData->screenStrategyConfigs_.find(curScreenName) != configData->screenStrategyConfigs_.end()) {
1065 curScreenStrategyId_ = configData->screenStrategyConfigs_[curScreenName];
1066 } else {
1067 curScreenStrategyId_ = "LTPO-DEFAULT";
1068 }
1069
1070 if (isEnableThermalStrategy_ && configData->screenConfigs_.find(
1071 curScreenStrategyId_ + HGM_CONFIG_TYPE_THERMAL_SUFFIX) != configData->screenConfigs_.end()) {
1072 curScreenStrategyId_ += HGM_CONFIG_TYPE_THERMAL_SUFFIX;
1073 }
1074
1075 UpdateScreenFrameRate();
1076 }
1077
HandleThermalFrameRate(bool status)1078 void HgmFrameRateManager::HandleThermalFrameRate(bool status)
1079 {
1080 auto& hgmCore = HgmCore::Instance();
1081 auto configData = hgmCore.GetPolicyConfigData();
1082 if (configData == nullptr) {
1083 return;
1084 }
1085
1086 if (isEnableThermalStrategy_ == status) {
1087 return;
1088 }
1089 isEnableThermalStrategy_ = status;
1090 std::string curScreenStrategyId;
1091 if (isEnableThermalStrategy_) {
1092 curScreenStrategyId = curScreenStrategyId_ + HGM_CONFIG_TYPE_THERMAL_SUFFIX;
1093 } else {
1094 curScreenStrategyId = curScreenStrategyId_.substr(
1095 0, curScreenStrategyId_.length() - std::string(HGM_CONFIG_TYPE_THERMAL_SUFFIX).length());
1096 }
1097 if (configData->screenConfigs_.find(curScreenStrategyId) == configData->screenConfigs_.end()) {
1098 HGM_LOGE("HgmFrameRateManager::HandleThermalFrameRate not support thermal config");
1099 return;
1100 }
1101 RS_TRACE_NAME_FMT("HgmFrameRateManager::HandleThermalFrameRate type:%s, status:%d", curScreenStrategyId.c_str(),
1102 status);
1103 curScreenStrategyId_ = curScreenStrategyId;
1104 UpdateScreenFrameRate();
1105 }
1106
UpdateScreenFrameRate()1107 void HgmFrameRateManager::UpdateScreenFrameRate()
1108 {
1109 auto& hgmCore = HgmCore::Instance();
1110 auto configData = hgmCore.GetPolicyConfigData();
1111 if (configData == nullptr) {
1112 return;
1113 }
1114
1115 multiAppStrategy_.UpdateXmlConfigCache();
1116 GetLowBrightVec(configData);
1117 GetStylusVec(configData);
1118 UpdateEnergyConsumptionConfig();
1119
1120 multiAppStrategy_.CalcVote();
1121 hgmCore.SetLtpoConfig();
1122 MarkVoteChange();
1123 HgmConfigCallbackManager::GetInstance()->SyncHgmConfigChangeCallback();
1124
1125 // hgm warning: use !isLtpo_ instead after GetDisplaySupportedModes ready
1126 if (curScreenStrategyId_.find("LTPO") == std::string::npos) {
1127 DeliverRefreshRateVote({"VOTER_LTPO"}, REMOVE_VOTE);
1128 }
1129
1130 if (!IsCurrentScreenSupportAS()) {
1131 isAdaptive_.store(SupportASStatus::NOT_SUPPORT);
1132 }
1133 }
1134
HandleRsFrame()1135 void HgmFrameRateManager::HandleRsFrame()
1136 {
1137 touchManager_.HandleRsFrame();
1138 pointerManager_.HandleRsFrame();
1139 }
1140
HandleSceneEvent(pid_t pid,EventInfo eventInfo)1141 void HgmFrameRateManager::HandleSceneEvent(pid_t pid, EventInfo eventInfo)
1142 {
1143 std::string sceneName = eventInfo.description;
1144 auto screenSetting = multiAppStrategy_.GetScreenSetting();
1145 auto &gameSceneList = screenSetting.gameSceneList;
1146 auto &ancoSceneList = screenSetting.ancoSceneList;
1147
1148 // control the list of supported frame rates for stylus pen, not control frame rate directly
1149 if (STYLUS_STATUS_MAP.find(sceneName) != STYLUS_STATUS_MAP.end()) {
1150 stylusMode_ = STYLUS_STATUS_MAP.at(sceneName);
1151 return;
1152 }
1153
1154 if (gameSceneList.find(sceneName) != gameSceneList.end()) {
1155 if (eventInfo.eventStatus == ADD_VOTE) {
1156 if (gameScenes_.insert(sceneName).second) {
1157 MarkVoteChange();
1158 }
1159 } else {
1160 if (gameScenes_.erase(sceneName)) {
1161 MarkVoteChange();
1162 }
1163 }
1164 }
1165 if (ancoSceneList.find(sceneName) != ancoSceneList.end()) {
1166 if (eventInfo.eventStatus == ADD_VOTE) {
1167 if (ancoScenes_.insert(sceneName).second) {
1168 MarkVoteChange();
1169 }
1170 } else {
1171 if (ancoScenes_.erase(sceneName)) {
1172 MarkVoteChange();
1173 }
1174 }
1175 }
1176
1177 std::pair<std::string, pid_t> info = std::make_pair(sceneName, pid);
1178 auto scenePos = find(sceneStack_.begin(), sceneStack_.end(), info);
1179 if (eventInfo.eventStatus == ADD_VOTE) {
1180 if (scenePos == sceneStack_.end()) {
1181 sceneStack_.push_back(info);
1182 MarkVoteChange("VOTER_SCENE");
1183 }
1184 } else {
1185 if (scenePos != sceneStack_.end()) {
1186 sceneStack_.erase(scenePos);
1187 MarkVoteChange("VOTER_SCENE");
1188 }
1189 }
1190 }
1191
HandleVirtualDisplayEvent(pid_t pid,EventInfo eventInfo)1192 void HgmFrameRateManager::HandleVirtualDisplayEvent(pid_t pid, EventInfo eventInfo)
1193 {
1194 std::string virtualDisplayName = eventInfo.description;
1195 auto configData = HgmCore::Instance().GetPolicyConfigData();
1196 if (configData == nullptr || !configData->virtualDisplaySwitch_) {
1197 // disable vote from virtual display in xml
1198 return;
1199 }
1200
1201 auto virtualDisplayConfig = configData->virtualDisplayConfigs_;
1202 if (virtualDisplayConfig.count(virtualDisplayName) == 0 ||
1203 configData->strategyConfigs_.count(virtualDisplayConfig[virtualDisplayName]) == 0) {
1204 HGM_LOGW("HandleVirtualDisplayEvent:unknow virtual display [%{public}s]", virtualDisplayName.c_str());
1205 DeliverRefreshRateVote({"VOTER_VIRTUALDISPLAY", OLED_60_HZ, OLED_60_HZ, pid}, eventInfo.eventStatus);
1206 } else {
1207 auto curStrategy = configData->strategyConfigs_[virtualDisplayConfig[virtualDisplayName]];
1208 DeliverRefreshRateVote({"VOTER_VIRTUALDISPLAY", curStrategy.min, curStrategy.max, pid}, ADD_VOTE);
1209 }
1210 }
1211
HandleGamesEvent(pid_t pid,EventInfo eventInfo)1212 void HgmFrameRateManager::HandleGamesEvent(pid_t pid, EventInfo eventInfo)
1213 {
1214 if (!eventInfo.eventStatus) {
1215 isGameSupportAS_ = SupportASStatus::NOT_SUPPORT;
1216 DeliverRefreshRateVote({"VOTER_GAMES"}, false);
1217 return;
1218 }
1219 auto [pkgName, gamePid, appType] = HgmMultiAppStrategy::AnalyzePkgParam(eventInfo.description);
1220 if (gamePid == DEFAULT_PID) {
1221 HGM_LOGE("unknow game pid: %{public}s, skip", eventInfo.description.c_str());
1222 return;
1223 }
1224 if (pid != DEFAULT_PID) {
1225 cleanPidCallback_[pid].insert(CleanPidCallbackType::GAMES);
1226 }
1227 PolicyConfigData::StrategyConfig config;
1228 if (multiAppStrategy_.GetAppStrategyConfig(pkgName, config) == EXEC_SUCCESS) {
1229 isGameSupportAS_ = config.supportAS;
1230 SetGameNodeName(multiAppStrategy_.GetGameNodeName(pkgName));
1231 } else {
1232 isGameSupportAS_ = SupportASStatus::NOT_SUPPORT;
1233 SetGameNodeName("");
1234 }
1235 DeliverRefreshRateVote(
1236 {"VOTER_GAMES", eventInfo.minRefreshRate, eventInfo.maxRefreshRate, gamePid}, eventInfo.eventStatus);
1237 }
1238
HandleMultiSelfOwnedScreenEvent(pid_t pid,EventInfo eventInfo)1239 void HgmFrameRateManager::HandleMultiSelfOwnedScreenEvent(pid_t pid, EventInfo eventInfo)
1240 {
1241 HgmCore::Instance().SetMultiSelfOwnedScreenEnable(eventInfo.eventStatus);
1242 DeliverRefreshRateVote(
1243 {"VOTER_MULTISELFOWNEDSCREEN", eventInfo.minRefreshRate, eventInfo.maxRefreshRate, pid},
1244 eventInfo.eventStatus);
1245 }
1246
MarkVoteChange(const std::string & voter)1247 void HgmFrameRateManager::MarkVoteChange(const std::string& voter)
1248 {
1249 if (auto iter = voteRecord_.find(voter);
1250 voter != "" && (iter == voteRecord_.end() || !iter->second.second) && !voterTouchEffective_) {
1251 return;
1252 }
1253 Reset();
1254
1255 VoteInfo resultVoteInfo = ProcessRefreshRateVote();
1256 if (lastVoteInfo_ == resultVoteInfo) {
1257 if (!voterTouchEffective_) {
1258 return;
1259 }
1260 } else {
1261 lastVoteInfo_ = resultVoteInfo;
1262 HGM_LOGI("Strategy:%{public}s Screen:%{public}d Mode:%{public}d -- %{public}s", curScreenStrategyId_.c_str(),
1263 static_cast<int>(curScreenId_.load()), curRefreshRateMode_, resultVoteInfo.ToSimpleString().c_str());
1264 }
1265
1266 // max used here
1267 FrameRateRange finalRange = {resultVoteInfo.max, resultVoteInfo.max, resultVoteInfo.max};
1268 auto refreshRate = CalcRefreshRate(curScreenId_.load(), finalRange);
1269 if (refreshRate == currRefreshRate_ && isAmbientStatus_ < LightFactorStatus::LOW_LEVEL && !voterTouchEffective_) {
1270 return;
1271 }
1272
1273 // changeGenerator only once in a single vsync period
1274 if (!changeGeneratorRateValid_.load()) {
1275 return;
1276 }
1277 bool needChangeDssRefreshRate = currRefreshRate_.load() != refreshRate;
1278 RS_TRACE_NAME_FMT("MarkVoteChange: %d %d", currRefreshRate_.load(), refreshRate);
1279 currRefreshRate_.store(refreshRate);
1280 schedulePreferredFpsChange_ = needChangeDssRefreshRate;
1281 FrameRateReport();
1282
1283 bool frameRateChanged = false;
1284 if (rsFrameRateLinker_ != nullptr) {
1285 frameRateChanged = CollectFrameRateChange(finalRange, rsFrameRateLinker_, appFrameRateLinkers_);
1286 }
1287 // 当dvsync在连续延迟切帧阶段,使用dvsync内记录的刷新率判断是否变化
1288 CreateVSyncGenerator()->DVSyncRateChanged(controllerRate_, frameRateChanged);
1289 auto& hgmCore = HgmCore::Instance();
1290 bool needForceUpdate = currRefreshRate_.load() != hgmCore.GetPendingScreenRefreshRate();
1291 if (hgmCore.GetLtpoEnabled() && frameRateChanged) {
1292 HandleFrameRateChangeForLTPO(timestamp_.load(), false);
1293 if (needChangeDssRefreshRate && changeDssRefreshRateCb_ != nullptr) {
1294 changeDssRefreshRateCb_(curScreenId_, refreshRate, true);
1295 }
1296 } else {
1297 std::lock_guard<std::mutex> lock(pendingMutex_);
1298 pendingRefreshRate_ = std::make_shared<uint32_t>(currRefreshRate_);
1299 if (needChangeDssRefreshRate && changeDssRefreshRateCb_ != nullptr) {
1300 changeDssRefreshRateCb_(curScreenId_, refreshRate, true);
1301 }
1302 }
1303 ReportHiSysEvent(resultVoteInfo);
1304 }
1305
DeliverRefreshRateVote(const VoteInfo & voteInfo,bool eventStatus)1306 void HgmFrameRateManager::DeliverRefreshRateVote(const VoteInfo& voteInfo, bool eventStatus)
1307 {
1308 RS_TRACE_NAME_FMT("Deliver voter:%s(pid:%d extInfo:%s), status:%u, value:[%d-%d]",
1309 voteInfo.voterName.c_str(), voteInfo.pid, voteInfo.extInfo.c_str(),
1310 eventStatus, voteInfo.min, voteInfo.max);
1311 if (voteInfo.min > voteInfo.max) {
1312 HGM_LOGW("HgmFrameRateManager:invalid vote %{public}s(%{public}d %{public}s):[%{public}d, %{public}d]",
1313 voteInfo.voterName.c_str(), voteInfo.pid, voteInfo.extInfo.c_str(), voteInfo.min, voteInfo.max);
1314 return;
1315 }
1316
1317 voteRecord_.try_emplace(voteInfo.voterName, std::pair<std::vector<VoteInfo>, bool>({{}, true}));
1318 auto& vec = voteRecord_[voteInfo.voterName].first;
1319
1320 auto voter = voteInfo.voterName != "VOTER_PACKAGES" ? voteInfo.voterName : "";
1321
1322 // clear
1323 if ((voteInfo.pid == 0) && (eventStatus == REMOVE_VOTE)) {
1324 if (!vec.empty()) {
1325 vec.clear();
1326 MarkVoteChange(voter);
1327 }
1328 return;
1329 }
1330
1331 for (auto it = vec.begin(); it != vec.end(); it++) {
1332 if ((*it).pid != voteInfo.pid) {
1333 continue;
1334 }
1335
1336 if (eventStatus == REMOVE_VOTE) {
1337 // remove
1338 it = vec.erase(it);
1339 MarkVoteChange(voter);
1340 return;
1341 } else {
1342 if ((*it).min != voteInfo.min || (*it).max != voteInfo.max) {
1343 // modify
1344 vec.erase(it);
1345 vec.push_back(voteInfo);
1346 MarkVoteChange(voter);
1347 } else if (voteInfo.voterName == "VOTER_PACKAGES") {
1348 // force update cause VOTER_PACKAGES is flag of safe_voter
1349 MarkVoteChange(voter);
1350 }
1351 return;
1352 }
1353 }
1354
1355 // add
1356 if (eventStatus == ADD_VOTE) {
1357 pidRecord_.insert(voteInfo.pid);
1358 vec.push_back(voteInfo);
1359 MarkVoteChange(voter);
1360 }
1361 }
1362
MergeRangeByPriority(VoteRange & rangeRes,const VoteRange & curVoteRange)1363 std::pair<bool, bool> HgmFrameRateManager::MergeRangeByPriority(VoteRange& rangeRes, const VoteRange& curVoteRange)
1364 {
1365 auto &[min, max] = rangeRes;
1366 auto &[minTemp, maxTemp] = curVoteRange;
1367 bool needMergeVoteInfo = false;
1368 if (minTemp > min) {
1369 min = minTemp;
1370 if (min >= max) {
1371 min = max;
1372 return {true, needMergeVoteInfo};
1373 }
1374 }
1375 if (maxTemp < max) {
1376 max = maxTemp;
1377 needMergeVoteInfo = true;
1378 if (min >= max) {
1379 max = min;
1380 return {true, needMergeVoteInfo};
1381 }
1382 }
1383 if (min == max) {
1384 return {true, needMergeVoteInfo};
1385 }
1386 return {false, needMergeVoteInfo};
1387 }
1388
MergeLtpo2IdleVote(std::vector<std::string>::iterator & voterIter,VoteInfo & resultVoteInfo,VoteRange & mergedVoteRange)1389 bool HgmFrameRateManager::MergeLtpo2IdleVote(
1390 std::vector<std::string>::iterator &voterIter, VoteInfo& resultVoteInfo, VoteRange &mergedVoteRange)
1391 {
1392 bool mergeSuccess = false;
1393 // [VOTER_LTPO, VOTER_IDLE)
1394 for (; voterIter != voters_.end() - 1; voterIter++) {
1395 if (voteRecord_.find(*voterIter) == voteRecord_.end()) {
1396 continue;
1397 }
1398 voteRecord_[*voterIter].second = true;
1399 auto vec = voteRecord_[*voterIter].first;
1400 if (vec.empty()) {
1401 continue;
1402 }
1403
1404 VoteInfo curVoteInfo = vec.back();
1405 if (!multiAppStrategy_.CheckPidValid(curVoteInfo.pid)) {
1406 ProcessVoteLog(curVoteInfo, true);
1407 continue;
1408 }
1409 if (curVoteInfo.voterName == "VOTER_VIDEO") {
1410 std::string voterPkgName = "";
1411 auto foregroundPidApp = multiAppStrategy_.GetForegroundPidApp();
1412 if (foregroundPidApp.find(curVoteInfo.pid) != foregroundPidApp.end()) {
1413 voterPkgName = foregroundPidApp[curVoteInfo.pid].second;
1414 } else if (auto pkgs = multiAppStrategy_.GetPackages(); !pkgs.empty()) { // Get the current package name
1415 voterPkgName = std::get<0>(HgmMultiAppStrategy::AnalyzePkgParam(pkgs.front()));
1416 }
1417 auto configData = HgmCore::Instance().GetPolicyConfigData();
1418 if (configData != nullptr &&
1419 configData->videoFrameRateList_.find(voterPkgName) == configData->videoFrameRateList_.end()) {
1420 ProcessVoteLog(curVoteInfo, true);
1421 continue;
1422 }
1423 }
1424 ProcessVoteLog(curVoteInfo, false);
1425 if (mergeSuccess) {
1426 mergedVoteRange.first = mergedVoteRange.first > curVoteInfo.min ? mergedVoteRange.first : curVoteInfo.min;
1427 if (curVoteInfo.max >= mergedVoteRange.second) {
1428 mergedVoteRange.second = curVoteInfo.max;
1429 resultVoteInfo.Merge(curVoteInfo);
1430 }
1431 } else {
1432 resultVoteInfo.Merge(curVoteInfo);
1433 mergedVoteRange = {curVoteInfo.min, curVoteInfo.max};
1434 }
1435 mergeSuccess = true;
1436 }
1437 return mergeSuccess;
1438 }
1439
IsCurrentScreenSupportAS()1440 bool HgmFrameRateManager::IsCurrentScreenSupportAS()
1441 {
1442 auto hdiDevice = HdiDevice::GetInstance();
1443 if (hdiDevice == nullptr) {
1444 return false;
1445 }
1446 ScreenId id = HgmCore::Instance().GetActiveScreenId();
1447 ScreenPhysicalId screenId = static_cast<ScreenPhysicalId>(id);
1448 uint64_t propertyAS = 0;
1449 hdiDevice->GetDisplayProperty(screenId, ADAPTIVE_SYNC_PROPERTY, propertyAS);
1450 return propertyAS == DISPLAY_SUCCESS;
1451 }
1452
ProcessAdaptiveSync(const std::string & voterName)1453 void HgmFrameRateManager::ProcessAdaptiveSync(const std::string& voterName)
1454 {
1455 bool isAdaptiveSyncEnabled = HgmCore::Instance().GetAdaptiveSyncEnabled();
1456
1457 if (isGameSupportAS_ != SupportASStatus::SUPPORT_AS) {
1458 isAdaptive_.store(isGameSupportAS_);
1459 return;
1460 }
1461
1462 if (!isAdaptiveSyncEnabled) {
1463 return;
1464 }
1465
1466 // VOTER_GAMES wins, enter adaptive vsync mode
1467 bool isGameVoter = voterName == "VOTER_GAMES";
1468
1469 if ((isAdaptive_.load() == SupportASStatus::SUPPORT_AS && isGameVoter) ||
1470 (isAdaptive_.load() == SupportASStatus::NOT_SUPPORT && !isGameVoter)) {
1471 return;
1472 }
1473
1474 if (isGameVoter && isGameSupportAS_ != SupportASStatus::SUPPORT_AS) {
1475 HGM_LOGI("this game does not support adaptive sync mode");
1476 return;
1477 }
1478
1479 if (isGameVoter && !IsCurrentScreenSupportAS()) {
1480 HGM_LOGI("current screen not support adaptive sync mode");
1481 return;
1482 }
1483
1484 HGM_LOGI("ProcessHgmFrameRate RSAdaptiveVsync change mode");
1485 RS_TRACE_BEGIN("ProcessHgmFrameRate RSAdaptiveVsync change mode");
1486 isAdaptive_.load() == SupportASStatus::NOT_SUPPORT ? isAdaptive_.store(SupportASStatus::SUPPORT_AS) :
1487 isAdaptive_.store(SupportASStatus::NOT_SUPPORT);
1488 RS_TRACE_END();
1489 }
1490
CheckAncoVoter(const std::string & voter,VoteInfo & curVoteInfo)1491 void HgmFrameRateManager::CheckAncoVoter(const std::string& voter, VoteInfo& curVoteInfo)
1492 {
1493 if (voter == "VOTER_ANCO" && !ancoScenes_.empty()) {
1494 // Multiple scene are not considered at this time
1495 auto configData = HgmCore::Instance().GetPolicyConfigData();
1496 auto screenSetting = multiAppStrategy_.GetScreenSetting();
1497 auto ancoSceneIt = screenSetting.ancoSceneList.find(*ancoScenes_.begin());
1498 uint32_t min = OLED_60_HZ;
1499 uint32_t max = OLED_90_HZ;
1500 if (configData != nullptr && ancoSceneIt != screenSetting.ancoSceneList.end() &&
1501 configData->strategyConfigs_.find(ancoSceneIt->second.strategy) != configData->strategyConfigs_.end()) {
1502 min = static_cast<uint32_t>(configData->strategyConfigs_[ancoSceneIt->second.strategy].min);
1503 max = static_cast<uint32_t>(configData->strategyConfigs_[ancoSceneIt->second.strategy].max);
1504 }
1505 curVoteInfo.SetRange(min, max);
1506 }
1507 }
1508
ProcessRefreshRateVote(std::vector<std::string>::iterator & voterIter,VoteInfo & resultVoteInfo,VoteRange & voteRange,bool & voterGamesEffective)1509 bool HgmFrameRateManager::ProcessRefreshRateVote(std::vector<std::string>::iterator& voterIter,
1510 VoteInfo& resultVoteInfo, VoteRange& voteRange, bool &voterGamesEffective)
1511 {
1512 VoteRange range;
1513 VoteInfo info;
1514 if (*voterIter == "VOTER_LTPO" && MergeLtpo2IdleVote(voterIter, info, range)) {
1515 auto [mergeVoteRange, mergeVoteInfo] = MergeRangeByPriority(voteRange, range);
1516 if (mergeVoteInfo) {
1517 resultVoteInfo.Merge(info);
1518 }
1519 if (mergeVoteRange) {
1520 return true;
1521 }
1522 }
1523
1524 auto &voter = *voterIter;
1525 if (voteRecord_.find(voter) == voteRecord_.end()) {
1526 return false;
1527 }
1528 voteRecord_[voter].second = true;
1529 auto& voteInfos = voteRecord_[voter].first;
1530 auto firstValidVoteInfoIter = std::find_if(voteInfos.begin(), voteInfos.end(), [this] (auto& voteInfo) {
1531 if (!multiAppStrategy_.CheckPidValid(voteInfo.pid)) {
1532 ProcessVoteLog(voteInfo, true);
1533 return false;
1534 }
1535 return true;
1536 });
1537 if (firstValidVoteInfoIter == voteInfos.end()) {
1538 return false;
1539 }
1540 auto curVoteInfo = *firstValidVoteInfoIter;
1541 if (voter == "VOTER_GAMES") {
1542 if (!gameScenes_.empty() || !multiAppStrategy_.CheckPidValid(curVoteInfo.pid, true)) {
1543 ProcessVoteLog(curVoteInfo, true);
1544 return false;
1545 }
1546 voterGamesEffective = true;
1547 }
1548 CheckAncoVoter(voter, curVoteInfo);
1549 ProcessVoteLog(curVoteInfo, false);
1550 auto [mergeVoteRange, mergeVoteInfo] = MergeRangeByPriority(voteRange, {curVoteInfo.min, curVoteInfo.max});
1551 if (mergeVoteInfo) {
1552 resultVoteInfo.Merge(curVoteInfo);
1553 }
1554 if (mergeVoteRange) {
1555 return true;
1556 }
1557 return false;
1558 }
1559
ProcessRefreshRateVote()1560 VoteInfo HgmFrameRateManager::ProcessRefreshRateVote()
1561 {
1562 UpdateVoteRule();
1563
1564 VoteInfo resultVoteInfo;
1565 VoteRange voteRange = { OLED_MIN_HZ, OLED_MAX_HZ };
1566 auto &[min, max] = voteRange;
1567
1568 bool voterGamesEffective = false;
1569 auto voterIter = voters_.begin();
1570 for (; voterIter != voters_.end(); ++voterIter) {
1571 if (ProcessRefreshRateVote(voterIter, resultVoteInfo, voteRange, voterGamesEffective)) {
1572 break;
1573 }
1574 }
1575 voterGamesEffective_ = voterGamesEffective;
1576 // update effective status
1577 if (voterIter != voters_.end()) {
1578 ++voterIter;
1579 for (; voterIter != voters_.end(); ++voterIter) {
1580 if (auto iter = voteRecord_.find(*voterIter); iter != voteRecord_.end()) {
1581 iter->second.second = false;
1582 }
1583 }
1584 }
1585 if (voteRecord_["VOTER_PACKAGES"].second || voteRecord_["VOTER_LTPO"].second) {
1586 voteRecord_["VOTER_SCENE"].second = true;
1587 }
1588 HGM_LOGD("Process: Strategy:%{public}s Screen:%{public}d Mode:%{public}d -- VoteResult:{%{public}d-%{public}d}",
1589 curScreenStrategyId_.c_str(), static_cast<int>(curScreenId_.load()), curRefreshRateMode_, min, max);
1590 SetResultVoteInfo(resultVoteInfo, min, max);
1591 ProcessAdaptiveSync(resultVoteInfo.voterName);
1592 return resultVoteInfo;
1593 }
1594
ChangePriority(uint32_t curScenePriority)1595 void HgmFrameRateManager::ChangePriority(uint32_t curScenePriority)
1596 {
1597 // restore
1598 voters_ = std::vector<std::string>(std::begin(VOTER_NAME), std::end(VOTER_NAME));
1599 switch (curScenePriority) {
1600 case VOTER_SCENE_PRIORITY_BEFORE_PACKAGES: {
1601 auto scenePos1 = find(voters_.begin(), voters_.end(), "VOTER_SCENE");
1602 voters_.erase(scenePos1);
1603 auto packagesPos1 = find(voters_.begin(), voters_.end(), "VOTER_PACKAGES");
1604 voters_.insert(packagesPos1, "VOTER_SCENE");
1605 break;
1606 }
1607 case VOTER_LTPO_PRIORITY_BEFORE_PACKAGES: {
1608 auto scenePos2 = find(voters_.begin(), voters_.end(), "VOTER_SCENE");
1609 voters_.erase(scenePos2);
1610 auto packagesPos2 = find(voters_.begin(), voters_.end(), "VOTER_PACKAGES");
1611 voters_.insert(packagesPos2, "VOTER_SCENE");
1612 auto ltpoPos2 = find(voters_.begin(), voters_.end(), "VOTER_LTPO");
1613 voters_.erase(ltpoPos2);
1614 auto packagesPos3 = find(voters_.begin(), voters_.end(), "VOTER_PACKAGES");
1615 voters_.insert(packagesPos3, "VOTER_LTPO");
1616 break;
1617 }
1618 default:
1619 break;
1620 }
1621 }
1622
UpdateVoteRule()1623 void HgmFrameRateManager::UpdateVoteRule()
1624 {
1625 // restore
1626 ChangePriority(DEFAULT_PRIORITY);
1627 multiAppStrategy_.SetDisableSafeVoteValue(false);
1628 // dynamic priority for scene
1629 if (sceneStack_.empty()) {
1630 // no active scene
1631 DeliverRefreshRateVote({"VOTER_SCENE"}, REMOVE_VOTE);
1632 return;
1633 }
1634 auto configData = HgmCore::Instance().GetPolicyConfigData();
1635 if (configData == nullptr) {
1636 return;
1637 }
1638 if (configData->screenConfigs_.count(curScreenStrategyId_) == 0 ||
1639 configData->screenConfigs_[curScreenStrategyId_].count(std::to_string(curRefreshRateMode_)) == 0) {
1640 return;
1641 }
1642 auto curScreenSceneList =
1643 configData->screenConfigs_[curScreenStrategyId_][std::to_string(curRefreshRateMode_)].sceneList;
1644 if (curScreenSceneList.empty()) {
1645 // no scene configed in cur screen
1646 return;
1647 }
1648
1649 std::string lastScene;
1650 auto scenePos = sceneStack_.rbegin();
1651 for (; scenePos != sceneStack_.rend(); scenePos++) {
1652 lastScene = (*scenePos).first;
1653 if (curScreenSceneList.count(lastScene) != 0) {
1654 break;
1655 }
1656 }
1657 if (scenePos == sceneStack_.rend()) {
1658 // no valid scene
1659 DeliverRefreshRateVote({"VOTER_SCENE"}, REMOVE_VOTE);
1660 return;
1661 }
1662 auto curSceneConfig = curScreenSceneList[lastScene];
1663 if (!XMLParser::IsNumber(curSceneConfig.priority) ||
1664 configData->strategyConfigs_.find(curSceneConfig.strategy) == configData->strategyConfigs_.end()) {
1665 return;
1666 }
1667 uint32_t curScenePriority = static_cast<uint32_t>(std::stoi(curSceneConfig.priority));
1668 uint32_t min = static_cast<uint32_t>(configData->strategyConfigs_[curSceneConfig.strategy].min);
1669 uint32_t max = static_cast<uint32_t>(configData->strategyConfigs_[curSceneConfig.strategy].max);
1670 HGM_LOGD("UpdateVoteRule: SceneName:%{public}s", lastScene.c_str());
1671 DeliverRefreshRateVote({"VOTER_SCENE", min, max, (*scenePos).second, lastScene}, ADD_VOTE);
1672
1673 ChangePriority(curScenePriority);
1674 multiAppStrategy_.SetDisableSafeVoteValue(curSceneConfig.disableSafeVote);
1675 }
1676
CleanVote(pid_t pid)1677 void HgmFrameRateManager::CleanVote(pid_t pid)
1678 {
1679 if (pid == DEFAULT_PID) {
1680 return;
1681 }
1682 multiAppStrategy_.CleanApp(pid);
1683 if (auto iter = cleanPidCallback_.find(pid); iter != cleanPidCallback_.end()) {
1684 for (auto cleanPidCallbackType : iter->second) {
1685 switch (cleanPidCallbackType) {
1686 case CleanPidCallbackType::LIGHT_FACTOR:
1687 HandleLightFactorStatus(DEFAULT_PID, LightFactorStatus::NORMAL_HIGH);
1688 break;
1689 case CleanPidCallbackType::PACKAGE_EVENT:
1690 HandlePackageEvent(DEFAULT_PID, {}); // handle empty pkg
1691 break;
1692 case CleanPidCallbackType::TOUCH_EVENT:
1693 HandleTouchEvent(DEFAULT_PID, TouchStatus::TOUCH_UP, LAST_TOUCH_CNT);
1694 break;
1695 case CleanPidCallbackType::GAMES:
1696 DeliverRefreshRateVote({"VOTER_GAMES"}, false);
1697 break;
1698 case CleanPidCallbackType::APP_STRATEGY_CONFIG_EVENT:
1699 HandleAppStrategyConfigEvent(DEFAULT_PID, "", {});
1700 break;
1701 case CleanPidCallbackType::PAGE_URL:
1702 CleanPageUrlVote(pid);
1703 break;
1704 default:
1705 break;
1706 }
1707 }
1708 iter->second.clear();
1709 }
1710
1711 if (pidRecord_.count(pid) == 0) {
1712 return;
1713 }
1714 HGM_LOGW("CleanVote: i am [%{public}d], i died, clean my votes please.", pid);
1715 pidRecord_.erase(pid);
1716
1717 for (auto& [voterName, voterInfo] : voteRecord_) {
1718 for (auto iter = voterInfo.first.begin(); iter != voterInfo.first.end();) {
1719 if (iter->pid == pid) {
1720 auto voter = iter->voterName;
1721 iter = voterInfo.first.erase(iter);
1722 MarkVoteChange(voter);
1723 break;
1724 } else {
1725 ++iter;
1726 }
1727 }
1728 }
1729 }
1730
SetResultVoteInfo(VoteInfo & voteInfo,uint32_t min,uint32_t max)1731 void HgmFrameRateManager::SetResultVoteInfo(VoteInfo& voteInfo, uint32_t min, uint32_t max)
1732 {
1733 voteInfo.min = min;
1734 voteInfo.max = max;
1735 if (voteInfo.voterName == "VOTER_PACKAGES" && touchManager_.GetState() != TouchState::IDLE_STATE) {
1736 voteInfo.extInfo = "ONTOUCH";
1737 }
1738 if (auto packages = multiAppStrategy_.GetPackages(); packages.size() > 0) {
1739 const auto& package = packages.front();
1740 const auto& pos = package.find(":");
1741 if (pos != package.npos) {
1742 voteInfo.bundleName = package.substr(0, pos);
1743 } else {
1744 voteInfo.bundleName = packages.front();
1745 }
1746 }
1747 }
1748
UpdateEnergyConsumptionConfig()1749 void HgmFrameRateManager::UpdateEnergyConsumptionConfig()
1750 {
1751 HgmEnergyConsumptionPolicy::Instance().SetEnergyConsumptionConfig(
1752 multiAppStrategy_.GetScreenSetting().animationPowerConfig);
1753 HgmEnergyConsumptionPolicy::Instance().SetUiEnergyConsumptionConfig(
1754 multiAppStrategy_.GetScreenSetting().uiPowerConfig);
1755 HgmEnergyConsumptionPolicy::Instance().SetRefreshRateMode(curRefreshRateMode_, curScreenStrategyId_);
1756 }
1757
ProcessVoteLog(const VoteInfo & curVoteInfo,bool isSkip)1758 void HgmFrameRateManager::ProcessVoteLog(const VoteInfo& curVoteInfo, bool isSkip)
1759 {
1760 RS_TRACE_NAME_FMT("Process voter:%s(pid:%d), value:[%d-%d]%s",
1761 curVoteInfo.voterName.c_str(), curVoteInfo.pid, curVoteInfo.min, curVoteInfo.max, isSkip ? " skip" : "");
1762 HGM_LOGD("Process: %{public}s(%{public}d):[%{public}d, %{public}d]%{public}s",
1763 curVoteInfo.voterName.c_str(), curVoteInfo.pid, curVoteInfo.min, curVoteInfo.max, isSkip ? " skip" : "");
1764 }
1765
UpdateUIFrameworkDirtyNodes(std::vector<std::weak_ptr<RSRenderNode>> & uiFwkDirtyNodes,uint64_t timestamp)1766 bool HgmFrameRateManager::UpdateUIFrameworkDirtyNodes(
1767 std::vector<std::weak_ptr<RSRenderNode>>& uiFwkDirtyNodes, uint64_t timestamp)
1768 {
1769 timestamp_ = timestamp;
1770 HgmEnergyConsumptionPolicy::Instance().CheckOnlyVideoCallExist();
1771 if (!voterTouchEffective_ || voterGamesEffective_) {
1772 surfaceData_.clear();
1773 return false;
1774 }
1775 std::unordered_map<std::string, pid_t> uiFrameworkDirtyNodeName;
1776 for (auto iter = uiFwkDirtyNodes.begin(); iter != uiFwkDirtyNodes.end();) {
1777 auto renderNode = iter->lock();
1778 if (renderNode == nullptr) {
1779 iter = uiFwkDirtyNodes.erase(iter);
1780 } else {
1781 if (renderNode->IsDirty()) {
1782 uiFrameworkDirtyNodeName[renderNode->GetNodeName()] = ExtractPid(renderNode->GetId());
1783 }
1784 ++iter;
1785 }
1786 }
1787
1788 if (uiFrameworkDirtyNodeName.empty() && surfaceData_.empty() &&
1789 (timestamp - lastPostIdleDetectorTaskTimestamp_) < BUFFER_IDLE_TIME_OUT) {
1790 return false;
1791 }
1792 HgmTaskHandleThread::Instance().PostTask([this, uiFrameworkDirtyNodeName, timestamp,
1793 surfaceData = surfaceData_] () {
1794 for (const auto &[surfaceName, pid, uiFwkType] : surfaceData) {
1795 if (multiAppStrategy_.CheckPidValid(pid, true)) {
1796 idleDetector_.UpdateSurfaceTime(surfaceName, timestamp, pid, uiFwkType);
1797 }
1798 }
1799 for (const auto& [uiFwkDirtyNodeName, pid] : uiFrameworkDirtyNodeName) {
1800 if (multiAppStrategy_.CheckPidValid(pid, true)) {
1801 idleDetector_.UpdateSurfaceTime(uiFwkDirtyNodeName, timestamp, pid, UIFWKType::FROM_UNKNOWN);
1802 }
1803 }
1804 });
1805 surfaceData_.clear();
1806 lastPostIdleDetectorTaskTimestamp_ = timestamp;
1807 return true;
1808 }
1809
HandleGameNode(const RSRenderNodeMap & nodeMap)1810 void HgmFrameRateManager::HandleGameNode(const RSRenderNodeMap& nodeMap)
1811 {
1812 bool isGameSelfNodeOnTree = false;
1813 std::string gameNodeName = GetGameNodeName();
1814 nodeMap.TraverseSurfaceNodes(
1815 [this, &isGameSelfNodeOnTree, &gameNodeName]
1816 (const std::shared_ptr<RSSurfaceRenderNode>& surfaceNode) mutable {
1817 if (surfaceNode->IsOnTheTree() && gameNodeName == surfaceNode->GetName()) {
1818 isGameSelfNodeOnTree = true;
1819 }
1820 }
1821 );
1822 RS_TRACE_NAME_FMT("HgmFrameRateManager::HandleGameNode, game node on tree: %d", isGameSelfNodeOnTree);
1823 isGameNodeOnTree_.store(isGameSelfNodeOnTree);
1824 }
1825
HandleAppStrategyConfigEvent(pid_t pid,const std::string & pkgName,const std::vector<std::pair<std::string,std::string>> & newConfig)1826 void HgmFrameRateManager::HandleAppStrategyConfigEvent(pid_t pid, const std::string& pkgName,
1827 const std::vector<std::pair<std::string, std::string>>& newConfig)
1828 {
1829 if (pid != DEFAULT_PID) {
1830 cleanPidCallback_[pid].insert(CleanPidCallbackType::APP_STRATEGY_CONFIG_EVENT);
1831 }
1832 multiAppStrategy_.SetAppStrategyConfig(pkgName, newConfig);
1833 }
1834
SetChangeGeneratorRateValid(bool valid)1835 void HgmFrameRateManager::SetChangeGeneratorRateValid(bool valid)
1836 {
1837 if (changeGeneratorRateValid_ == valid) {
1838 return;
1839 }
1840 changeGeneratorRateValid_ = valid;
1841 if (!valid) {
1842 changeGeneratorRateValidTimer_.Start();
1843 }
1844 }
1845
ProcessPageUrlVote(pid_t pid,std::string strategy,const bool isAddVoter)1846 void HgmFrameRateManager::ProcessPageUrlVote(pid_t pid, std::string strategy, const bool isAddVoter)
1847 {
1848 if (isAddVoter) {
1849 PolicyConfigData::StrategyConfig strategyConfig;
1850 if (multiAppStrategy_.GetStrategyConfig(strategy, strategyConfig) == EXEC_SUCCESS) {
1851 auto min = strategyConfig.min;
1852 auto max = strategyConfig.max;
1853 DeliverRefreshRateVote({"VOTER_PAGE_URL", min, max, pid}, ADD_VOTE);
1854 }
1855 if (pid != DEFAULT_PID) {
1856 cleanPidCallback_[pid].insert(CleanPidCallbackType::PAGE_URL);
1857 }
1858 } else {
1859 DeliverRefreshRateVote({"VOTER_PAGE_URL", 0, 0, pid}, REMOVE_VOTE);
1860 }
1861 }
1862
CleanPageUrlVote(pid_t pid)1863 void HgmFrameRateManager::CleanPageUrlVote(pid_t pid)
1864 {
1865 DeliverRefreshRateVote({"VOTER_PAGE_URL", 0, 0, pid}, REMOVE_VOTE);
1866 appPageUrlStrategy_.CleanPageUrlVote(pid);
1867 }
1868
HandlePageUrlEvent()1869 void HgmFrameRateManager::HandlePageUrlEvent()
1870 {
1871 auto screenSetting = multiAppStrategy_.GetScreenSetting();
1872 appPageUrlStrategy_.SetPageUrlConfig(screenSetting.pageUrlConfig);
1873 appPageUrlStrategy_.NotifyScreenSettingChange();
1874 }
1875
NotifyPageName(pid_t pid,const std::string & packageName,const std::string & pageName,bool isEnter)1876 void HgmFrameRateManager::NotifyPageName(pid_t pid, const std::string &packageName,
1877 const std::string &pageName, bool isEnter)
1878 {
1879 auto screenSetting = multiAppStrategy_.GetScreenSetting();
1880 appPageUrlStrategy_.SetPageUrlConfig(screenSetting.pageUrlConfig);
1881 appPageUrlStrategy_.NotifyPageName(pid, packageName, pageName, isEnter);
1882 }
1883
CheckRefreshRateChange(bool followRs,bool frameRateChanged,uint32_t refreshRate)1884 void HgmFrameRateManager::CheckRefreshRateChange(bool followRs, bool frameRateChanged, uint32_t refreshRate)
1885 {
1886 bool needChangeDssRefreshRate = currRefreshRate_.load() != refreshRate;
1887 // 当dvsync在连续延迟切帧阶段,使用dvsync内记录的刷新率判断是否变化
1888 CreateVSyncGenerator()->DVSyncRateChanged(controllerRate_, frameRateChanged);
1889 if (HgmCore::Instance().GetLtpoEnabled() && frameRateChanged) {
1890 HandleFrameRateChangeForLTPO(timestamp_.load(), followRs);
1891 if (needChangeDssRefreshRate && changeDssRefreshRateCb_ != nullptr) {
1892 changeDssRefreshRateCb_(curScreenId_.load(), refreshRate, true);
1893 }
1894 } else {
1895 std::lock_guard<std::mutex> lock(pendingMutex_);
1896 pendingRefreshRate_ = std::make_shared<uint32_t>(currRefreshRate_);
1897 if (needChangeDssRefreshRate && changeDssRefreshRateCb_ != nullptr) {
1898 changeDssRefreshRateCb_(curScreenId_.load(), refreshRate, true);
1899 }
1900 }
1901 }
1902
FrameRateReportTask(uint32_t leftRetryTimes)1903 void HgmFrameRateManager::FrameRateReportTask(uint32_t leftRetryTimes)
1904 {
1905 HgmTaskHandleThread::Instance().PostTask([this, leftRetryTimes] () {
1906 HGM_LOGI("FrameRateReportTask left retry: %{public}d", leftRetryTimes);
1907 if (leftRetryTimes == 1 || system::GetBoolParameter("bootevent.boot.completed", false)) {
1908 HGM_LOGI("FrameRateReportTask run.");
1909 schedulePreferredFpsChange_ = true;
1910 FrameRateReport();
1911 return;
1912 }
1913 if (leftRetryTimes > 1) {
1914 FrameRateReportTask(leftRetryTimes - 1);
1915 }
1916 }, FRAME_RATE_REPORT_DELAY_TIME);
1917 }
1918 } // namespace Rosen
1919 } // namespace OHOS
1920
1921