• 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 <limits>
22 #include "common/rs_common_hook.h"
23 #include "common/rs_optional_trace.h"
24 #include "common/rs_thread_handler.h"
25 #include "pipeline/rs_uni_render_judgement.h"
26 #include "hgm_config_callback_manager.h"
27 #include "hgm_core.h"
28 #include "hgm_energy_consumption_policy.h"
29 #include "hgm_event.h"
30 #include "hgm_hfbc_config.h"
31 #include "hgm_log.h"
32 #include "hgm_screen_info.h"
33 #include "parameters.h"
34 #include "rs_trace.h"
35 #include "sandbox_utils.h"
36 #include "frame_rate_report.h"
37 #include "hdi_device.h"
38 #include "pipeline/rs_surface_render_node.h"
39 #include "platform/common/rs_hisysevent.h"
40 #include "vsync_sampler.h"
41 
42 namespace OHOS {
43 namespace Rosen {
44 namespace {
45 constexpr int32_t IDLE_TIMER_EXPIRED = 200; // ms
46 constexpr int32_t CHANGE_GENERATOR_RATE_VALID_TIMEOUT = 20; // ms
47 constexpr int64_t UNI_RENDER_VSYNC_OFFSET = 5000000; // ns
48 constexpr int64_t UNI_RENDER_VSYNC_OFFSET_DELAY_MODE = -3300000; // ns
49 constexpr uint32_t REPORT_VOTER_INFO_LIMIT = 20;
50 constexpr int32_t LAST_TOUCH_CNT = 1;
51 
52 constexpr uint32_t FIRST_FRAME_TIME_OUT = 100; // 100ms
53 constexpr uint64_t BUFFER_IDLE_TIME_OUT = 200000000; // 200ms
54 constexpr long DRAG_SCENE_CHANGE_RATE_TIMEOUT = 100; // 100ms
55 const std::string UP_TIME_OUT_TASK_ID = "UP_TIME_OUT_TASK_ID";
56 const std::string S_UP_TIMEOUT_MS = "up_timeout_ms";
57 const std::string S_RS_IDLE_TIMEOUT_MS = "rs_idle_timeout_ms";
58 const std::string LOW_BRIGHT = "LowBright";
59 const std::string ANCO_LOW_BRIGHT = "AncoLowBright";
60 const std::string STYLUS_PEN = "StylusPen";
61 
62 constexpr int ADAPTIVE_SYNC_PROPERTY = 3;
63 constexpr int DISPLAY_SUCCESS = 1;
64 constexpr int32_t VIRTUAL_KEYBOARD_FINGERS_MIN_CNT = 8;
65 constexpr uint32_t FRAME_RATE_REPORT_MAX_RETRY_TIMES = 3;
66 constexpr uint32_t FRAME_RATE_REPORT_DELAY_TIME = 20000;
67 }
68 
HgmFrameRateManager()69 HgmFrameRateManager::HgmFrameRateManager()
70     : changeGeneratorRateValidTimer_("ChangeGeneratorRateValid",
71           std::chrono::milliseconds(CHANGE_GENERATOR_RATE_VALID_TIMEOUT), nullptr, [this]() {
72               changeGeneratorRateValid_ = true;
73               UpdateSoftVSync(false);
74           }),
__anon2ea4af7f0302() 75       rsFrameRateTimer_("rsFrameRate", std::chrono::milliseconds(IDLE_TIMER_EXPIRED), nullptr, [this]() {
76           if (rsFrameRateLinker_ != nullptr) {
77               rsFrameRateLinker_->SetExpectedRange({});
78               UpdateSoftVSync(false);
79           }
80       }),
81       frameVoter_(HgmFrameVoter(multiAppStrategy_))
82 {
__anon2ea4af7f0402(const std::string& voter) 83     frameVoter_.SetChangeRangeCallback([this](const std::string& voter) {
84         MarkVoteChange(voter);
85     });
86 }
87 
Init(sptr<VSyncController> rsController,sptr<VSyncController> appController,sptr<VSyncGenerator> vsyncGenerator,sptr<VSyncDistributor> appDistributor)88 void HgmFrameRateManager::Init(sptr<VSyncController> rsController,
89     sptr<VSyncController> appController, sptr<VSyncGenerator> vsyncGenerator, sptr<VSyncDistributor> appDistributor)
90 {
91     auto& hgmCore = HgmCore::Instance();
92     curRefreshRateMode_ = hgmCore.GetCurrentRefreshRateMode();
93     multiAppStrategy_.UpdateXmlConfigCache();
94     UpdateEnergyConsumptionConfig();
95 
96     InitConfig();
97     RegisterCoreCallbacksAndInitController(rsController, appController, vsyncGenerator, appDistributor);
98     multiAppStrategy_.RegisterStrategyChangeCallback([this](const PolicyConfigData::StrategyConfig& strategy) {
99         frameVoter_.SetTouchUpLTPOFirstDynamicMode(strategy.dynamicMode);
100         DeliverRefreshRateVote({"VOTER_PACKAGES", strategy.min, strategy.max}, ADD_VOTE);
101         touchManager_.SetUpTimeout(strategy.upTimeOut);
102         idleFps_ = strategy.idleFps;
103         HandleIdleEvent(true);
104     });
105     static std::once_flag createFlag;
106     std::call_once(createFlag, [this]() {
107         InitTouchManager();
108     });
109     hgmCore.SetLtpoConfig();
110     multiAppStrategy_.CalcVote();
111     appPageUrlStrategy_.RegisterPageUrlVoterCallback([this](pid_t pid,
112         std::string strategy, const bool isAddVoter) {
113         ProcessPageUrlVote(pid, strategy, isAddVoter);
114     });
115     HgmHfbcConfig& hfbcConfig = hgmCore.GetHfbcConfig();
116     hfbcConfig.HandleHfbcConfig({""});
117     FrameRateReportTask(FRAME_RATE_REPORT_MAX_RETRY_TIMES);
118     userDefine_.Init();
119 }
120 
InitConfig()121 void HgmFrameRateManager::InitConfig()
122 {
123     auto& hgmCore = HgmCore::Instance();
124     // hgm warning: get non active screenId in non-folding devices(from sceneboard)
125     auto screenList = hgmCore.GetScreenIds();
126     curScreenId_.store(screenList.empty() ? 0 : screenList.front());
127     auto& hgmScreenInfo = HgmScreenInfo::GetInstance();
128     isLtpo_ = hgmScreenInfo.IsLtpoType(hgmScreenInfo.GetScreenType(curScreenId_.load()));
129     std::string curScreenName = "screen" + std::to_string(curScreenId_.load()) + "_" + (isLtpo_ ? "LTPO" : "LTPS");
130     auto configData = hgmCore.GetPolicyConfigData();
131     if (configData != nullptr) {
132         auto iter = configData->screenStrategyConfigs_.find(curScreenName);
133         if (iter != configData->screenStrategyConfigs_.end()) {
134             curScreenStrategyId_ = iter->second;
135         }
136         if (curScreenStrategyId_.empty()) {
137             curScreenStrategyId_ = "LTPO-DEFAULT";
138         }
139         auto configVisitor = hgmCore.GetPolicyConfigVisitor();
140         if (configVisitor != nullptr) {
141             configVisitor->ChangeScreen(curScreenStrategyId_);
142         }
143         curScreenDefaultStrategyId_ = curScreenStrategyId_;
144         if (configData->xmlCompatibleMode_) {
145             curRefreshRateMode_ = configData->SettingModeId2XmlModeId(curRefreshRateMode_);
146         }
147         multiAppStrategy_.UpdateXmlConfigCache();
148         SetTimeoutParamsFromConfig(configData);
149         GetLowBrightVec(configData);
150         GetAncoLowBrightVec(configData);
151         GetStylusVec(configData);
152         UpdateEnergyConsumptionConfig();
153         multiAppStrategy_.CalcVote();
154         HandleIdleEvent(ADD_VOTE);
155         UpdateScreenExtStrategyConfig(configData->screenConfigs_);
156         softVSyncManager_.GetVRateMiniFPS(configData);
157     }
158 }
159 
RegisterCoreCallbacksAndInitController(sptr<VSyncController> rsController,sptr<VSyncController> appController,sptr<VSyncGenerator> vsyncGenerator,sptr<VSyncDistributor> appDistributor)160 void HgmFrameRateManager::RegisterCoreCallbacksAndInitController(sptr<VSyncController> rsController,
161     sptr<VSyncController> appController, sptr<VSyncGenerator> vsyncGenerator, sptr<VSyncDistributor> appDistributor)
162 {
163     if (rsController == nullptr || appController == nullptr) {
164         HGM_LOGE("HgmFrameRateManager::rsController or appController is nullptr");
165         return;
166     }
167     auto& hgmCore = HgmCore::Instance();
168     hgmCore.RegisterRefreshRateModeChangeCallback([rsController, appController](int32_t mode) {
169         if (HgmCore::Instance().IsLTPOSwitchOn()) {
170             rsController->SetPhaseOffset(0);
171             appController->SetPhaseOffset(0);
172             CreateVSyncGenerator()->SetVSyncMode(VSYNC_MODE_LTPO);
173         } else {
174             if (RSUniRenderJudgement::IsUniRender()) {
175                 int64_t offset = HgmCore::Instance().IsDelayMode() ?
176                     UNI_RENDER_VSYNC_OFFSET_DELAY_MODE : UNI_RENDER_VSYNC_OFFSET;
177                 rsController->SetPhaseOffset(offset);
178                 appController->SetPhaseOffset(offset);
179             }
180             CreateVSyncGenerator()->SetVSyncMode(VSYNC_MODE_LTPS);
181         }
182     });
183 
184     hgmCore.RegisterRefreshRateUpdateCallback([](int32_t refreshRate) {
185         HgmTaskHandleThread::Instance().PostTask([refreshRate]() {
186             HgmConfigCallbackManager::GetInstance()->SyncRefreshRateUpdateCallback(refreshRate);
187         });
188     });
189 
190     controller_ = std::make_shared<HgmVSyncGeneratorController>(rsController, appController, vsyncGenerator);
191     std::weak_ptr<HgmVSyncGeneratorController> weakController(controller_);
192     softVSyncManager_.InitController(weakController, appDistributor);
193 }
194 
SetTimeoutParamsFromConfig(const std::shared_ptr<PolicyConfigData> & configData)195 void HgmFrameRateManager::SetTimeoutParamsFromConfig(const std::shared_ptr<PolicyConfigData>& configData)
196 {
197     if (configData == nullptr || configData->timeoutStrategyConfig_.empty()) {
198         return;
199     }
200     int32_t upTimeoutMs = 0;
201     int32_t rsIdleTimeoutMs = 0;
202     if (configData->timeoutStrategyConfig_.find(S_UP_TIMEOUT_MS) != configData->timeoutStrategyConfig_.end() &&
203         XMLParser::IsNumber(configData->timeoutStrategyConfig_[S_UP_TIMEOUT_MS])) {
204         upTimeoutMs = static_cast<int32_t>(std::stoi(configData->timeoutStrategyConfig_[S_UP_TIMEOUT_MS]));
205     }
206     if (configData->timeoutStrategyConfig_.find(S_RS_IDLE_TIMEOUT_MS) != configData->timeoutStrategyConfig_.end() &&
207         XMLParser::IsNumber(configData->timeoutStrategyConfig_[S_RS_IDLE_TIMEOUT_MS])) {
208         rsIdleTimeoutMs = static_cast<int32_t>(std::stoi(configData->timeoutStrategyConfig_[S_RS_IDLE_TIMEOUT_MS]));
209     }
210     if (upTimeoutMs != 0) {
211         touchManager_.SetUpTimeout(upTimeoutMs);
212         HGM_LOGI("set upTimeout from Config");
213     }
214     if (rsIdleTimeoutMs != 0) {
215         touchManager_.SetRsIdleTimeout(rsIdleTimeoutMs);
216         HGM_LOGI("set rsIdleTimeout from Config");
217     }
218 }
219 
InitTouchManager()220 void HgmFrameRateManager::InitTouchManager()
221 {
222     auto updateTouchToMultiAppStrategy = [this](TouchState newState) {
223         HgmMultiAppStrategy::TouchInfo touchInfo = { .pkgName = touchManager_.GetPkgName(), .touchState = newState };
224         HgmEnergyConsumptionPolicy::Instance().SetTouchState(newState);
225         multiAppStrategy_.HandleTouchInfo(touchInfo);
226         UpdateSoftVSync(false);
227     };
228     touchManager_.RegisterEnterStateCallback(TouchState::DOWN_STATE,
229         [this, updateTouchToMultiAppStrategy](TouchState lastState, TouchState newState) {
230             needForceUpdateUniRender_ = true;
231             updateTouchToMultiAppStrategy(newState);
232             startCheck_.store(false);
233             voterTouchEffective_.store(true);
234             needForceUpdateUniRender_ = false;
235         });
236     touchManager_.RegisterEnterStateCallback(TouchState::IDLE_STATE,
237         [this, updateTouchToMultiAppStrategy](TouchState lastState, TouchState newState) {
238             SetSchedulerPreferredFps(OLED_60_HZ);
239             startCheck_.store(false);
240             softVSyncManager_.ChangePerformanceFirst(false);
241             updateTouchToMultiAppStrategy(newState);
242             voterTouchEffective_.store(false);
243         });
244     touchManager_.RegisterEnterStateCallback(TouchState::UP_STATE,
245         [this, updateTouchToMultiAppStrategy](TouchState lastState, TouchState newState) {
246             frameVoter_.SetIsTouchUpLTPOFirstPeriod(true);
247             HgmTaskHandleThread::Instance().PostEvent(UP_TIME_OUT_TASK_ID, [this]() {
248                 frameVoter_.SetIsTouchUpLTPOFirstPeriod(false);
249                 startCheck_.store(true);
250                 UpdateSoftVSync(false);
251             }, FIRST_FRAME_TIME_OUT);
252             updateTouchToMultiAppStrategy(newState);
253         });
254     touchManager_.RegisterExitStateCallback(TouchState::UP_STATE,
255         [this](TouchState lastState, TouchState newState) {
256             frameVoter_.SetIsTouchUpLTPOFirstPeriod(false);
257             HgmTaskHandleThread::Instance().RemoveEvent(UP_TIME_OUT_TASK_ID);
258             startCheck_.store(false);
259         });
260     RegisterUpTimeoutAndDownEvent();
261 }
262 
RegisterUpTimeoutAndDownEvent()263 void HgmFrameRateManager::RegisterUpTimeoutAndDownEvent()
264 {
265     touchManager_.RegisterEventCallback(TouchEvent::DOWN_EVENT, [this](TouchEvent event) {
266         SetSchedulerPreferredFps(OLED_120_HZ);
267         touchManager_.ChangeState(TouchState::DOWN_STATE);
268     });
269     touchManager_.RegisterExitStateCallback(TouchState::IDLE_STATE,
270         [this](TouchState lastState, TouchState newState) {
271             softVSyncManager_.ChangePerformanceFirst(true);
272         });
273 }
274 
ProcessPendingRefreshRate(uint64_t timestamp,int64_t vsyncId,uint32_t rsRate,bool isUiDvsyncOn)275 void HgmFrameRateManager::ProcessPendingRefreshRate(
276     uint64_t timestamp, int64_t vsyncId, uint32_t rsRate, bool isUiDvsyncOn)
277 {
278     std::lock_guard<std::mutex> lock(pendingMutex_);
279     // ensure that vsync switching takes effect in this frame
280     if (vsyncId < vsyncCountOfChangeGeneratorRate_) {
281         return;
282     }
283     auto& hgmCore = HgmCore::Instance();
284     hgmCore.SetTimestamp(timestamp);
285     if (pendingRefreshRate_ != nullptr) {
286         hgmCore.SetPendingConstraintRelativeTime(pendingConstraintRelativeTime_);
287         lastPendingConstraintRelativeTime_ = pendingConstraintRelativeTime_;
288         pendingConstraintRelativeTime_ = 0;
289 
290         hgmCore.SetPendingScreenRefreshRate(*pendingRefreshRate_);
291         lastPendingRefreshRate_ = *pendingRefreshRate_;
292         pendingRefreshRate_.reset();
293         RS_TRACE_NAME_FMT("ProcessHgmFrameRate pendingRefreshRate: %d", lastPendingRefreshRate_);
294     } else {
295         if (lastPendingConstraintRelativeTime_ != 0) {
296             hgmCore.SetPendingConstraintRelativeTime(lastPendingConstraintRelativeTime_);
297         }
298         if (lastPendingRefreshRate_ != 0) {
299             hgmCore.SetPendingScreenRefreshRate(lastPendingRefreshRate_);
300             RS_TRACE_NAME_FMT("ProcessHgmFrameRate pendingRefreshRate: %d", lastPendingRefreshRate_);
301         }
302     }
303 
304     if (hgmCore.GetLtpoEnabled() && isLtpo_ && rsRate > OLED_10_HZ &&
305         isUiDvsyncOn && GetCurScreenStrategyId().find("LTPO") != std::string::npos) {
306         hgmCore.SetPendingScreenRefreshRate(rsRate);
307         RS_TRACE_NAME_FMT("ProcessHgmFrameRate pendingRefreshRate: %d ui-dvsync", rsRate);
308     }
309     SetChangeGeneratorRateValid(true);
310 }
311 
UpdateSurfaceTime(const std::string & surfaceName,pid_t pid,UIFWKType uiFwkType)312 void HgmFrameRateManager::UpdateSurfaceTime(const std::string& surfaceName, pid_t pid, UIFWKType uiFwkType)
313 {
314     HgmEnergyConsumptionPolicy::Instance().StatisticsVideoCallBufferCount(pid, surfaceName);
315     if (!voterTouchEffective_) {
316         return;
317     }
318     surfaceData_.emplace_back(std::tuple<std::string, pid_t, UIFWKType>({surfaceName, pid, uiFwkType}));
319 }
320 
UpdateAppSupportedState()321 void HgmFrameRateManager::UpdateAppSupportedState()
322 {
323     PolicyConfigData::StrategyConfig config;
324     if (multiAppStrategy_.GetFocusAppStrategyConfig(config) == EXEC_SUCCESS &&
325         (config.dynamicMode == DynamicModeType::TOUCH_EXT_ENABLED ||
326          config.dynamicMode == DynamicModeType::TOUCH_EXT_ENABLED_LTPO_FIRST)) {
327         idleDetector_.SetAppSupportedState(true);
328     } else {
329         idleDetector_.SetAppSupportedState(false);
330     }
331     idleDetector_.SetBufferFpsMap(std::move(config.bufferFpsMap));
332 }
333 
SetAceAnimatorVote(const std::shared_ptr<RSRenderFrameRateLinker> & linker)334 void HgmFrameRateManager::SetAceAnimatorVote(const std::shared_ptr<RSRenderFrameRateLinker>& linker)
335 {
336     if (linker == nullptr) {
337         return;
338     }
339     if (linker->GetAceAnimatorExpectedFrameRate() >= 0) {
340         RS_TRACE_NAME_FMT("SetAceAnimatorVote PID = [%d]  linkerId = [%" PRIu64 "]  SetAceAnimatorIdleState[false] "
341             "AnimatorExpectedFrameRate = [%d]", ExtractPid(linker->GetId()), linker->GetId(),
342             linker->GetAceAnimatorExpectedFrameRate());
343         idleDetector_.SetAceAnimatorIdleState(false);
344         idleDetector_.UpdateAceAnimatorExpectedFrameRate(linker->GetAceAnimatorExpectedFrameRate());
345     }
346 }
347 
UpdateGuaranteedPlanVote(uint64_t timestamp)348 void HgmFrameRateManager::UpdateGuaranteedPlanVote(uint64_t timestamp)
349 {
350     if (!idleDetector_.GetAppSupportedState()) {
351         return;
352     }
353     idleDetector_.UpdateSurfaceState(timestamp);
354     RS_TRACE_NAME_FMT("HgmFrameRateManager:: TouchState = [%d]  SurFaceIdleState = [%d]  AceAnimatorIdleState = [%d]",
355         touchManager_.GetState(), idleDetector_.GetSurfaceIdleState(), idleDetector_.GetAceAnimatorIdleState());
356 
357     // After touch up, wait FIRST_FRAME_TIME_OUT ms
358     if (!startCheck_.load() || touchManager_.GetState() == TouchState::IDLE_STATE) {
359         lastTouchUpExpectFps_ = 0;
360         return;
361     }
362 
363     // remove the touch vote if third framework idle, otherwise vote the touch up fps
364     if (idleDetector_.GetSurfaceIdleState() && idleDetector_.GetAceAnimatorIdleState()) {
365         RS_TRACE_NAME_FMT("UpdateGuaranteedPlanVote:: Surface And Animator Idle, remove touch vote");
366         DeliverRefreshRateVote({"VOTER_TOUCH"}, REMOVE_VOTE);
367         lastTouchUpExpectFps_ = 0;
368     } else {
369         int32_t currTouchUpExpectedFPS = idleDetector_.GetTouchUpExpectedFPS();
370         if (currTouchUpExpectedFPS == lastTouchUpExpectFps_) {
371             return;
372         }
373 
374         lastTouchUpExpectFps_ = currTouchUpExpectedFPS;
375         HgmMultiAppStrategy::TouchInfo touchInfo = {
376             .touchState = TouchState::UP_STATE,
377             .upExpectFps = currTouchUpExpectedFPS,
378         };
379         multiAppStrategy_.HandleTouchInfo(touchInfo);
380     }
381 }
382 
ProcessLtpoVote(const FrameRateRange & finalRange)383 void HgmFrameRateManager::ProcessLtpoVote(const FrameRateRange& finalRange)
384 {
385     frameVoter_.SetDragScene(finalRange.type_ == DRAG_SCENE_FRAME_RATE_TYPE);
386     if (finalRange.IsValid()) {
387         auto refreshRate = UpdateFrameRateWithDelay(CalcRefreshRate(curScreenId_.load(), finalRange));
388         RS_TRACE_NAME_FMT("ProcessLtpoVote isDragScene_: [%d], refreshRate: [%d], lastLTPORefreshRate_: [%d]",
389             frameVoter_.IsDragScene(), refreshRate, lastLTPORefreshRate_);
390         DeliverRefreshRateVote(
391             {"VOTER_LTPO", refreshRate, refreshRate, DEFAULT_PID, finalRange.GetExtInfo()}, ADD_VOTE);
392     } else {
393         DeliverRefreshRateVote({.voterName = "VOTER_LTPO"}, REMOVE_VOTE);
394     }
395 }
396 
UpdateFrameRateWithDelay(uint32_t refreshRate)397 uint32_t HgmFrameRateManager::UpdateFrameRateWithDelay(uint32_t refreshRate)
398 {
399     if (!frameVoter_.IsDragScene()) {
400         return refreshRate;
401     }
402 
403     auto curTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()
404                     .time_since_epoch()).count();
405     if (refreshRate < lastLTPORefreshRate_ && curTime - lastLTPOVoteTime_ < DRAG_SCENE_CHANGE_RATE_TIMEOUT) {
406         return lastLTPORefreshRate_;
407     }
408 
409     lastLTPORefreshRate_ = refreshRate;
410     lastLTPOVoteTime_ = curTime;
411     return refreshRate;
412 }
413 
UniProcessDataForLtpo(uint64_t timestamp,std::shared_ptr<RSRenderFrameRateLinker> rsFrameRateLinker,const FrameRateLinkerMap & appFrameRateLinkers,const std::map<uint64_t,int> & vRatesMap)414 void HgmFrameRateManager::UniProcessDataForLtpo(uint64_t timestamp,
415     std::shared_ptr<RSRenderFrameRateLinker> rsFrameRateLinker, const FrameRateLinkerMap& appFrameRateLinkers,
416     const std::map<uint64_t, int>& vRatesMap)
417 {
418     RS_TRACE_FUNC();
419     timestamp_ = timestamp;
420     rsFrameRateLinker_ = rsFrameRateLinker;
421     appFrameRateLinkers_ = appFrameRateLinkers;
422 
423     softVSyncManager_.UniProcessDataForLtpo(vRatesMap, appFrameRateLinkers_);
424     UpdateSoftVSync(true);
425 }
426 
UpdateSoftVSync(bool followRs)427 void HgmFrameRateManager::UpdateSoftVSync(bool followRs)
428 {
429     if (rsFrameRateLinker_ == nullptr) {
430         return;
431     }
432     FrameRateRange finalRange = rsFrameRateLinker_->GetExpectedRange();
433     HgmEnergyConsumptionPolicy::Instance().GetAnimationIdleFps(finalRange);
434     rsFrameRateLinker_->SetExpectedRange(finalRange);
435     idleDetector_.SetAceAnimatorIdleState(true);
436     for (auto linker : appFrameRateLinkers_) {
437         if (linker.second == nullptr || !multiAppStrategy_.CheckPidValid(ExtractPid(linker.first))) {
438             continue;
439         }
440         SetAceAnimatorVote(linker.second);
441         auto expectedRange = linker.second->GetExpectedRange();
442         if (expectedRange.type_ == OHOS::Rosen::NATIVE_VSYNC_FRAME_RATE_TYPE &&
443             linker.second->NativeVSyncIsTimeOut()) {
444             continue;
445         }
446         if (!HgmEnergyConsumptionPolicy::Instance().GetUiIdleFps(expectedRange, ExtractPid(linker.first)) &&
447             (expectedRange.type_ & ANIMATION_STATE_FIRST_FRAME) != 0 &&
448             expectedRange.preferred_ < static_cast<int32_t>(currRefreshRate_)) {
449             expectedRange.Set(currRefreshRate_, currRefreshRate_, currRefreshRate_);
450         }
451         finalRange.Merge(expectedRange);
452     }
453     HgmEnergyConsumptionPolicy::Instance().PrintEnergyConsumptionLog(finalRange);
454     ProcessLtpoVote(finalRange);
455 
456     UpdateGuaranteedPlanVote(timestamp_);
457     idleDetector_.ResetAceAnimatorExpectedFrameRate();
458     // changeGenerator only once in a single vsync period
459     if (!changeGeneratorRateValid_.load()) {
460         return;
461     }
462     // max used here
463     finalRange = {lastVoteInfo_.max, lastVoteInfo_.max, lastVoteInfo_.max};
464     RS_TRACE_NAME_FMT("VoteRes: %s[%d, %d]", lastVoteInfo_.voterName.c_str(), lastVoteInfo_.min, lastVoteInfo_.max);
465     bool needChangeDssRefreshRate = false;
466     auto refreshRate = CalcRefreshRate(curScreenId_.load(), finalRange);
467     if (currRefreshRate_.load() != refreshRate) {
468         currRefreshRate_.store(refreshRate);
469         schedulePreferredFpsChange_ = true;
470         needChangeDssRefreshRate = true;
471         FrameRateReport();
472     }
473     bool frameRateChanged = softVSyncManager_.CollectFrameRateChange(finalRange,
474         rsFrameRateLinker_,
475         appFrameRateLinkers_,
476         currRefreshRate_);
477     CheckRefreshRateChange(followRs, frameRateChanged, refreshRate, needChangeDssRefreshRate);
478     ReportHiSysEvent(lastVoteInfo_);
479 }
480 
ReportHiSysEvent(const VoteInfo & frameRateVoteInfo)481 void HgmFrameRateManager::ReportHiSysEvent(const VoteInfo& frameRateVoteInfo)
482 {
483     if (frameRateVoteInfo.voterName.empty()) {
484         return;
485     }
486     bool needAdd = frameRateVoteInfoVec_.empty() || frameRateVoteInfoVec_.back().second != frameRateVoteInfo;
487     if (frameRateVoteInfoVec_.size() >= REPORT_VOTER_INFO_LIMIT) {
488         std::string msg;
489         for (auto& [timestamp, voteInfo] : frameRateVoteInfoVec_) {
490             msg += voteInfo.ToString(timestamp);
491         }
492         RS_TRACE_NAME("HgmFrameRateManager::ReportHiSysEvent HiSysEventWrite");
493         RSHiSysEvent::EventWrite(RSEventName::HGM_VOTER_INFO, RSEventType::RS_STATISTIC, "MSG", msg);
494         frameRateVoteInfoVec_.clear();
495     }
496     if (needAdd) {
497         auto currentTime = std::chrono::time_point_cast<std::chrono::milliseconds>(
498             std::chrono::system_clock::now()).time_since_epoch().count();
499         frameRateVoteInfoVec_.push_back({currentTime, frameRateVoteInfo});
500         HGM_LOGD("ReportHiSysEvent: %{public}s", frameRateVoteInfo.ToString(currentTime).c_str());
501     }
502 }
503 
FrameRateReport()504 void HgmFrameRateManager::FrameRateReport()
505 {
506     if (!schedulePreferredFpsChange_) {
507         return;
508     }
509     std::unordered_map<pid_t, uint32_t> rates;
510     rates[GetRealPid()] = currRefreshRate_;
511     if (curRefreshRateMode_ != HGM_REFRESHRATE_MODE_AUTO) {
512         rates[UNI_APP_PID] = currRefreshRate_;
513     } else if (schedulePreferredFps_ == OLED_60_HZ && currRefreshRate_ == OLED_60_HZ) {
514         rates[UNI_APP_PID] = OLED_60_HZ;
515     } else {
516         rates[UNI_APP_PID] = OLED_120_HZ;
517     }
518     HGM_LOGD("FrameRateReport: RS(%{public}d) = %{public}d, APP(%{public}d) = %{public}d",
519         GetRealPid(), rates[GetRealPid()], UNI_APP_PID, rates[UNI_APP_PID]);
520     RS_TRACE_NAME_FMT("FrameRateReport: RS(%d) = %d, APP(%d) = %d",
521         GetRealPid(), rates[GetRealPid()], UNI_APP_PID, rates[UNI_APP_PID]);
522     FRAME_TRACE::FrameRateReport::GetInstance().SendFrameRates(rates);
523     FRAME_TRACE::FrameRateReport::GetInstance().SendFrameRatesToRss(rates);
524     schedulePreferredFpsChange_ = false;
525 }
526 
HandleFrameRateChangeForLTPO(uint64_t timestamp,bool followRs,bool isNeedDvsyncDelay)527 void HgmFrameRateManager::HandleFrameRateChangeForLTPO(uint64_t timestamp, bool followRs, bool isNeedDvsyncDelay)
528 {
529     std::lock_guard<std::mutex> lock(pendingMutex_);
530     auto& hgmCore = HgmCore::Instance();
531     auto lastRefreshRate = hgmCore.GetPendingScreenRefreshRate();
532     uint64_t targetTime = 0;
533     // low refresh rate switch to high refresh rate immediately.
534     if (lastRefreshRate < OLED_60_HZ && currRefreshRate_ > lastRefreshRate) {
535         hgmCore.SetPendingScreenRefreshRate(currRefreshRate_);
536         pendingRefreshRate_ = std::make_shared<uint32_t>(currRefreshRate_);
537         hgmCore.SetScreenRefreshRateImme(currRefreshRate_);
538         if (hgmCore.IsLowRateToHighQuickEnabled() && controller_) {
539             targetTime = controller_->CalcVSyncQuickTriggerTime(timestamp, lastRefreshRate);
540             if (targetTime > timestamp && targetTime > 0) {
541                 pendingConstraintRelativeTime_ = targetTime - timestamp;
542             } else {
543                 pendingConstraintRelativeTime_ = 0;
544             }
545             hgmCore.SetPendingConstraintRelativeTime(pendingConstraintRelativeTime_);
546             pendingConstraintRelativeTime_ = 0;
547         }
548         // ChangeGeneratorRate delay 1 frame
549         if (!followRs) {
550             changeGeneratorRateValidTimer_.Start();
551             return;
552         }
553     }
554 
555     // Start of DVSync
556     auto controllerRate = softVSyncManager_.GetControllerRate();
557     int64_t delayTime = 0;
558     if (isNeedDvsyncDelay) {
559         delayTime = CreateVSyncGenerator()->SetCurrentRefreshRate(controllerRate, lastRefreshRate);
560     }
561     std::vector<std::pair<FrameRateLinkerId, uint32_t>> appChangeData = softVSyncManager_.GetSoftAppChangeData();
562     if (delayTime != 0) {
563         DVSyncTaskProcessor(delayTime, targetTime, appChangeData, controllerRate);
564     } else if (controller_) {
565         vsyncCountOfChangeGeneratorRate_ = controller_->ChangeGeneratorRate(
566             controllerRate, appChangeData, targetTime, isNeedUpdateAppOffset_);
567     }
568     // End of DVSync
569     isNeedUpdateAppOffset_ = false;
570     pendingRefreshRate_ = std::make_shared<uint32_t>(currRefreshRate_);
571     SetChangeGeneratorRateValid(false);
572 }
573 
DVSyncTaskProcessor(int64_t delayTime,uint64_t targetTime,std::vector<std::pair<FrameRateLinkerId,uint32_t>> appChangeData,int64_t controllerRate)574 void HgmFrameRateManager::DVSyncTaskProcessor(int64_t delayTime, uint64_t targetTime,
575     std::vector<std::pair<FrameRateLinkerId, uint32_t>> appChangeData, int64_t controllerRate)
576 {
577     bool needUpdate = isNeedUpdateAppOffset_;
578     RSTaskMessage::RSTask task = [this, targetTime, controllerRate, appChangeData, needUpdate]() {
579         if (controller_) {
580             vsyncCountOfChangeGeneratorRate_ = controller_->ChangeGeneratorRate(controllerRate,
581                 appChangeData, targetTime, needUpdate);
582         }
583         CreateVSyncGenerator()->SetCurrentRefreshRate(0, 0);
584     };
585     HgmTaskHandleThread::Instance().PostTask(task, delayTime);
586 }
587 
GetSupportedRefreshRates(const std::shared_ptr<PolicyConfigData> & configData,const std::string & modeKey,std::vector<uint32_t> & targetVec,bool handleAmbientEffect)588 void HgmFrameRateManager::GetSupportedRefreshRates(const std::shared_ptr<PolicyConfigData>& configData,
589     const std::string& modeKey, std::vector<uint32_t>& targetVec, bool handleAmbientEffect)
590 {
591     if (configData == nullptr) {
592         return;
593     }
594 
595     // Check if current screen strategy ID exists in supported mode configs
596     if (configData->supportedModeConfigs_.find(curScreenStrategyId_) == configData->supportedModeConfigs_.end()) {
597         return;
598     }
599     auto supportedModeConfig = configData->supportedModeConfigs_[curScreenStrategyId_];
600     auto iter = supportedModeConfig.find(modeKey);
601     if (iter == supportedModeConfig.end() || iter->second.empty()) {
602         return;
603     }
604 
605     // Get supported refresh rates from HgmCore
606     auto supportRefreshRateVec = HgmCore::Instance().GetScreenSupportedRefreshRates(curScreenId_.load());
607     targetVec.clear();
608 
609     // Match supported refresh rates
610     for (auto rate : iter->second) {
611         auto it = std::find(supportRefreshRateVec.begin(), supportRefreshRateVec.end(), rate);
612         if (it != supportRefreshRateVec.end()) {
613             targetVec.push_back(*it);
614         }
615     }
616 
617     // Handle ambient effect if needed
618     if (!targetVec.empty() && handleAmbientEffect) {
619         isAmbientEffect_ = true;
620         multiAppStrategy_.HandleLowAmbientStatus(isAmbientEffect_);
621     }
622 }
623 
GetLowBrightVec(const std::shared_ptr<PolicyConfigData> & configData)624 void HgmFrameRateManager::GetLowBrightVec(const std::shared_ptr<PolicyConfigData>& configData)
625 {
626     isAmbientEffect_ = false;
627     multiAppStrategy_.HandleLowAmbientStatus(isAmbientEffect_);
628     GetSupportedRefreshRates(configData, LOW_BRIGHT, lowBrightVec_, true);
629 }
630 
GetAncoLowBrightVec(const std::shared_ptr<PolicyConfigData> & configData)631 void HgmFrameRateManager::GetAncoLowBrightVec(const std::shared_ptr<PolicyConfigData>& configData)
632 {
633     GetSupportedRefreshRates(configData, ANCO_LOW_BRIGHT, ancoLowBrightVec_, false);
634 }
635 
GetStylusVec(const std::shared_ptr<PolicyConfigData> & configData)636 void HgmFrameRateManager::GetStylusVec(const std::shared_ptr<PolicyConfigData>& configData)
637 {
638     if (!configData) {
639         return;
640     }
641 
642     // refresh rate for stylus pen
643     if (configData->supportedModeConfigs_.find(curScreenStrategyId_) == configData->supportedModeConfigs_.end()) {
644         return;
645     }
646     auto supportedModeConfig = configData->supportedModeConfigs_[curScreenStrategyId_];
647     auto iter = supportedModeConfig.find(STYLUS_PEN);
648     if (iter == supportedModeConfig.end() || iter->second.empty()) {
649         return;
650     }
651     auto supportRefreshRateVec = HgmCore::Instance().GetScreenSupportedRefreshRates(curScreenId_.load());
652     stylusVec_.clear();
653     for (auto rate : iter->second) {
654         auto it = std::find(supportRefreshRateVec.begin(), supportRefreshRateVec.end(), rate);
655         if (it != supportRefreshRateVec.end()) {
656             stylusVec_.push_back(rate);
657         }
658     }
659 }
660 
CalcRefreshRate(const ScreenId id,const FrameRateRange & range) const661 uint32_t HgmFrameRateManager::CalcRefreshRate(const ScreenId id, const FrameRateRange& range) const
662 {
663     // Find current refreshRate by FrameRateRange. For example:
664     // 1. FrameRateRange[min, max, preferred] is [24, 48, 48], supported refreshRates
665     // of current screen are {30, 60, 90}, the result should be 30, not 60.
666     // 2. FrameRateRange[min, max, preferred] is [150, 150, 150], supported refreshRates
667     // of current screen are {30, 60, 90}, the result will be 90.
668     uint32_t refreshRate = currRefreshRate_;
669     std::vector<uint32_t> supportRefreshRateVec;
670     bool stylusFlag = (isStylusWakeUp_ && !stylusVec_.empty());
671     if ((isLtpo_ && isAmbientStatus_ == LightFactorStatus::NORMAL_LOW && isAmbientEffect_) ||
672         (!isLtpo_ && isAmbientEffect_ && isAmbientStatus_ != LightFactorStatus::HIGH_LEVEL)) {
673         RS_TRACE_NAME_FMT("Replace supported refresh rates from config");
674         if (CheckAncoVoterStatus()) {
675             supportRefreshRateVec = ancoLowBrightVec_;
676         } else {
677             supportRefreshRateVec = lowBrightVec_;
678         }
679     } else if (stylusFlag) {
680         supportRefreshRateVec = stylusVec_;
681         HGM_LOGD("stylusVec size = %{public}zu", stylusVec_.size());
682     } else {
683         supportRefreshRateVec = HgmCore::Instance().GetScreenSupportedRefreshRates(id);
684     }
685     if (supportRefreshRateVec.empty()) {
686         return refreshRate;
687     }
688     std::sort(supportRefreshRateVec.begin(), supportRefreshRateVec.end());
689     // In stylus mode, refresh is the first value of less than or equal to preferred in supportRefreshRateVec;
690     // supportRefreshRateVec is not empty when stylusFlag is true;
691     // The return value of upper_bound is bigger than preferred, so need subtract one;
692     if (stylusFlag) {
693         auto item = std::upper_bound(supportRefreshRateVec.begin(), supportRefreshRateVec.end(), range.preferred_);
694         if ((item - supportRefreshRateVec.begin()) > 0) {
695             item--;
696         }
697         return *item;
698     }
699     auto iter = std::lower_bound(supportRefreshRateVec.begin(), supportRefreshRateVec.end(), range.preferred_);
700     if (iter != supportRefreshRateVec.end()) {
701         refreshRate = *iter;
702         if (refreshRate > static_cast<uint32_t>(range.max_) &&
703             (iter - supportRefreshRateVec.begin()) > 0) {
704             iter--;
705             if (*iter >= static_cast<uint32_t>(range.min_) &&
706                 *iter <= static_cast<uint32_t>(range.max_)) {
707                 refreshRate = *iter;
708             }
709         }
710     } else {
711         refreshRate = supportRefreshRateVec.back();
712     }
713     return refreshRate;
714 }
715 
GetExpectedFrameRate(const RSPropertyUnit unit,float velocityPx,int32_t areaPx,int32_t lengthPx) const716 int32_t HgmFrameRateManager::GetExpectedFrameRate(const RSPropertyUnit unit, float velocityPx,
717     int32_t areaPx, int32_t lengthPx) const
718 {
719     static const std::map<RSPropertyUnit, std::string> typeMap = {
720         {RSPropertyUnit::PIXEL_POSITION, "translate"},
721         {RSPropertyUnit::PIXEL_SIZE, "scale"},
722         {RSPropertyUnit::RATIO_SCALE, "scale"},
723         {RSPropertyUnit::ANGLE_ROTATION, "rotation"}
724     };
725     if (auto it = typeMap.find(unit); it != typeMap.end()) {
726         return GetPreferredFps(it->second, PixelToMM(velocityPx), SqrPixelToSqrMM(areaPx), PixelToMM(lengthPx));
727     }
728     return 0;
729 }
730 
GetPreferredFps(const std::string & type,float velocityMM,float areaSqrMM,float lengthMM) const731 int32_t HgmFrameRateManager::GetPreferredFps(const std::string& type, float velocityMM,
732     float areaSqrMM, float lengthMM) const
733 {
734     auto& configData = HgmCore::Instance().GetPolicyConfigData();
735     if (!configData) {
736         return 0;
737     }
738     if (ROSEN_EQ(velocityMM, 0.f)) {
739         return 0;
740     }
741     const auto curScreenStrategyId = curScreenStrategyId_;
742     const std::string settingMode = std::to_string(curRefreshRateMode_);
743     if (configData->screenConfigs_.find(curScreenStrategyId) == configData->screenConfigs_.end() ||
744         configData->screenConfigs_[curScreenStrategyId].find(settingMode) ==
745         configData->screenConfigs_[curScreenStrategyId].end()) {
746         return 0;
747     }
748     auto& screenSetting = configData->screenConfigs_[curScreenStrategyId][settingMode];
749     auto matchFunc = [velocityMM](const auto& pair) {
750         return velocityMM >= pair.second.min && (velocityMM < pair.second.max || pair.second.max == -1);
751     };
752 
753     // find result if it's small size animation
754     bool needCheck = screenSetting.smallSizeArea > 0 && screenSetting.smallSizeLength > 0;
755     bool matchArea = areaSqrMM > 0 && areaSqrMM < screenSetting.smallSizeArea;
756     bool matchLength = lengthMM > 0 && lengthMM < screenSetting.smallSizeLength;
757     if (needCheck && matchArea && matchLength &&
758         screenSetting.smallSizeAnimationDynamicSettings.find(type) !=
759         screenSetting.smallSizeAnimationDynamicSettings.end()) {
760         auto& config = screenSetting.smallSizeAnimationDynamicSettings[type];
761         auto iter = std::find_if(config.begin(), config.end(), matchFunc);
762         if (iter != config.end()) {
763             RS_OPTIONAL_TRACE_NAME_FMT("GetPreferredFps (small size): type: %s, speed: %f, area: %f, length: %f,"
764                 "rate: %d", type.c_str(), velocityMM, areaSqrMM, lengthMM, iter->second.preferredFps);
765             return iter->second.preferredFps;
766         }
767     }
768 
769     // it's not a small size animation or current small size config don't cover it, find result in normal config
770     if (screenSetting.animationDynamicSettings.find(type) != screenSetting.animationDynamicSettings.end()) {
771         auto& config = screenSetting.animationDynamicSettings[type];
772         auto iter = std::find_if(config.begin(), config.end(), matchFunc);
773         if (iter != config.end()) {
774             RS_OPTIONAL_TRACE_NAME_FMT("GetPreferredFps: type: %s, speed: %f, area: %f, length: %f, rate: %d",
775                 type.c_str(), velocityMM, areaSqrMM, lengthMM, iter->second.preferredFps);
776             return iter->second.preferredFps;
777         }
778     }
779     return 0;
780 }
781 
782 template<typename T>
PixelToMM(T pixel)783 float HgmFrameRateManager::PixelToMM(T pixel)
784 {
785     auto& hgmCore = HgmCore::Instance();
786     sptr<HgmScreen> hgmScreen = hgmCore.GetScreen(hgmCore.GetActiveScreenId());
787     if (hgmScreen && hgmScreen->GetPpi() > 0.f) {
788         return pixel / hgmScreen->GetPpi() * INCH_2_MM;
789     }
790     return 0.f;
791 }
792 
793 template<typename T>
SqrPixelToSqrMM(T sqrPixel)794 float HgmFrameRateManager::SqrPixelToSqrMM(T sqrPixel)
795 {
796     return PixelToMM(PixelToMM(sqrPixel));
797 }
798 
HandleLightFactorStatus(pid_t pid,int32_t state)799 void HgmFrameRateManager::HandleLightFactorStatus(pid_t pid, int32_t state)
800 {
801     // based on the light determine whether allowed to reduce the screen refresh rate to avoid screen flicker
802     // 1.normal strategy : there are two states {NORMAL_HIGH, NORMAL_LOW}
803     // NORMAL_HIGH : allowed to reduce the screen refresh rate; NORMAL_LOW : not allowed
804     // 2.brightness level strategy : there are three states {LOW_LEVEL, MIDDLE_LEVEL, HIGH_LEVEL}
805     // LOW_LEVEL : not allowed to reduce the screen refresh rate, up to 90Hz;
806     // MIDDLE_LEVEL : allowed to reduce the screen refresh rate, up to 90Hz;
807     // HIGH_LEVEL : allowed to reduce the screen refresh rate, up to 120Hz
808     HGM_LOGI("HandleLightFactorStatus status:%{public}d", state);
809     if (pid != DEFAULT_PID) {
810         cleanPidCallback_[pid].insert(CleanPidCallbackType::LIGHT_FACTOR);
811     }
812     multiAppStrategy_.SetScreenType(isLtpo_);
813     multiAppStrategy_.HandleLightFactorStatus(state);
814     isAmbientStatus_ = state;
815     MarkVoteChange();
816 }
817 
HandlePackageEvent(pid_t pid,const std::vector<std::string> & packageList)818 void HgmFrameRateManager::HandlePackageEvent(pid_t pid, const std::vector<std::string>& packageList)
819 {
820     if (pid != DEFAULT_PID) {
821         cleanPidCallback_[pid].insert(CleanPidCallbackType::PACKAGE_EVENT);
822     }
823     // check whether to enable HFBC
824     HgmHfbcConfig& hfbcConfig = HgmCore::Instance().GetHfbcConfig();
825     hfbcConfig.HandleHfbcConfig(packageList);
826     multiAppStrategy_.HandlePkgsEvent(packageList);
827     HgmEventDistributor::Instance()->HandlePackageEvent(packageList);
828     MarkVoteChange("VOTER_SCENE");
829     UpdateAppSupportedState();
830 }
831 
HandleRefreshRateEvent(pid_t pid,const EventInfo & eventInfo)832 void HgmFrameRateManager::HandleRefreshRateEvent(pid_t pid, const EventInfo& eventInfo)
833 {
834     std::string eventName = eventInfo.eventName;
835     if (eventName == "VOTER_VIDEO_CALL") {
836         HgmEnergyConsumptionPolicy::Instance().SetVideoCallSceneInfo(eventInfo);
837         return;
838     } else if (eventName == "ENERGY_CONSUMPTION_ASSURANCE") {
839         HgmEnergyConsumptionPolicy::Instance().SetEnergyConsumptionAssuranceSceneInfo(eventInfo);
840         return;
841     }
842     auto voters = frameVoter_.GetVoters();
843     auto event = std::find(voters.begin(), voters.end(), eventName);
844     if (event == voters.end()) {
845         HGM_LOGW("HgmFrameRateManager:unknown event, eventName is %{public}s", eventName.c_str());
846         return;
847     }
848 
849     HGM_LOGD("%{public}s(%{public}d) %{public}s", eventName.c_str(), pid, eventInfo.description.c_str());
850     if (eventName == "VOTER_SCENE") {
851         HandleSceneEvent(pid, eventInfo);
852     } else if (eventName == "VOTER_VIRTUALDISPLAY") {
853         HandleVirtualDisplayEvent(pid, eventInfo);
854     } else if (eventName == "VOTER_GAMES") {
855         HandleGamesEvent(pid, eventInfo);
856     } else if (eventName == "VOTER_MULTISELFOWNEDSCREEN") {
857         HandleMultiSelfOwnedScreenEvent(pid, eventInfo);
858     } else {
859         DeliverRefreshRateVote({eventName, eventInfo.minRefreshRate, eventInfo.maxRefreshRate, pid},
860             eventInfo.eventStatus);
861     }
862 }
863 
HandleTouchEvent(pid_t pid,int32_t touchStatus,int32_t touchCnt)864 void HgmFrameRateManager::HandleTouchEvent(pid_t pid, int32_t touchStatus, int32_t touchCnt)
865 {
866     HGM_LOGD("HandleTouchEvent status:%{public}d", touchStatus);
867     if (frameVoter_.GetVoterGamesEffective() && touchManager_.GetState() == TouchState::DOWN_STATE) {
868         return;
869     }
870     if (frameVoter_.GetVoterGamesEffective() &&
871         (touchStatus ==  TOUCH_MOVE || touchStatus ==  TOUCH_BUTTON_DOWN || touchStatus ==  TOUCH_BUTTON_UP)) {
872         return;
873     }
874     HgmTaskHandleThread::Instance().PostTask([this, pid, touchStatus, touchCnt]() {
875         if (touchStatus ==  TOUCH_MOVE || touchStatus ==  TOUCH_BUTTON_DOWN || touchStatus ==  TOUCH_BUTTON_UP ||
876             touchStatus == AXIS_BEGIN || touchStatus == AXIS_UPDATE || touchStatus == AXIS_END) {
877             HandlePointerTask(pid, touchStatus, touchCnt);
878         } else {
879             HandleTouchTask(pid, touchStatus, touchCnt);
880         }
881     });
882 }
883 
HandleTouchTask(pid_t pid,int32_t touchStatus,int32_t touchCnt)884 void HgmFrameRateManager::HandleTouchTask(pid_t pid, int32_t touchStatus, int32_t touchCnt)
885 {
886     if (pid != DEFAULT_PID) {
887         cleanPidCallback_[pid].insert(CleanPidCallbackType::TOUCH_EVENT);
888     }
889 
890     if (touchStatus == TOUCH_DOWN || touchStatus == TOUCH_PULL_DOWN) {
891         HGM_LOGD("[touch manager] down");
892         PolicyConfigData::StrategyConfig strategyRes;
893         touchManager_.HandleTouchEvent(TouchEvent::DOWN_EVENT, "");
894     } else if (touchStatus == TOUCH_UP || touchStatus == TOUCH_PULL_UP) {
895         if (touchCnt != LAST_TOUCH_CNT) {
896             return;
897         }
898         auto voteRecord = frameVoter_.GetVoteRecord();
899         if (frameVoter_.GetVoterGamesEffective()) {
900             HGM_LOGD("[touch manager] keep down in games");
901             return;
902         }
903         if (touchCnt == LAST_TOUCH_CNT) {
904             HGM_LOGD("[touch manager] up");
905             touchManager_.HandleTouchEvent(TouchEvent::UP_EVENT, "");
906         }
907     } else if (touchStatus == TOUCH_CANCEL && touchCnt >= VIRTUAL_KEYBOARD_FINGERS_MIN_CNT) {
908         HGM_LOGD("[touch manager] cancel");
909         touchManager_.HandleTouchEvent(TouchEvent::UP_EVENT, "");
910     } else {
911         HGM_LOGD("[touch manager] other touch status not support");
912     }
913 }
914 
HandlePointerTask(pid_t pid,int32_t pointerStatus,int32_t pointerCnt)915 void HgmFrameRateManager::HandlePointerTask(pid_t pid, int32_t pointerStatus, int32_t pointerCnt)
916 {
917     if (pid != DEFAULT_PID) {
918         cleanPidCallback_[pid].insert(CleanPidCallbackType::TOUCH_EVENT);
919     }
920 
921     if (pointerStatus ==  TOUCH_MOVE || pointerStatus ==  TOUCH_BUTTON_DOWN || pointerStatus ==  TOUCH_BUTTON_UP) {
922         PolicyConfigData::StrategyConfig strategyRes;
923         if (multiAppStrategy_.GetFocusAppStrategyConfig(strategyRes) == EXEC_SUCCESS &&
924             strategyRes.pointerMode != PointerModeType::POINTER_DISENABLED) {
925             HGM_LOGD("[pointer manager] active");
926             pointerManager_.HandleTimerReset();
927             pointerManager_.HandlePointerEvent(PointerEvent::POINTER_ACTIVE_EVENT, "");
928         }
929     }
930 
931     if (pointerStatus ==  AXIS_BEGIN || pointerStatus == AXIS_UPDATE || pointerStatus == AXIS_END) {
932         PolicyConfigData::StrategyConfig strategyRes;
933         if (multiAppStrategy_.GetFocusAppStrategyConfig(strategyRes) == EXEC_SUCCESS &&
934             strategyRes.pointerMode != PointerModeType::POINTER_DISENABLED) {
935             HGM_LOGD("[pointer axis manager] active");
936             if (pointerStatus == AXIS_BEGIN) {
937                 pointerManager_.HandlePointerEvent(PointerEvent::POINTER_ACTIVE_EVENT, "");
938             } else {
939                 pointerManager_.HandleTimerReset();
940             }
941         }
942     }
943 }
944 
HandleDynamicModeEvent(bool enableDynamicModeEvent)945 void HgmFrameRateManager::HandleDynamicModeEvent(bool enableDynamicModeEvent)
946 {
947     HGM_LOGE("HandleDynamicModeEvent status:%{public}u", enableDynamicModeEvent);
948     HgmCore::Instance().SetEnableDynamicMode(enableDynamicModeEvent);
949     multiAppStrategy_.CalcVote();
950 }
951 
HandleIdleEvent(bool isIdle)952 void HgmFrameRateManager::HandleIdleEvent(bool isIdle)
953 {
954     if (isIdle) {
955         HGM_LOGD("HandleIdleEvent status:%{public}u", isIdle);
956         DeliverRefreshRateVote({"VOTER_IDLE", idleFps_, idleFps_}, ADD_VOTE);
957     } else {
958         DeliverRefreshRateVote({"VOTER_IDLE"}, REMOVE_VOTE);
959     }
960 }
961 
HandleRefreshRateMode(int32_t refreshRateMode)962 void HgmFrameRateManager::HandleRefreshRateMode(int32_t refreshRateMode)
963 {
964     HGM_LOGI("HandleRefreshRateMode curMode:%{public}d", refreshRateMode);
965     if (curRefreshRateMode_ == refreshRateMode) {
966         return;
967     }
968 
969     curRefreshRateMode_ = refreshRateMode;
970     DeliverRefreshRateVote({"VOTER_LTPO"}, REMOVE_VOTE);
971     multiAppStrategy_.UpdateXmlConfigCache();
972     UpdateEnergyConsumptionConfig();
973     HandlePageUrlEvent();
974     multiAppStrategy_.CalcVote();
975     HgmCore::Instance().SetLtpoConfig();
976     HgmConfigCallbackManager::GetInstance()->SyncHgmConfigChangeCallback();
977     UpdateAppSupportedState();  // sync app state config when RefreshRateMode changed
978 }
979 
HandleScreenPowerStatus(ScreenId id,ScreenPowerStatus status)980 void HgmFrameRateManager::HandleScreenPowerStatus(ScreenId id, ScreenPowerStatus status)
981 {
982     // hgm warning: strategy for screen off
983     HGM_LOGI("curScreen:%{public}d status:%{public}d", static_cast<int>(id), static_cast<int>(status));
984     if (status == ScreenPowerStatus::POWER_STATUS_ON) {
985         ReportHiSysEvent({.voterName = "SCREEN_POWER", .extInfo = "ON"});
986     } else if (status == ScreenPowerStatus::POWER_STATUS_SUSPEND) {
987         ReportHiSysEvent({.voterName = "SCREEN_POWER", .extInfo = "OFF"});
988     }
989     if (status != ScreenPowerStatus::POWER_STATUS_ON || curScreenId_.load() == id) {
990         return;
991     }
992 
993     auto& hgmCore = HgmCore::Instance();
994     auto screen = hgmCore.GetScreen(id);
995     if (!screen || !screen->GetSelfOwnedScreenFlag()) {
996         return;
997     }
998     if (hgmCore.GetMultiSelfOwnedScreenEnable()) {
999         return;
1000     }
1001 
1002     auto configData = hgmCore.GetPolicyConfigData();
1003     if (configData == nullptr) {
1004         return;
1005     }
1006     auto& hgmScreenInfo = HgmScreenInfo::GetInstance();
1007     auto isLtpo = hgmScreenInfo.IsLtpoType(hgmScreenInfo.GetScreenType(id));
1008     std::string curScreenName = "screen" + std::to_string(id) + "_" + (isLtpo ? "LTPO" : "LTPS");
1009 
1010     isLtpo_ = isLtpo;
1011     lastCurScreenId_.store(curScreenId_.load());
1012     curScreenId_.store(id);
1013     hgmCore.SetActiveScreenId(curScreenId_.load());
1014     HGM_LOGD("curScreen change:%{public}d", static_cast<int>(curScreenId_.load()));
1015 
1016     HandleScreenFrameRate(curScreenName);
1017     HandlePageUrlEvent();
1018 }
1019 
HandleScreenRectFrameRate(ScreenId id,const GraphicIRect & activeRect)1020 void HgmFrameRateManager::HandleScreenRectFrameRate(ScreenId id, const GraphicIRect& activeRect)
1021 {
1022     RS_TRACE_NAME_FMT("HgmFrameRateManager::HandleScreenRectFrameRate screenId:%d activeRect(%d, %d, %d, %d)",
1023         id, activeRect.x, activeRect.y, activeRect.w, activeRect.h);
1024     auto& hgmScreenInfo = HgmScreenInfo::GetInstance();
1025     auto& hgmCore = HgmCore::Instance();
1026     auto screen = hgmCore.GetScreen(id);
1027     if (!screen || !screen->GetSelfOwnedScreenFlag()) {
1028         return;
1029     }
1030 
1031     auto isLtpo = hgmScreenInfo.IsLtpoType(hgmScreenInfo.GetScreenType(id));
1032 
1033     std::string curScreenName = "screen" + std::to_string(id) + "_" + (isLtpo ? "LTPO" : "LTPS");
1034     curScreenName += "_" + std::to_string(activeRect.x);
1035     curScreenName += "_" + std::to_string(activeRect.y);
1036     curScreenName += "_" + std::to_string(activeRect.w);
1037     curScreenName += "_" + std::to_string(activeRect.h);
1038 
1039     HandleScreenFrameRate(curScreenName);
1040 }
1041 
HandleScreenFrameRate(std::string curScreenName)1042 void HgmFrameRateManager::HandleScreenFrameRate(std::string curScreenName)
1043 {
1044     auto& hgmCore = HgmCore::Instance();
1045     auto configData = hgmCore.GetPolicyConfigData();
1046     auto configVisitor = hgmCore.GetPolicyConfigVisitor();
1047     if (configData == nullptr || configVisitor == nullptr) {
1048         return;
1049     }
1050 
1051     if (configData->screenStrategyConfigs_.find(curScreenName) != configData->screenStrategyConfigs_.end()) {
1052         curScreenStrategyId_ = configData->screenStrategyConfigs_[curScreenName];
1053     } else {
1054         curScreenStrategyId_ = "LTPO-DEFAULT";
1055     }
1056     curScreenDefaultStrategyId_ = curScreenStrategyId_;
1057 
1058     curScreenStrategyId_ = GetCurScreenExtStrategyId();
1059     configVisitor->ChangeScreen(curScreenStrategyId_);
1060     UpdateScreenFrameRate();
1061 }
1062 
HandleScreenExtStrategyChange(bool status,const std::string & suffix)1063 void HgmFrameRateManager::HandleScreenExtStrategyChange(bool status, const std::string& suffix)
1064 {
1065     if (screenExtStrategyMap_.find(suffix) == screenExtStrategyMap_.end()) {
1066         return;
1067     }
1068     screenExtStrategyMap_[suffix].second = status;
1069 
1070     std::string curScreenStrategyId = GetCurScreenExtStrategyId();
1071     if (curScreenStrategyId != curScreenStrategyId_) {
1072         RS_TRACE_NAME_FMT("HgmFrameRateManager::HandleScreenExtStrategyChange type:%s, status:%d",
1073             curScreenStrategyId.c_str(), status);
1074         HGM_LOGI("HgmFrameRateManager::HandleScreenExtStrategyChange type:%{public}s, status:%{public}d",
1075             curScreenStrategyId.c_str(), status);
1076         curScreenStrategyId_ = curScreenStrategyId;
1077         auto configVisitor = HgmCore::Instance().GetPolicyConfigVisitor();
1078         if (configVisitor != nullptr) {
1079             configVisitor->ChangeScreen(curScreenStrategyId_);
1080         }
1081         UpdateScreenFrameRate();
1082     }
1083 }
1084 
GetCurScreenExtStrategyId()1085 std::string HgmFrameRateManager::GetCurScreenExtStrategyId()
1086 {
1087     auto& hgmCore = HgmCore::Instance();
1088     auto configData = hgmCore.GetPolicyConfigData();
1089     if (configData == nullptr) {
1090         return curScreenDefaultStrategyId_;
1091     }
1092 
1093     std::string suffix;
1094     for (const auto& [key, value] : screenExtStrategyMap_) {
1095         if (value.second && (screenExtStrategyMap_.find(suffix) == screenExtStrategyMap_.end() ||
1096             value.first > screenExtStrategyMap_[suffix].first)) {
1097             suffix = key;
1098         }
1099     }
1100     std::string curScreenStrategyId = curScreenDefaultStrategyId_ + suffix;
1101     if (configData->screenConfigs_.find(curScreenStrategyId) == configData->screenConfigs_.end()) {
1102         HGM_LOGE("HgmFrameRateManager::HandleScreenExtStrategyChange not support %{public}s config", suffix.c_str());
1103         return curScreenDefaultStrategyId_;
1104     }
1105     return curScreenStrategyId;
1106 }
1107 
UpdateScreenExtStrategyConfig(const PolicyConfigData::ScreenConfigMap & screenConfigs)1108 void HgmFrameRateManager::UpdateScreenExtStrategyConfig(const PolicyConfigData::ScreenConfigMap& screenConfigs)
1109 {
1110     std::unordered_set<std::string> screenConfigKeys;
1111     for (const auto& config : screenConfigs) {
1112         screenConfigKeys.insert(config.first);
1113     }
1114 
1115     for (auto it = screenExtStrategyMap_.begin(); it != screenExtStrategyMap_.end();) {
1116         if (std::find_if(screenConfigKeys.begin(), screenConfigKeys.end(),
1117             [&](const auto& item) { return item.find(it->first) != std::string::npos; }) == screenConfigKeys.end()) {
1118             it = screenExtStrategyMap_.erase(it);
1119         } else {
1120             ++it;
1121         }
1122     }
1123 }
1124 
UpdateScreenFrameRate()1125 void HgmFrameRateManager::UpdateScreenFrameRate()
1126 {
1127     auto& hgmCore = HgmCore::Instance();
1128     auto configData = hgmCore.GetPolicyConfigData();
1129     if (configData == nullptr) {
1130         return;
1131     }
1132 
1133     multiAppStrategy_.UpdateXmlConfigCache();
1134     GetLowBrightVec(configData);
1135     GetAncoLowBrightVec(configData);
1136     GetStylusVec(configData);
1137     UpdateEnergyConsumptionConfig();
1138 
1139     multiAppStrategy_.CalcVote();
1140     hgmCore.SetLtpoConfig();
1141     MarkVoteChange();
1142     HgmConfigCallbackManager::GetInstance()->SyncHgmConfigChangeCallback();
1143 
1144     // hgm warning: use !isLtpo_ instead after GetDisplaySupportedModes ready
1145     if (curScreenStrategyId_.find("LTPO") == std::string::npos) {
1146         DeliverRefreshRateVote({"VOTER_LTPO"}, REMOVE_VOTE);
1147     }
1148 
1149     if (!IsCurrentScreenSupportAS()) {
1150         isAdaptive_.store(SupportASStatus::NOT_SUPPORT);
1151     }
1152 }
1153 
HandleRsFrame()1154 void HgmFrameRateManager::HandleRsFrame()
1155 {
1156     touchManager_.HandleRsFrame();
1157     pointerManager_.HandleRsFrame();
1158 }
1159 
HandleStylusSceneEvent(const std::string & sceneName)1160 void HgmFrameRateManager::HandleStylusSceneEvent(const std::string& sceneName)
1161 {
1162     if (sceneName == "STYLUS_SLEEP" || sceneName == "STYLUS_NO_LINK") {
1163         isStylusWakeUp_ = false;
1164     } else if (sceneName == "STYLUS_WAKEUP") {
1165         isStylusWakeUp_ = true;
1166     }
1167 }
1168 
HandleSceneEvent(pid_t pid,const EventInfo & eventInfo)1169 void HgmFrameRateManager::HandleSceneEvent(pid_t pid, const EventInfo& eventInfo)
1170 {
1171     // control the list of supported frame rates for stylus pen, not control frame rate directly
1172     HandleStylusSceneEvent(eventInfo.description);
1173     HgmEventDistributor::Instance()->HandleSceneEvent(pid, eventInfo);
1174 }
1175 
HandleVirtualDisplayEvent(pid_t pid,EventInfo eventInfo)1176 void HgmFrameRateManager::HandleVirtualDisplayEvent(pid_t pid, EventInfo eventInfo)
1177 {
1178     std::string virtualDisplayName = eventInfo.description;
1179     auto configData = HgmCore::Instance().GetPolicyConfigData();
1180     if (configData == nullptr || !configData->virtualDisplaySwitch_) {
1181         // disable vote from virtual display in xml
1182         return;
1183     }
1184 
1185     auto virtualDisplayConfig = configData->virtualDisplayConfigs_;
1186     if (virtualDisplayConfig.count(virtualDisplayName) == 0 ||
1187         configData->strategyConfigs_.count(virtualDisplayConfig[virtualDisplayName]) == 0) {
1188         HGM_LOGW("HandleVirtualDisplayEvent:unknow virtual display [%{public}s]", virtualDisplayName.c_str());
1189         DeliverRefreshRateVote({"VOTER_VIRTUALDISPLAY", OLED_60_HZ, OLED_60_HZ, pid}, eventInfo.eventStatus);
1190     } else {
1191         auto curStrategy = configData->strategyConfigs_[virtualDisplayConfig[virtualDisplayName]];
1192         DeliverRefreshRateVote({"VOTER_VIRTUALDISPLAY", curStrategy.min, curStrategy.max, pid}, ADD_VOTE);
1193     }
1194 }
1195 
HandleGamesEvent(pid_t pid,EventInfo eventInfo)1196 void HgmFrameRateManager::HandleGamesEvent(pid_t pid, EventInfo eventInfo)
1197 {
1198     if (!eventInfo.eventStatus) {
1199         isGameSupportAS_ = SupportASStatus::NOT_SUPPORT;
1200         DeliverRefreshRateVote({"VOTER_GAMES"}, false);
1201         return;
1202     }
1203     auto [pkgName, gamePid, appType] = HgmMultiAppStrategy::AnalyzePkgParam(eventInfo.description);
1204     if (gamePid == DEFAULT_PID) {
1205         HGM_LOGE("unknow game pid: %{public}s, skip", eventInfo.description.c_str());
1206         return;
1207     }
1208     if (pid != DEFAULT_PID) {
1209         cleanPidCallback_[pid].insert(CleanPidCallbackType::GAMES);
1210     }
1211     PolicyConfigData::StrategyConfig config;
1212     if (multiAppStrategy_.GetAppStrategyConfig(pkgName, config) == EXEC_SUCCESS) {
1213         isGameSupportAS_ = config.supportAS;
1214         SetGameNodeName(multiAppStrategy_.GetGameNodeName(pkgName));
1215     } else {
1216         isGameSupportAS_ = SupportASStatus::NOT_SUPPORT;
1217         SetGameNodeName("");
1218     }
1219     DeliverRefreshRateVote(
1220         {"VOTER_GAMES", eventInfo.minRefreshRate, eventInfo.maxRefreshRate, gamePid}, eventInfo.eventStatus);
1221 }
1222 
HandleMultiSelfOwnedScreenEvent(pid_t pid,EventInfo eventInfo)1223 void HgmFrameRateManager::HandleMultiSelfOwnedScreenEvent(pid_t pid, EventInfo eventInfo)
1224 {
1225     HgmCore::Instance().SetMultiSelfOwnedScreenEnable(eventInfo.eventStatus);
1226     DeliverRefreshRateVote(
1227         {"VOTER_MULTISELFOWNEDSCREEN", eventInfo.minRefreshRate, eventInfo.maxRefreshRate, pid},
1228         eventInfo.eventStatus);
1229 }
1230 
MarkVoteChange(const std::string & voter)1231 void HgmFrameRateManager::MarkVoteChange(const std::string& voter)
1232 {
1233     auto voteRecord = frameVoter_.GetVoteRecord();
1234     if (auto iter = voteRecord.find(voter);
1235         voter != "" && (iter == voteRecord.end() || !iter->second.second) && !voterTouchEffective_) {
1236         return;
1237     }
1238 
1239     VoteInfo resultVoteInfo = ProcessRefreshRateVote();
1240     if (lastVoteInfo_ == resultVoteInfo) {
1241         if (isAmbientStatus_ < LightFactorStatus::LOW_LEVEL && !voterTouchEffective_) {
1242             return;
1243         }
1244     } else {
1245         lastVoteInfo_ = resultVoteInfo;
1246         HGM_LOGI("Strategy:%{public}s Screen:%{public}d Mode:%{public}d -- %{public}s", curScreenStrategyId_.c_str(),
1247             static_cast<int>(curScreenId_.load()), curRefreshRateMode_, resultVoteInfo.ToSimpleString().c_str());
1248     }
1249 
1250     // max used here
1251     FrameRateRange finalRange = {resultVoteInfo.max, resultVoteInfo.max, resultVoteInfo.max};
1252     auto refreshRate = CalcRefreshRate(curScreenId_.load(), finalRange);
1253     if (refreshRate == currRefreshRate_ && !voterTouchEffective_) {
1254         return;
1255     }
1256 
1257     CheckForceUpdateCallback(refreshRate);
1258 
1259     // changeGenerator only once in a single vsync period
1260     if (!changeGeneratorRateValid_.load()) {
1261         return;
1262     }
1263     bool needChangeDssRefreshRate = currRefreshRate_.load() != refreshRate;
1264     RS_TRACE_NAME_FMT("MarkVoteChange: %d %d", currRefreshRate_.load(), refreshRate);
1265     currRefreshRate_.store(refreshRate);
1266     schedulePreferredFpsChange_ = needChangeDssRefreshRate;
1267     FrameRateReport();
1268 
1269     bool frameRateChanged = false;
1270     if (rsFrameRateLinker_ != nullptr) {
1271         frameRateChanged = softVSyncManager_.CollectFrameRateChange(finalRange,
1272             rsFrameRateLinker_,
1273             appFrameRateLinkers_,
1274             currRefreshRate_);
1275     }
1276     CheckRefreshRateChange(false, frameRateChanged, refreshRate, needChangeDssRefreshRate);
1277     ReportHiSysEvent(resultVoteInfo);
1278 }
1279 
DeliverRefreshRateVote(const VoteInfo & voteInfo,bool eventStatus)1280 void HgmFrameRateManager::DeliverRefreshRateVote(const VoteInfo& voteInfo, bool eventStatus)
1281 {
1282     frameVoter_.DeliverVote(voteInfo, eventStatus);
1283 }
1284 
IsCurrentScreenSupportAS()1285 bool HgmFrameRateManager::IsCurrentScreenSupportAS()
1286 {
1287     auto hdiDevice = HdiDevice::GetInstance();
1288     if (hdiDevice == nullptr) {
1289         return false;
1290     }
1291     ScreenId id = HgmCore::Instance().GetActiveScreenId();
1292     ScreenPhysicalId screenId = static_cast<ScreenPhysicalId>(id);
1293     uint64_t propertyAS = 0;
1294     hdiDevice->GetDisplayProperty(screenId, ADAPTIVE_SYNC_PROPERTY, propertyAS);
1295     return propertyAS == DISPLAY_SUCCESS;
1296 }
1297 
ProcessAdaptiveSync(const std::string & voterName)1298 void HgmFrameRateManager::ProcessAdaptiveSync(const std::string& voterName)
1299 {
1300     // VOTER_GAMES wins, enter adaptive vsync mode
1301     bool isGameVoter = voterName == "VOTER_GAMES";
1302 
1303     if (!isGameVoter) {
1304         isAdaptive_.store(SupportASStatus::NOT_SUPPORT);
1305         return;
1306     }
1307 
1308     if (isGameSupportAS_ == SupportASStatus::GAME_SCENE_SKIP) {
1309         isAdaptive_.store(isGameSupportAS_);
1310         return;
1311     }
1312 
1313     if (!HgmCore::Instance().GetAdaptiveSyncEnabled()) {
1314         return;
1315     }
1316 
1317     if (isGameSupportAS_ != SupportASStatus::SUPPORT_AS) {
1318         HGM_LOGI("this game does not support adaptive sync mode");
1319         return;
1320     }
1321 
1322     if (!IsCurrentScreenSupportAS()) {
1323         HGM_LOGI("current screen not support adaptive sync mode");
1324         return;
1325     }
1326 
1327     HGM_LOGI("ProcessHgmFrameRate RSAdaptiveVsync change mode");
1328     RS_TRACE_BEGIN("ProcessHgmFrameRate RSAdaptiveVsync change mode");
1329     isAdaptive_.store(SupportASStatus::SUPPORT_AS);
1330     RS_TRACE_END();
1331 }
1332 
CheckAncoVoterStatus() const1333 bool HgmFrameRateManager::CheckAncoVoterStatus() const
1334 {
1335     if (isAmbientStatus_ != LightFactorStatus::NORMAL_LOW || !isLtpo_ ||
1336         !isAmbientEffect_ || ancoLowBrightVec_.empty()) {
1337         return false;
1338     }
1339     auto voteRecord = frameVoter_.GetVoteRecord();
1340     auto iter = voteRecord.find("VOTER_ANCO");
1341     if (iter == voteRecord.end() || iter->second.first.empty() || !iter->second.second) {
1342         return false;
1343     }
1344     return true;
1345 }
1346 
ProcessRefreshRateVote()1347 VoteInfo HgmFrameRateManager::ProcessRefreshRateVote()
1348 {
1349     auto [resultVoteInfo, voteRange] = frameVoter_.ProcessVote(curScreenStrategyId_,
1350         curScreenId_.load(), curRefreshRateMode_);
1351     auto [min, max] = voteRange;
1352     SetResultVoteInfo(resultVoteInfo, min, max);
1353     ProcessAdaptiveSync(resultVoteInfo.voterName);
1354 
1355     auto sampler = CreateVSyncSampler();
1356     sampler->SetAdaptive(isAdaptive_.load() == SupportASStatus::SUPPORT_AS);
1357     if (controller_ != nullptr) {
1358         controller_->ChangeAdaptiveStatus(isAdaptive_.load() == SupportASStatus::SUPPORT_AS);
1359     }
1360     return resultVoteInfo;
1361 }
1362 
CleanVote(pid_t pid)1363 void HgmFrameRateManager::CleanVote(pid_t pid)
1364 {
1365     if (pid == DEFAULT_PID) {
1366         return;
1367     }
1368     multiAppStrategy_.CleanApp(pid);
1369     if (auto iter = cleanPidCallback_.find(pid); iter != cleanPidCallback_.end()) {
1370         for (auto cleanPidCallbackType : iter->second) {
1371             switch (cleanPidCallbackType) {
1372                 case CleanPidCallbackType::LIGHT_FACTOR:
1373                     HandleLightFactorStatus(DEFAULT_PID, LightFactorStatus::NORMAL_HIGH);
1374                     break;
1375                 case CleanPidCallbackType::PACKAGE_EVENT:
1376                     HandlePackageEvent(DEFAULT_PID, {}); // handle empty pkg
1377                     break;
1378                 case CleanPidCallbackType::TOUCH_EVENT:
1379                     HandleTouchEvent(DEFAULT_PID, TouchStatus::TOUCH_UP, LAST_TOUCH_CNT);
1380                     break;
1381                 case CleanPidCallbackType::GAMES:
1382                     DeliverRefreshRateVote({"VOTER_GAMES"}, false);
1383                     break;
1384                 case CleanPidCallbackType::PAGE_URL:
1385                     CleanPageUrlVote(pid);
1386                     break;
1387                 case CleanPidCallbackType::APP_STRATEGY_CONFIG_EVENT:
1388                     HandleAppStrategyConfigEvent(DEFAULT_PID, "", {});
1389                     break;
1390                 default:
1391                     break;
1392             }
1393         }
1394         iter->second.clear();
1395     }
1396 
1397     softVSyncManager_.EraseGameRateDiscountMap(pid);
1398     frameVoter_.CleanVote(pid);
1399 }
1400 
SetResultVoteInfo(VoteInfo & voteInfo,uint32_t min,uint32_t max)1401 void HgmFrameRateManager::SetResultVoteInfo(VoteInfo& voteInfo, uint32_t min, uint32_t max)
1402 {
1403     voteInfo.min = min;
1404     voteInfo.max = max;
1405     if (voteInfo.voterName == "VOTER_PACKAGES" && touchManager_.GetState() != TouchState::IDLE_STATE) {
1406         voteInfo.extInfo = "ONTOUCH";
1407     }
1408     if (auto packages = multiAppStrategy_.GetPackages(); packages.size() > 0) {
1409         const auto& package = packages.front();
1410         const auto& pos = package.find(":");
1411         if (pos != package.npos) {
1412             voteInfo.bundleName = package.substr(0, pos);
1413         } else {
1414             voteInfo.bundleName = packages.front();
1415         }
1416     }
1417 }
1418 
UpdateEnergyConsumptionConfig()1419 void HgmFrameRateManager::UpdateEnergyConsumptionConfig()
1420 {
1421     HgmEnergyConsumptionPolicy::Instance().SetEnergyConsumptionConfig(
1422         multiAppStrategy_.GetScreenSetting().animationPowerConfig);
1423     HgmEnergyConsumptionPolicy::Instance().SetUiEnergyConsumptionConfig(
1424         multiAppStrategy_.GetScreenSetting().uiPowerConfig);
1425     HgmEnergyConsumptionPolicy::Instance().SetRefreshRateMode(curRefreshRateMode_, curScreenStrategyId_);
1426 }
1427 
UpdateUIFrameworkDirtyNodes(std::vector<std::weak_ptr<RSRenderNode>> & uiFwkDirtyNodes,uint64_t timestamp)1428 bool HgmFrameRateManager::UpdateUIFrameworkDirtyNodes(
1429     std::vector<std::weak_ptr<RSRenderNode>>& uiFwkDirtyNodes, uint64_t timestamp)
1430 {
1431     timestamp_ = timestamp;
1432     HgmEnergyConsumptionPolicy::Instance().CheckOnlyVideoCallExist();
1433     if (!voterTouchEffective_ || frameVoter_.GetVoterGamesEffective()) {
1434         surfaceData_.clear();
1435         return false;
1436     }
1437     std::unordered_map<std::string, pid_t> uiFrameworkDirtyNodeName;
1438     for (auto iter = uiFwkDirtyNodes.begin(); iter != uiFwkDirtyNodes.end();) {
1439         auto renderNode = iter->lock();
1440         if (renderNode == nullptr) {
1441             iter = uiFwkDirtyNodes.erase(iter);
1442         } else {
1443             if (renderNode->IsDirty()) {
1444                 uiFrameworkDirtyNodeName[renderNode->GetNodeName()] = ExtractPid(renderNode->GetId());
1445             }
1446             ++iter;
1447         }
1448     }
1449 
1450     if (uiFrameworkDirtyNodeName.empty() && surfaceData_.empty() &&
1451         (timestamp - lastPostIdleDetectorTaskTimestamp_) < BUFFER_IDLE_TIME_OUT) {
1452         return false;
1453     }
1454     HgmTaskHandleThread::Instance().PostTask([this, uiFrameworkDirtyNodeName, timestamp,
1455                                               surfaceData = surfaceData_]() {
1456         for (const auto& [surfaceName, pid, uiFwkType] : surfaceData) {
1457             if (multiAppStrategy_.CheckPidValid(pid, true)) {
1458                 idleDetector_.UpdateSurfaceTime(surfaceName, timestamp, pid, uiFwkType);
1459             }
1460         }
1461         for (const auto& [uiFwkDirtyNodeName, pid] : uiFrameworkDirtyNodeName) {
1462             if (multiAppStrategy_.CheckPidValid(pid, true)) {
1463                 idleDetector_.UpdateSurfaceTime(uiFwkDirtyNodeName, timestamp, pid, UIFWKType::FROM_UNKNOWN);
1464             }
1465         }
1466     });
1467     surfaceData_.clear();
1468     lastPostIdleDetectorTaskTimestamp_ = timestamp;
1469     return true;
1470 }
1471 
HandleGameNode(const RSRenderNodeMap & nodeMap)1472 bool HgmFrameRateManager::HandleGameNode(const RSRenderNodeMap& nodeMap)
1473 {
1474     bool isGameSelfNodeOnTree = false;
1475     bool isOtherSelfNodeOnTree = false;
1476     std::string gameNodeName = GetGameNodeName();
1477     nodeMap.TraverseSurfaceNodes(
1478         [this, &isGameSelfNodeOnTree, &gameNodeName, &isOtherSelfNodeOnTree]
1479         (const std::shared_ptr<RSSurfaceRenderNode>& surfaceNode) mutable {
1480             if (surfaceNode == nullptr) {
1481                 return;
1482             }
1483             if (surfaceNode->IsOnTheTree() &&
1484                 surfaceNode->GetSurfaceNodeType() == RSSurfaceNodeType::SELF_DRAWING_NODE) {
1485                 if (gameNodeName == surfaceNode->GetName()) {
1486                     isGameSelfNodeOnTree = true;
1487                 } else {
1488                     isOtherSelfNodeOnTree = true;
1489                 }
1490             }
1491         });
1492     RS_TRACE_NAME_FMT("HgmFrameRateManager::HandleGameNode, game node on tree: %d, other node no tree: %d",
1493                       isGameSelfNodeOnTree, isOtherSelfNodeOnTree);
1494     isGameNodeOnTree_.store(isGameSelfNodeOnTree && !isOtherSelfNodeOnTree);
1495     return isGameSelfNodeOnTree && !isOtherSelfNodeOnTree;
1496 }
1497 
HandleAppStrategyConfigEvent(pid_t pid,const std::string & pkgName,const std::vector<std::pair<std::string,std::string>> & newConfig)1498 void HgmFrameRateManager::HandleAppStrategyConfigEvent(pid_t pid, const std::string& pkgName,
1499     const std::vector<std::pair<std::string, std::string>>& newConfig)
1500 {
1501     if (pid != DEFAULT_PID) {
1502         cleanPidCallback_[pid].insert(CleanPidCallbackType::APP_STRATEGY_CONFIG_EVENT);
1503     }
1504     HgmEventDistributor::Instance()->HandleAppStrategyConfigEvent(pkgName, newConfig);
1505 }
1506 
SetChangeGeneratorRateValid(bool valid)1507 void HgmFrameRateManager::SetChangeGeneratorRateValid(bool valid)
1508 {
1509     if (changeGeneratorRateValid_ == valid) {
1510         return;
1511     }
1512     changeGeneratorRateValid_ = valid;
1513     if (!valid) {
1514         changeGeneratorRateValidTimer_.Start();
1515     }
1516 }
1517 
ProcessPageUrlVote(pid_t pid,std::string strategy,const bool isAddVoter)1518 void HgmFrameRateManager::ProcessPageUrlVote(pid_t pid, std::string strategy, const bool isAddVoter)
1519 {
1520     if (isAddVoter) {
1521         PolicyConfigData::StrategyConfig strategyConfig;
1522         if (multiAppStrategy_.GetStrategyConfig(strategy, strategyConfig) == EXEC_SUCCESS) {
1523             auto min = strategyConfig.min;
1524             auto max = strategyConfig.max;
1525             DeliverRefreshRateVote({"VOTER_PAGE_URL", min, max, pid}, ADD_VOTE);
1526         }
1527         if (pid != DEFAULT_PID) {
1528             cleanPidCallback_[pid].insert(CleanPidCallbackType::PAGE_URL);
1529         }
1530     } else {
1531         DeliverRefreshRateVote({"VOTER_PAGE_URL", 0, 0, pid}, REMOVE_VOTE);
1532     }
1533 }
1534 
CleanPageUrlVote(pid_t pid)1535 void HgmFrameRateManager::CleanPageUrlVote(pid_t pid)
1536 {
1537     DeliverRefreshRateVote({"VOTER_PAGE_URL", 0, 0, pid}, REMOVE_VOTE);
1538     appPageUrlStrategy_.CleanPageUrlVote(pid);
1539 }
1540 
HandlePageUrlEvent()1541 void HgmFrameRateManager::HandlePageUrlEvent()
1542 {
1543     auto screenSetting = multiAppStrategy_.GetScreenSetting();
1544     appPageUrlStrategy_.SetPageUrlConfig(screenSetting.pageUrlConfig);
1545     appPageUrlStrategy_.NotifyScreenSettingChange();
1546 }
1547 
NotifyPageName(pid_t pid,const std::string & packageName,const std::string & pageName,bool isEnter)1548 void HgmFrameRateManager::NotifyPageName(pid_t pid, const std::string& packageName,
1549     const std::string& pageName, bool isEnter)
1550 {
1551     auto screenSetting = multiAppStrategy_.GetScreenSetting();
1552     appPageUrlStrategy_.SetPageUrlConfig(screenSetting.pageUrlConfig);
1553     appPageUrlStrategy_.NotifyPageName(pid, packageName, pageName, isEnter);
1554 }
1555 
CheckNeedUpdateAppOffset(uint32_t refreshRate,uint32_t controllerRate)1556 void HgmFrameRateManager::CheckNeedUpdateAppOffset(uint32_t refreshRate, uint32_t controllerRate)
1557 {
1558     if (controller_ == nullptr || refreshRate > OLED_60_HZ || isNeedUpdateAppOffset_ ||
1559         !controller_->CheckNeedUpdateAppOffsetRefreshRate(controllerRate)) {
1560         return;
1561     }
1562     if (touchManager_.GetState() == TouchState::IDLE_STATE) {
1563         isNeedUpdateAppOffset_ = true;
1564         return;
1565     }
1566     auto voteRecord = frameVoter_.GetVoteRecord();
1567     if (auto iter = voteRecord.find("VOTER_THERMAL");
1568         iter != voteRecord.end() && !iter->second.first.empty() &&
1569         iter->second.first.back().max > 0 && iter->second.first.back().max <= OLED_60_HZ) {
1570         isNeedUpdateAppOffset_ = true;
1571         return;
1572     }
1573 }
1574 
CheckRefreshRateChange(bool followRs,bool frameRateChanged,uint32_t refreshRate,bool needChangeDssRefreshRate)1575 void HgmFrameRateManager::CheckRefreshRateChange(
1576     bool followRs, bool frameRateChanged, uint32_t refreshRate, bool needChangeDssRefreshRate)
1577 {
1578     // 当dvsync在连续延迟切帧阶段,使用dvsync内记录的刷新率判断是否变化
1579     auto controllerRate = softVSyncManager_.GetControllerRate();
1580     bool isNeedDvsyncDelay = CreateVSyncGenerator()->DVSyncRateChanged(controllerRate,
1581         frameRateChanged, needChangeDssRefreshRate);
1582     bool appOffsetChange = false;
1583     if (controller_ != nullptr) {
1584         CheckNeedUpdateAppOffset(refreshRate, controllerRate);
1585         appOffsetChange = isNeedUpdateAppOffset_ && controller_->GetPulseNum() != 0;
1586     }
1587     if (HgmCore::Instance().GetLtpoEnabled() &&
1588         (frameRateChanged || (appOffsetChange && !CreateVSyncGenerator()->IsUiDvsyncOn()))) {
1589         HandleFrameRateChangeForLTPO(timestamp_.load(), followRs, isNeedDvsyncDelay);
1590         if (needChangeDssRefreshRate && forceUpdateCallback_ != nullptr) {
1591             forceUpdateCallback_(false, true);
1592         }
1593     } else {
1594         std::lock_guard<std::mutex> lock(pendingMutex_);
1595         pendingRefreshRate_ = std::make_shared<uint32_t>(currRefreshRate_);
1596         if (needChangeDssRefreshRate && forceUpdateCallback_ != nullptr) {
1597             forceUpdateCallback_(false, true);
1598         }
1599         if (frameRateChanged) {
1600             softVSyncManager_.SetQosVSyncRate(currRefreshRate_, appFrameRateLinkers_);
1601         }
1602     }
1603     if (HgmCore::Instance().GetLtpoEnabled() && appOffsetChange && isNeedUpdateAppOffset_) {
1604         HgmCore::Instance().SetHgmTaskFlag(true);
1605     }
1606     isNeedUpdateAppOffset_ = false;
1607 }
1608 
FrameRateReportTask(uint32_t leftRetryTimes)1609 void HgmFrameRateManager::FrameRateReportTask(uint32_t leftRetryTimes)
1610 {
1611     HgmTaskHandleThread::Instance().PostTask(
1612         [this, leftRetryTimes]() {
1613             if (leftRetryTimes == 1 || system::GetBoolParameter("bootevent.boot.completed", false)) {
1614                 HGM_LOGI("FrameRateReportTask run and left retry:%{public}d", leftRetryTimes);
1615                 schedulePreferredFpsChange_ = true;
1616                 FrameRateReport();
1617                 return;
1618             }
1619             if (leftRetryTimes > 1) {
1620                 FrameRateReportTask(leftRetryTimes - 1);
1621             }
1622         },
1623         FRAME_RATE_REPORT_DELAY_TIME);
1624 }
1625 
SetVsyncRateDiscountLTPO(const std::vector<uint64_t> & linkerIds,uint32_t rateDiscount)1626 bool HgmFrameRateManager::SetVsyncRateDiscountLTPO(const std::vector<uint64_t>& linkerIds, uint32_t rateDiscount)
1627 {
1628     HgmTaskHandleThread::Instance().PostTask([this, linkerIds, rateDiscount]() {
1629         softVSyncManager_.SetVsyncRateDiscountLTPO(linkerIds, rateDiscount);
1630         UpdateSoftVSync(false);
1631     });
1632     return true;
1633 }
1634 } // namespace Rosen
1635 } // namespace OHOS
1636 
1637