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