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