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