• 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_log.h"
26 #include "vsync_generator.h"
27 #include "platform/common/rs_system_properties.h"
28 #include "parameters.h"
29 #include "frame_rate_report.h"
30 #include "sandbox_utils.h"
31 
32 namespace OHOS::Rosen {
33 static std::map<uint32_t, int64_t> IDEAL_PERIOD = {
34     { 120, 8333333 },
35     { 90, 11111111 },
36     { 72, 13888888 },
37     { 60, 16666666 }
38 };
39 
Instance()40 HgmCore& HgmCore::Instance()
41 {
42     static HgmCore instance;
43     if (instance.IsInit()) {
44         return instance;
45     }
46     if (instance.Init() == false) {
47         HGM_LOGI("HgmCore initialization failed");
48     }
49 
50     return instance;
51 }
52 
HgmCore()53 HgmCore::HgmCore()
54 {
55     HGM_LOGI("Construction of Hgmcore");
56 }
57 
Init()58 bool HgmCore::Init()
59 {
60     if (isInit_) {
61         return true;
62     }
63 
64     if (!isEnabled_) {
65         HGM_LOGE("HgmCore Hgm is desactivated");
66         return false;
67     }
68 
69     if (InitXmlConfig() != EXEC_SUCCESS) {
70         HGM_LOGE("HgmCore falied to parse");
71         return false;
72     }
73 
74     // ensure that frameRateManager init after XML parsed.
75     hgmFrameRateMgr_ = std::make_unique<HgmFrameRateManager>();
76 
77     int newRateMode = static_cast<int32_t>(RSSystemProperties::GetHgmRefreshRateModesEnabled());
78     if (newRateMode == 0) {
79         HGM_LOGI("HgmCore No customer refreshrate mode found, set to xml default");
80         if (mPolicyConfigData_ == nullptr) {
81             HGM_LOGE("HgmCore failed to get parsed data");
82         } else {
83             customFrameRateMode_ = static_cast<RefreshRateMode>(std::stoi(mPolicyConfigData_->defaultRefreshRateMode_));
84         }
85     } else {
86         HGM_LOGI("HgmCore No customer refreshrate mode found: %{public}d", newRateMode);
87         customFrameRateMode_ = static_cast<RefreshRateMode>(newRateMode);
88     }
89 
90     SetLtpoConfig();
91 
92     isInit_ = true;
93     HGM_LOGI("HgmCore initialization success!!!");
94     return isInit_;
95 }
96 
InitXmlConfig()97 int32_t HgmCore::InitXmlConfig()
98 {
99     HGM_LOGD("HgmCore is parsing xml configuration");
100     if (!mParser_) {
101         mParser_ = std::make_unique<XMLParser>();
102     }
103 
104     if (mParser_->LoadConfiguration(configFileProduct) != EXEC_SUCCESS) {
105         HGM_LOGW("HgmCore failed to load prod xml configuration file");
106     }
107     if (mParser_->Parse() != EXEC_SUCCESS) {
108         HGM_LOGW("HgmCore failed to parse prod xml configuration");
109     }
110 
111     if (!mPolicyConfigData_) {
112         mPolicyConfigData_ = mParser_->GetParsedData();
113     }
114 
115     return EXEC_SUCCESS;
116 }
117 
SetLtpoConfig()118 void HgmCore::SetLtpoConfig()
119 {
120     if ((hgmFrameRateMgr_ == nullptr) || (mPolicyConfigData_ == nullptr)) {
121         return;
122     }
123     auto curScreenStrategyId = hgmFrameRateMgr_->GetCurScreenStrategyId();
124     auto curScreenSetting =
125         mPolicyConfigData_->screenConfigs_[curScreenStrategyId][std::to_string(customFrameRateMode_)];
126     if (curScreenSetting.ltpoConfig.find("switch") != curScreenSetting.ltpoConfig.end()) {
127         ltpoEnabled_ = std::stoi(curScreenSetting.ltpoConfig["switch"]);
128     } else {
129         ltpoEnabled_ = 0;
130         HGM_LOGW("HgmCore failed to find switch strategy for LTPO");
131     }
132 
133     if (curScreenSetting.ltpoConfig.find("maxTE") != curScreenSetting.ltpoConfig.end()) {
134         maxTE_ = std::stoul(curScreenSetting.ltpoConfig["maxTE"]);
135     } else {
136         maxTE_ = 0;
137         HGM_LOGW("HgmCore failed to find TE strategy for LTPO");
138     }
139 
140     if (curScreenSetting.ltpoConfig.find("alignRate") != curScreenSetting.ltpoConfig.end()) {
141         alignRate_ = std::stoul(curScreenSetting.ltpoConfig["alignRate"]);
142     } else {
143         alignRate_ = 0;
144         HGM_LOGW("HgmCore failed to find alignRate strategy for LTPO");
145     }
146 
147     if (curScreenSetting.ltpoConfig.find("pipelineOffsetPulseNum") != curScreenSetting.ltpoConfig.end()) {
148         pipelineOffsetPulseNum_ = std::stoi(curScreenSetting.ltpoConfig["pipelineOffsetPulseNum"]);
149         CreateVSyncGenerator()->SetVSyncPhaseByPulseNum(pipelineOffsetPulseNum_);
150     } else {
151         pipelineOffsetPulseNum_ = 0;
152         HGM_LOGW("HgmCore failed to find pipelineOffset strategy for LTPO");
153     }
154 
155     HGM_LOGI("HgmCore LTPO strategy ltpoEnabled: %{public}d, maxTE: %{public}d, alignRate: %{public}d, " \
156         "pipelineOffsetPulseNum: %{public}d", ltpoEnabled_, maxTE_, alignRate_, pipelineOffsetPulseNum_);
157 }
158 
RegisterRefreshRateModeChangeCallback(const RefreshRateModeChangeCallback & callback)159 void HgmCore::RegisterRefreshRateModeChangeCallback(const RefreshRateModeChangeCallback& callback)
160 {
161     refreshRateModeChangeCallback_ = callback;
162     if (refreshRateModeChangeCallback_ != nullptr) {
163         refreshRateModeChangeCallback_(customFrameRateMode_);
164     }
165 }
166 
SetCustomRateMode(RefreshRateMode mode)167 int32_t HgmCore::SetCustomRateMode(RefreshRateMode mode)
168 {
169     customFrameRateMode_ = mode;
170     return EXEC_SUCCESS;
171 }
172 
SetScreenRefreshRate(ScreenId id,int32_t sceneId,int32_t rate)173 int32_t HgmCore::SetScreenRefreshRate(ScreenId id, int32_t sceneId, int32_t rate)
174 {
175     // set the screen to the desired refreshrate
176     HGM_LOGD("HgmCore setting screen " PUBU64 " to the rate of %{public}d", id, rate);
177     auto screen = GetScreen(id);
178     if (!screen) {
179         HGM_LOGW("HgmCore failed to get screen of : " PUBU64 "", id);
180         return HGM_ERROR;
181     }
182 
183     if (rate <= 0) {
184         HGM_LOGW("HgmCore refuse an illegal framerate: %{public}d", rate);
185         return HGM_ERROR;
186     }
187     sceneId = static_cast<int32_t>(screenSceneSet_.size());
188     int32_t modeToSwitch = screen->SetActiveRefreshRate(sceneId, static_cast<uint32_t>(rate));
189     if (modeToSwitch < 0) {
190         return modeToSwitch;
191     }
192 
193     std::lock_guard<std::mutex> lock(modeListMutex_);
194 
195     // the rate is accepted and passed to a list, will be applied by hardwarethread before sending the composition
196     HGM_LOGI("HgmCore the rate of %{public}d is accepted, the target mode is %{public}d", rate, modeToSwitch);
197     if (modeListToApply_ == nullptr) {
198         HGM_LOGD("HgmCore modeListToApply_ is invalid, buiding a new mode list");
199         modeListToApply_ = std::make_unique<std::unordered_map<ScreenId, int32_t>>();
200     }
201     auto modeList = modeListToApply_.get();
202     (*modeList)[id] = modeToSwitch;
203     return modeToSwitch;
204 }
205 
SetRateAndResolution(ScreenId id,int32_t sceneId,int32_t rate,int32_t width,int32_t height)206 int32_t HgmCore::SetRateAndResolution(ScreenId id, int32_t sceneId, int32_t rate, int32_t width, int32_t height)
207 {
208     // reserved
209     return HGM_ERROR;
210 }
211 
SetRefreshRateMode(RefreshRateMode refreshRateMode)212 int32_t HgmCore::SetRefreshRateMode(RefreshRateMode refreshRateMode)
213 {
214     HGM_LOGD("HgmCore set refreshrate mode to : %{public}d", refreshRateMode);
215     // change refreshrate mode by setting application
216     if (SetCustomRateMode(refreshRateMode) != EXEC_SUCCESS) {
217         return HGM_ERROR;
218     }
219 
220     hgmFrameRateMgr_->HandleRefreshRateMode(refreshRateMode);
221 
222     if (refreshRateModeChangeCallback_ != nullptr) {
223         refreshRateModeChangeCallback_(refreshRateMode);
224     }
225     return EXEC_SUCCESS;
226 }
227 
NotifyScreenPowerStatus(ScreenId id,ScreenPowerStatus status)228 void HgmCore::NotifyScreenPowerStatus(ScreenId id, ScreenPowerStatus status)
229 {
230     hgmFrameRateMgr_->HandleScreenPowerStatus(id, status);
231 
232     if (refreshRateModeChangeCallback_ != nullptr) {
233         refreshRateModeChangeCallback_(customFrameRateMode_);
234     }
235 }
236 
AddScreen(ScreenId id,int32_t defaultMode,ScreenSize & screenSize)237 int32_t HgmCore::AddScreen(ScreenId id, int32_t defaultMode, ScreenSize& screenSize)
238 {
239     // add a physical screen to hgm during hotplug event
240     HGM_LOGI("HgmCore adding screen : " PUBI64 "", id);
241     bool removeId = std::any_of(screenIds_.begin(), screenIds_.end(),
242         [id](const ScreenId screen) { return screen == id; });
243     if (removeId) {
244         if (RemoveScreen(id) != EXEC_SUCCESS) {
245             HGM_LOGW("HgmCore failed to remove the existing screen, not adding : " PUBI64 "", id);
246             return HGM_BASE_REMOVE_FAILED;
247         }
248     }
249 
250     sptr<HgmScreen> newScreen = new HgmScreen(id, defaultMode, screenSize);
251 
252     std::lock_guard<std::mutex> lock(listMutex_);
253     screenList_.push_back(newScreen);
254     screenIds_.push_back(id);
255 
256     int32_t screenNum = GetScreenListSize();
257     HGM_LOGI("HgmCore num of screen is %{public}d", screenNum);
258     return EXEC_SUCCESS;
259 }
260 
RemoveScreen(ScreenId id)261 int32_t HgmCore::RemoveScreen(ScreenId id)
262 {
263     std::lock_guard<std::mutex> lock(listMutex_);
264     // delete a screen during a hotplug event
265     HGM_LOGD("HgmCore deleting the screen : " PUBU64 "", id);
266     for (auto screen = screenIds_.begin(); screen != screenIds_.end(); ++screen) {
267         if (*screen == id) {
268             screenIds_.erase(screen);
269             break;
270         }
271     }
272     for (auto screen = screenList_.begin(); screen != screenList_.end(); ++screen) {
273         if ((*screen)->GetId() == id) {
274             screenList_.erase(screen);
275             break;
276         }
277     }
278     return EXEC_SUCCESS;
279 }
280 
AddScreenInfo(ScreenId id,int32_t width,int32_t height,uint32_t rate,int32_t mode)281 int32_t HgmCore::AddScreenInfo(ScreenId id, int32_t width, int32_t height, uint32_t rate, int32_t mode)
282 {
283     // add a supported screen mode to the screen
284     auto screen = GetScreen(id);
285     if (!screen) {
286         HGM_LOGW("HgmCore failed to get screen of : " PUBU64 "", id);
287         return HGM_NO_SCREEN;
288     }
289 
290     if (screen->AddScreenModeInfo(width, height, rate, mode) == EXEC_SUCCESS) {
291         return EXEC_SUCCESS;
292     }
293 
294     HGM_LOGW("HgmCore failed to add screen mode info of screen : " PUBU64 "", id);
295     return HGM_SCREEN_PARAM_ERROR;
296 }
297 
RefreshBundleName(const std::string & name)298 int32_t HgmCore::RefreshBundleName(const std::string& name)
299 {
300     if (name == currentBundleName_) {
301         return EXEC_SUCCESS;
302     }
303 
304     currentBundleName_ = name;
305 
306     if (customFrameRateMode_ == HGM_REFRESHRATE_MODE_AUTO) {
307         return EXEC_SUCCESS;
308     }
309 
310     int resetResult = SetRefreshRateMode(customFrameRateMode_);
311     if (resetResult == EXEC_SUCCESS) {
312         HGM_LOGI("HgmCore reset current refreshrate mode: %{public}d due to bundlename: %{public}s",
313             customFrameRateMode_, currentBundleName_.c_str());
314     }
315     return EXEC_SUCCESS;
316 }
317 
GetScreenCurrentRefreshRate(ScreenId id) const318 uint32_t HgmCore::GetScreenCurrentRefreshRate(ScreenId id) const
319 {
320     auto screen = GetScreen(id);
321     if (!screen) {
322         HGM_LOGW("HgmCore failed to find screen " PUBU64 "", id);
323         return static_cast<uint32_t>(EXEC_SUCCESS);
324     }
325 
326     return screen->GetActiveRefreshRate();
327 }
328 
GetCurrentRefreshRateMode() const329 int32_t HgmCore::GetCurrentRefreshRateMode() const
330 {
331     int32_t currentRefreshRateMode = static_cast<int32_t>(customFrameRateMode_);
332     return currentRefreshRateMode;
333 }
334 
GetScreen(ScreenId id) const335 sptr<HgmScreen> HgmCore::GetScreen(ScreenId id) const
336 {
337     std::lock_guard<std::mutex> lock(listMutex_);
338     for (auto screen = screenList_.begin(); screen != screenList_.end(); ++screen) {
339         if ((*screen)->GetId() == id) {
340             return *screen;
341         }
342     }
343 
344     return nullptr;
345 }
346 
GetScreenSupportedRefreshRates(ScreenId id)347 std::vector<uint32_t> HgmCore::GetScreenSupportedRefreshRates(ScreenId id)
348 {
349     auto screen = GetScreen(id);
350     if (!screen) {
351         HGM_LOGW("HgmCore failed to find screen " PUBU64 "", id);
352         return std::vector<uint32_t>(static_cast<uint32_t>(EXEC_SUCCESS));
353     }
354 
355     auto supportedRates = screen->GetSupportedRates();
356     std::vector<uint32_t> retVec;
357     retVec.assign(supportedRates.begin(), supportedRates.end());
358     return retVec;
359 }
360 
GetScreenComponentRefreshRates(ScreenId id)361 std::vector<int32_t> HgmCore::GetScreenComponentRefreshRates(ScreenId id)
362 {
363     if (!mPolicyConfigData_) {
364         HGM_LOGW("HgmCore no parsed component data, returning default value");
365         return std::vector<int32_t>(static_cast<uint32_t>(EXEC_SUCCESS));
366     }
367 
368     std::vector<int32_t> retVec;
369     for (const auto& [rate, _] : mPolicyConfigData_->refreshRateForSettings_) {
370         retVec.emplace_back(std::stoi(rate));
371         HGM_LOGE("HgmCore Adding component rate: %{public}d", std::stoi(rate));
372     }
373     return retVec;
374 }
375 
GetModesToApply()376 std::unique_ptr<std::unordered_map<ScreenId, int32_t>> HgmCore::GetModesToApply()
377 {
378     std::lock_guard<std::mutex> lock(modeListMutex_);
379     return std::move(modeListToApply_);
380 }
381 
SetActiveScreenId(ScreenId id)382 void HgmCore::SetActiveScreenId(ScreenId id)
383 {
384     activeScreenId_ = id;
385 }
386 
GetActiveScreen() const387 sptr<HgmScreen> HgmCore::GetActiveScreen() const
388 {
389     if (activeScreenId_ == INVALID_SCREEN_ID) {
390         HGM_LOGE("HgmScreen activeScreenId_ noset");
391         return nullptr;
392     }
393     return GetScreen(activeScreenId_);
394 }
395 
GetIdealPeriod(uint32_t rate)396 int64_t HgmCore::GetIdealPeriod(uint32_t rate)
397 {
398     if (IDEAL_PERIOD.count(rate)) {
399         return IDEAL_PERIOD[rate];
400     }
401     return 0;
402 }
403 } // namespace OHOS::Rosen
404