• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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_core.h"
17 
18 #include <algorithm>
19 #include <cstddef>
20 #include <cstdint>
21 #include <string>
22 #include <unistd.h>
23 
24 #include "hgm_frame_rate_manager.h"
25 #include "hgm_config_callback_manager.h"
26 #include "hgm_log.h"
27 #include "vsync_generator.h"
28 #include "platform/common/rs_system_properties.h"
29 #include "parameters.h"
30 #include "frame_rate_report.h"
31 #include "sandbox_utils.h"
32 
33 namespace OHOS::Rosen {
34 static std::map<uint32_t, int64_t> IDEAL_PERIOD = {
35     { 144, 6944444 },
36     { 120, 8333333 },
37     { 90, 11111111 },
38     { 80, 12500000 },
39     { 72, 13888888 },
40     { 60, 16666666 },
41     { 48, 20833333 },
42     { 45, 22222222 },
43     { 40, 25000000 },
44     { 36, 27777777 },
45     { 30, 33333333 },
46     { 24, 41666666 },
47     { 20, 50000000 },
48     { 15, 66666666 },
49     { 10, 100000000 },
50 };
51 
Instance()52 HgmCore& HgmCore::Instance()
53 {
54     static HgmCore instance;
55     static std::mutex mtx;
56     if (instance.IsInit()) {
57         return instance;
58     }
59 
60     std::lock_guard<std::mutex> lock(mtx);
61     if (instance.IsInit()) {
62         return instance;
63     }
64 
65     if (instance.Init() == false) {
66         HGM_LOGI("HgmCore initialization failed");
67     }
68 
69     return instance;
70 }
71 
HgmCore()72 HgmCore::HgmCore()
73 {
74     HGM_LOGI("Construction of Hgmcore");
75 }
76 
Init()77 bool HgmCore::Init()
78 {
79     if (!isEnabled_) {
80         HGM_LOGE("HgmCore Hgm is desactivated");
81         return false;
82     }
83 
84     if (InitXmlConfig() != EXEC_SUCCESS) {
85         HGM_LOGE("HgmCore falied to parse");
86         return false;
87     }
88 
89     // ensure that frameRateManager init after XML parsed.
90     hgmFrameRateMgr_ = std::make_unique<HgmFrameRateManager>();
91 
92     auto newRateMode = static_cast<int32_t>(RSSystemProperties::GetHgmRefreshRateModesEnabled());
93     if (newRateMode == 0) {
94         HGM_LOGI("HgmCore No customer refreshrate mode found, set to xml default");
95         if (mPolicyConfigData_ == nullptr || !XMLParser::IsNumber(mPolicyConfigData_->defaultRefreshRateMode_)) {
96             HGM_LOGE("HgmCore failed to get parsed data");
97         } else {
98             customFrameRateMode_ = std::stoi(mPolicyConfigData_->defaultRefreshRateMode_);
99         }
100     } else {
101         HGM_LOGI("HgmCore No customer refreshrate mode found: %{public}d", newRateMode);
102         customFrameRateMode_ = newRateMode;
103         if (customFrameRateMode_ != HGM_REFRESHRATE_MODE_AUTO &&
104             mPolicyConfigData_ != nullptr && mPolicyConfigData_->xmlCompatibleMode_) {
105             customFrameRateMode_ = mPolicyConfigData_->SettingModeId2XmlModeId(customFrameRateMode_);
106         }
107         CheckCustomFrameRateModeValid();
108     }
109 
110     SetLtpoConfig();
111 
112     isInit_.store(true);
113     HGM_LOGI("HgmCore initialization success!!!");
114     return isInit_;
115 }
116 
CheckCustomFrameRateModeValid()117 void HgmCore::CheckCustomFrameRateModeValid()
118 {
119     if (hgmFrameRateMgr_ == nullptr || mPolicyConfigData_ == nullptr) {
120         return;
121     }
122 
123     auto curScreenStrategyId = hgmFrameRateMgr_->GetCurScreenStrategyId();
124     auto &screenConfigs = mPolicyConfigData_->screenConfigs_;
125     if (screenConfigs.find(curScreenStrategyId) == screenConfigs.end()) {
126         return;
127     }
128 
129     auto &screenConfig = screenConfigs[curScreenStrategyId];
130     auto modeStr = std::to_string(customFrameRateMode_);
131     if (screenConfig.find(modeStr) != screenConfig.end() || screenConfig.empty()) {
132         return;
133     }
134 
135     int32_t maxMode = HGM_REFRESHRATE_MODE_AUTO;
136     for (auto &[modeStr, _] : screenConfig) {
137         if (!XMLParser::IsNumber(modeStr)) {
138             continue;
139         }
140         auto mode = std::stoi(modeStr);
141         if (maxMode < mode) {
142             maxMode = mode;
143         }
144     }
145     HGM_LOGE("auto repair mode: %{public}d -> %{public}d", customFrameRateMode_, maxMode);
146     customFrameRateMode_ = maxMode;
147 }
148 
InitXmlConfig()149 int32_t HgmCore::InitXmlConfig()
150 {
151     HGM_LOGD("HgmCore is parsing xml configuration");
152     if (!mParser_) {
153         mParser_ = std::make_unique<XMLParser>();
154     }
155 
156     if (mParser_->LoadConfiguration(configFileProduct) != EXEC_SUCCESS) {
157         HGM_LOGW("HgmCore failed to load prod xml configuration file");
158     }
159     if (mParser_->Parse() != EXEC_SUCCESS) {
160         HGM_LOGW("HgmCore failed to parse prod xml configuration");
161     }
162 
163     if (!mPolicyConfigData_) {
164         mPolicyConfigData_ = mParser_->GetParsedData();
165     }
166 
167     return EXEC_SUCCESS;
168 }
169 
SetLtpoConfig()170 void HgmCore::SetLtpoConfig()
171 {
172     if ((hgmFrameRateMgr_ == nullptr) || (mPolicyConfigData_ == nullptr)) {
173         return;
174     }
175     auto curScreenStrategyId = hgmFrameRateMgr_->GetCurScreenStrategyId();
176     if (mPolicyConfigData_->screenConfigs_.count(curScreenStrategyId) == 0 ||
177         mPolicyConfigData_->screenConfigs_[curScreenStrategyId].count(std::to_string(customFrameRateMode_)) == 0) {
178         return;
179     }
180     auto curScreenSetting =
181         mPolicyConfigData_->screenConfigs_[curScreenStrategyId][std::to_string(customFrameRateMode_)];
182     if (curScreenSetting.ltpoConfig.find("switch") != curScreenSetting.ltpoConfig.end() &&
183         XMLParser::IsNumber(curScreenSetting.ltpoConfig["switch"])) {
184         ltpoEnabled_ = std::stoi(curScreenSetting.ltpoConfig["switch"]);
185     } else {
186         ltpoEnabled_ = 0;
187         HGM_LOGW("HgmCore failed to find switch strategy for LTPO");
188     }
189 
190     if (curScreenSetting.ltpoConfig.find("maxTE") != curScreenSetting.ltpoConfig.end()) {
191         maxTE_ = std::stoul(curScreenSetting.ltpoConfig["maxTE"]);
192     } else {
193         maxTE_ = 0;
194         HGM_LOGW("HgmCore failed to find TE strategy for LTPO");
195     }
196 
197     if (curScreenSetting.ltpoConfig.find("alignRate") != curScreenSetting.ltpoConfig.end()) {
198         alignRate_ = std::stoul(curScreenSetting.ltpoConfig["alignRate"]);
199     } else {
200         alignRate_ = 0;
201         HGM_LOGW("HgmCore failed to find alignRate strategy for LTPO");
202     }
203 
204     if (curScreenSetting.ltpoConfig.find("pipelineOffsetPulseNum") != curScreenSetting.ltpoConfig.end() &&
205         XMLParser::IsNumber(curScreenSetting.ltpoConfig["pipelineOffsetPulseNum"])) {
206         pipelineOffsetPulseNum_ = std::stoi(curScreenSetting.ltpoConfig["pipelineOffsetPulseNum"]);
207         CreateVSyncGenerator()->SetVSyncPhaseByPulseNum(pipelineOffsetPulseNum_);
208     } else {
209         pipelineOffsetPulseNum_ = 0;
210         HGM_LOGW("HgmCore failed to find pipelineOffset strategy for LTPO");
211     }
212 
213     SetScreenConstraintConfig();
214     HGM_LOGI("HgmCore LTPO strategy ltpoEnabled: %{public}d, maxTE: %{public}d, alignRate: %{public}d, " \
215         "pipelineOffsetPulseNum: %{public}d, vBlankIdleCorrectSwitch: %{public}d, lowRateToHighQuickSwitch: %{public}d",
216         ltpoEnabled_, maxTE_, alignRate_, pipelineOffsetPulseNum_, vBlankIdleCorrectSwitch_, lowRateToHighQuickSwitch_);
217 }
218 
SetScreenConstraintConfig()219 void HgmCore::SetScreenConstraintConfig()
220 {
221     auto curScreenStrategyId = hgmFrameRateMgr_->GetCurScreenStrategyId();
222     if (mPolicyConfigData_->screenConfigs_.count(curScreenStrategyId) == 0 ||
223         mPolicyConfigData_->screenConfigs_[curScreenStrategyId].count(std::to_string(customFrameRateMode_)) == 0) {
224         return;
225     }
226     auto curScreenSetting =
227         mPolicyConfigData_->screenConfigs_[curScreenStrategyId][std::to_string(customFrameRateMode_)];
228     if (curScreenSetting.ltpoConfig.find("vBlankIdleCorrectSwitch") != curScreenSetting.ltpoConfig.end() &&
229         XMLParser::IsNumber(curScreenSetting.ltpoConfig["vBlankIdleCorrectSwitch"])) {
230         vBlankIdleCorrectSwitch_ =  std::stoi(curScreenSetting.ltpoConfig["vBlankIdleCorrectSwitch"]);
231     } else {
232         vBlankIdleCorrectSwitch_ = 0;
233         HGM_LOGW("HgmCore failed to find vBlankIdleCorrectSwitch strategy for LTPO");
234     }
235 
236     if (curScreenSetting.ltpoConfig.find("lowRateToHighQuickSwitch") != curScreenSetting.ltpoConfig.end() &&
237         XMLParser::IsNumber(curScreenSetting.ltpoConfig["lowRateToHighQuickSwitch"])) {
238         lowRateToHighQuickSwitch_ =  std::stoi(curScreenSetting.ltpoConfig["lowRateToHighQuickSwitch"]);
239     } else {
240         lowRateToHighQuickSwitch_ = 0;
241         HGM_LOGW("HgmCore failed to find lowRateToHighQuickSwitch strategy for LTPO");
242     }
243 }
244 
RegisterRefreshRateModeChangeCallback(const RefreshRateModeChangeCallback & callback)245 void HgmCore::RegisterRefreshRateModeChangeCallback(const RefreshRateModeChangeCallback& callback)
246 {
247     refreshRateModeChangeCallback_ = callback;
248     if (refreshRateModeChangeCallback_ != nullptr) {
249         auto refreshRateModeName = GetCurrentRefreshRateModeName();
250         refreshRateModeChangeCallback_(refreshRateModeName);
251     }
252 }
253 
SetCustomRateMode(int32_t mode)254 int32_t HgmCore::SetCustomRateMode(int32_t mode)
255 {
256     customFrameRateMode_ = mode;
257     return EXEC_SUCCESS;
258 }
259 
RegisterRefreshRateUpdateCallback(const RefreshRateUpdateCallback & callback)260 void HgmCore::RegisterRefreshRateUpdateCallback(const RefreshRateUpdateCallback& callback)
261 {
262     ScreenId screenId = HgmCore::Instance().GetActiveScreenId();
263     uint32_t refreshRate = HgmCore::Instance().GetScreenCurrentRefreshRate(screenId);
264     refreshRateUpdateCallback_ = callback;
265     if (refreshRateUpdateCallback_ != nullptr) {
266         refreshRateUpdateCallback_(refreshRate);
267     }
268 }
269 
SetScreenRefreshRate(ScreenId id,int32_t sceneId,int32_t rate)270 int32_t HgmCore::SetScreenRefreshRate(ScreenId id, int32_t sceneId, int32_t rate)
271 {
272     // set the screen to the desired refreshrate
273     HGM_LOGD("HgmCore setting screen " PUBU64 " to the rate of %{public}d", id, rate);
274     auto screen = GetScreen(id);
275     if (!screen) {
276         HGM_LOGW("HgmCore failed to get screen of : " PUBU64 "", id);
277         return HGM_ERROR;
278     }
279 
280     if (rate <= 0) {
281         HGM_LOGW("HgmCore refuse an illegal framerate: %{public}d", rate);
282         return HGM_ERROR;
283     }
284     sceneId = static_cast<int32_t>(screenSceneSet_.size());
285     int32_t modeToSwitch = screen->SetActiveRefreshRate(sceneId, static_cast<uint32_t>(rate));
286     if (modeToSwitch < 0) {
287         return modeToSwitch;
288     }
289 
290     std::lock_guard<std::mutex> lock(modeListMutex_);
291 
292     // the rate is accepted and passed to a list, will be applied by hardwarethread before sending the composition
293     HGM_LOGI("HgmCore the rate of %{public}d is accepted, the target mode is %{public}d", rate, modeToSwitch);
294     if (modeListToApply_ == nullptr) {
295         HGM_LOGD("HgmCore modeListToApply_ is invalid, buiding a new mode list");
296         modeListToApply_ = std::make_unique<std::unordered_map<ScreenId, int32_t>>();
297     }
298     auto modeList = modeListToApply_.get();
299     (*modeList)[id] = modeToSwitch;
300 
301     if (refreshRateUpdateCallback_) {
302         refreshRateUpdateCallback_(rate);
303         HGM_LOGD("refresh rate changed, notify to app");
304     }
305     return modeToSwitch;
306 }
307 
SetRateAndResolution(ScreenId id,int32_t sceneId,int32_t rate,int32_t width,int32_t height)308 int32_t HgmCore::SetRateAndResolution(ScreenId id, int32_t sceneId, int32_t rate, int32_t width, int32_t height)
309 {
310     // reserved
311     return HGM_ERROR;
312 }
313 
SetRefreshRateMode(int32_t refreshRateMode)314 int32_t HgmCore::SetRefreshRateMode(int32_t refreshRateMode)
315 {
316     // setting mode to xml modeid
317     if (refreshRateMode != HGM_REFRESHRATE_MODE_AUTO
318         && mPolicyConfigData_ != nullptr && mPolicyConfigData_->xmlCompatibleMode_) {
319         refreshRateMode = mPolicyConfigData_->SettingModeId2XmlModeId(refreshRateMode);
320     }
321     HGM_LOGD("HgmCore set refreshrate mode to : %{public}d", refreshRateMode);
322     // change refreshrate mode by setting application
323     if (SetCustomRateMode(refreshRateMode) != EXEC_SUCCESS) {
324         return HGM_ERROR;
325     }
326 
327     hgmFrameRateMgr_->HandleRefreshRateMode(refreshRateMode);
328 
329     auto refreshRateModeName = GetCurrentRefreshRateModeName();
330     if (refreshRateModeChangeCallback_ != nullptr) {
331         refreshRateModeChangeCallback_(refreshRateModeName);
332     }
333     HgmConfigCallbackManager::GetInstance()->SyncRefreshRateModeChangeCallback(refreshRateModeName);
334     return EXEC_SUCCESS;
335 }
336 
NotifyScreenPowerStatus(ScreenId id,ScreenPowerStatus status)337 void HgmCore::NotifyScreenPowerStatus(ScreenId id, ScreenPowerStatus status)
338 {
339     if (hgmFrameRateMgr_ != nullptr) {
340         hgmFrameRateMgr_->HandleScreenPowerStatus(id, status);
341     }
342 
343     if (refreshRateModeChangeCallback_ != nullptr) {
344         auto refreshRateModeName = GetCurrentRefreshRateModeName();
345         refreshRateModeChangeCallback_(refreshRateModeName);
346     }
347 }
348 
AddScreen(ScreenId id,int32_t defaultMode,ScreenSize & screenSize)349 int32_t HgmCore::AddScreen(ScreenId id, int32_t defaultMode, ScreenSize& screenSize)
350 {
351     // add a physical screen to hgm during hotplug event
352     HGM_LOGI("HgmCore adding screen : " PUBI64 "", id);
353     bool removeId = std::any_of(screenIds_.begin(), screenIds_.end(),
354         [id](const ScreenId screen) { return screen == id; });
355     if (removeId) {
356         if (RemoveScreen(id) != EXEC_SUCCESS) {
357             HGM_LOGW("HgmCore failed to remove the existing screen, not adding : " PUBI64 "", id);
358             return HGM_BASE_REMOVE_FAILED;
359         }
360     }
361 
362     sptr<HgmScreen> newScreen = new HgmScreen(id, defaultMode, screenSize);
363 
364     std::lock_guard<std::mutex> lock(listMutex_);
365     screenList_.push_back(newScreen);
366     screenIds_.push_back(id);
367 
368     int32_t screenNum = GetScreenListSize();
369     HGM_LOGI("HgmCore num of screen is %{public}d", screenNum);
370     return EXEC_SUCCESS;
371 }
372 
RemoveScreen(ScreenId id)373 int32_t HgmCore::RemoveScreen(ScreenId id)
374 {
375     std::lock_guard<std::mutex> lock(listMutex_);
376     // delete a screen during a hotplug event
377     HGM_LOGD("HgmCore deleting the screen : " PUBU64 "", id);
378     for (auto screen = screenIds_.begin(); screen != screenIds_.end(); ++screen) {
379         if (*screen == id) {
380             screenIds_.erase(screen);
381             break;
382         }
383     }
384     for (auto screen = screenList_.begin(); screen != screenList_.end(); ++screen) {
385         if ((*screen)->GetId() == id) {
386             screenList_.erase(screen);
387             break;
388         }
389     }
390     return EXEC_SUCCESS;
391 }
392 
AddScreenInfo(ScreenId id,int32_t width,int32_t height,uint32_t rate,int32_t mode)393 int32_t HgmCore::AddScreenInfo(ScreenId id, int32_t width, int32_t height, uint32_t rate, int32_t mode)
394 {
395     // add a supported screen mode to the screen
396     auto screen = GetScreen(id);
397     if (!screen) {
398         HGM_LOGW("HgmCore failed to get screen of : " PUBU64 "", id);
399         return HGM_NO_SCREEN;
400     }
401 
402     if (screen->AddScreenModeInfo(width, height, rate, mode) == EXEC_SUCCESS) {
403         return EXEC_SUCCESS;
404     }
405 
406     HGM_LOGW("HgmCore failed to add screen mode info of screen : " PUBU64 "", id);
407     return HGM_SCREEN_PARAM_ERROR;
408 }
409 
RefreshBundleName(const std::string & name)410 int32_t HgmCore::RefreshBundleName(const std::string& name)
411 {
412     if (name == currentBundleName_) {
413         return EXEC_SUCCESS;
414     }
415 
416     currentBundleName_ = name;
417 
418     if (customFrameRateMode_ == HGM_REFRESHRATE_MODE_AUTO) {
419         return EXEC_SUCCESS;
420     }
421 
422     int resetResult = SetRefreshRateMode(customFrameRateMode_);
423     if (resetResult == EXEC_SUCCESS) {
424         HGM_LOGI("HgmCore reset current refreshrate mode: %{public}d due to bundlename: %{public}s",
425             customFrameRateMode_, currentBundleName_.c_str());
426     }
427     return EXEC_SUCCESS;
428 }
429 
GetScreenCurrentRefreshRate(ScreenId id) const430 uint32_t HgmCore::GetScreenCurrentRefreshRate(ScreenId id) const
431 {
432     auto screen = GetScreen(id);
433     if (!screen) {
434         HGM_LOGW("HgmCore failed to find screen " PUBU64 "", id);
435         return static_cast<uint32_t>(EXEC_SUCCESS);
436     }
437 
438     return screen->GetActiveRefreshRate();
439 }
440 
GetCurrentRefreshRateMode() const441 int32_t HgmCore::GetCurrentRefreshRateMode() const
442 {
443     if (customFrameRateMode_ != HGM_REFRESHRATE_MODE_AUTO
444         && mPolicyConfigData_ != nullptr && mPolicyConfigData_->xmlCompatibleMode_) {
445         return mPolicyConfigData_->XmlModeId2SettingModeId(customFrameRateMode_);
446     }
447     return customFrameRateMode_;
448 }
449 
GetCurrentRefreshRateModeName() const450 int32_t HgmCore::GetCurrentRefreshRateModeName() const
451 {
452     if (mPolicyConfigData_ != nullptr && mPolicyConfigData_->xmlCompatibleMode_) {
453         return mPolicyConfigData_->GetRefreshRateModeName(customFrameRateMode_);
454     }
455     std::map<int32_t, int32_t> modeIdRateMap = {{-1, -1}, {1, 60}, {2, 90}, {3, 120}};
456     if (modeIdRateMap.find(customFrameRateMode_) != modeIdRateMap.end()) {
457         return modeIdRateMap[customFrameRateMode_];
458     }
459     return customFrameRateMode_;
460 }
461 
GetScreen(ScreenId id) const462 sptr<HgmScreen> HgmCore::GetScreen(ScreenId id) const
463 {
464     std::lock_guard<std::mutex> lock(listMutex_);
465     for (auto screen = screenList_.begin(); screen != screenList_.end(); ++screen) {
466         if ((*screen)->GetId() == id) {
467             return *screen;
468         }
469     }
470 
471     return nullptr;
472 }
473 
GetScreenSupportedRefreshRates(ScreenId id)474 std::vector<uint32_t> HgmCore::GetScreenSupportedRefreshRates(ScreenId id)
475 {
476     auto screen = GetScreen(id);
477     if (!screen) {
478         HGM_LOGW("HgmCore failed to find screen " PUBU64 "", id);
479         return std::vector<uint32_t>(static_cast<uint32_t>(EXEC_SUCCESS));
480     }
481 
482     auto supportedRates = screen->GetSupportedRates();
483     std::vector<uint32_t> retVec;
484     retVec.assign(supportedRates.begin(), supportedRates.end());
485     return retVec;
486 }
487 
GetScreenComponentRefreshRates(ScreenId id)488 std::vector<int32_t> HgmCore::GetScreenComponentRefreshRates(ScreenId id)
489 {
490     if (!mPolicyConfigData_) {
491         HGM_LOGW("HgmCore no parsed component data, returning default value");
492         return std::vector<int32_t>(static_cast<uint32_t>(EXEC_SUCCESS));
493     }
494 
495     std::vector<int32_t> retVec;
496     for (const auto& [rate, _] : mPolicyConfigData_->refreshRateForSettings_) {
497         retVec.emplace_back(rate);
498         HGM_LOGE("HgmCore Adding component rate: %{public}d", rate);
499     }
500     return retVec;
501 }
502 
GetModesToApply()503 std::unique_ptr<std::unordered_map<ScreenId, int32_t>> HgmCore::GetModesToApply()
504 {
505     std::lock_guard<std::mutex> lock(modeListMutex_);
506     return std::move(modeListToApply_);
507 }
508 
SetActiveScreenId(ScreenId id)509 void HgmCore::SetActiveScreenId(ScreenId id)
510 {
511     activeScreenId_ = id;
512 }
513 
GetActiveScreen() const514 sptr<HgmScreen> HgmCore::GetActiveScreen() const
515 {
516     if (activeScreenId_ == INVALID_SCREEN_ID) {
517         HGM_LOGE("HgmScreen activeScreenId_ noset");
518         return nullptr;
519     }
520     return GetScreen(activeScreenId_);
521 }
522 
GetIdealPeriod(uint32_t rate)523 int64_t HgmCore::GetIdealPeriod(uint32_t rate)
524 {
525     if (IDEAL_PERIOD.count(rate)) {
526         return IDEAL_PERIOD[rate];
527     }
528     return 0;
529 }
530 } // namespace OHOS::Rosen
531