• 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 <string>
19 #include <unistd.h>
20 
21 #include "hgm_log.h"
22 
23 namespace OHOS::Rosen {
Instance()24 HgmCore& HgmCore::Instance()
25 {
26     static HgmCore instance;
27     if (instance.IsInit()) {
28         return instance;
29     }
30 
31     if (instance.Init() == false) {
32         HGM_LOGI("HgmCore initialization failed");
33     }
34 
35     return instance;
36 }
37 
HgmCore()38 HgmCore::HgmCore()
39 {
40     HGM_LOGI("Construction of Hgmcore");
41 }
42 
~HgmCore()43 HgmCore::~HgmCore()
44 {
45     std::lock_guard<std::mutex> lock(listMutex_);
46     HGM_LOGI("Destruction of HgmCore");
47     auto screen = screenList_.begin();
48     while (screen != screenList_.end()) {
49         screenList_.erase(screen++);
50     }
51     auto screenIdIter = screenIds_.begin();
52     while (screenIdIter != screenIds_.end()) {
53         screenIds_.erase(screenIdIter++);
54     }
55 }
56 
Init()57 bool HgmCore::Init()
58 {
59     if (isInit_) {
60         return true;
61     }
62 
63     if (!isEnabled_) {
64         HGM_LOGE("HgmCore Hgm is desactivated");
65         return false;
66     }
67 
68     if (InitXmlConfig() != EXEC_SUCCESS) {
69         HGM_LOGE("HgmCore falied to parse");
70         return false;
71     }
72     hgmFrameRateTool_ = HgmFrameRateTool::GetInstance();
73 
74     isInit_ = true;
75     HGM_LOGI("HgmCore initialization success!!!");
76     return isInit_;
77 }
78 
InitXmlConfig()79 int32_t HgmCore::InitXmlConfig()
80 {
81     // parse xml configuration to hgm
82     HGM_LOGD("HgmCore is parsing xml configuration");
83     if (!mParser_) {
84         mParser_ = std::make_unique<XMLParser>();
85     }
86     if (mParser_->LoadConfiguration() != EXEC_SUCCESS) {
87         HGM_LOGE("HgmCore failed to load xml configuration file");
88         return XML_FILE_LOAD_FAIL;
89     }
90     if (mParser_->Parse()) {
91         HGM_LOGE("HgmCore failed to parse xml configuration");
92         return XML_GET_ROOT_FAIL;
93     }
94     if (!mParsedConfigData_) {
95         mParsedConfigData_ = mParser_->GetParsedData();
96     }
97     return EXEC_SUCCESS;
98 }
99 
SetCustomRateMode(RefreshRateMode mode)100 int32_t HgmCore::SetCustomRateMode(RefreshRateMode mode)
101 {
102     customFrameRateMode_ = mode;
103     return EXEC_SUCCESS;
104 }
105 
SetModeBySettingConfig()106 int32_t HgmCore::SetModeBySettingConfig()
107 {
108     if (!mParsedConfigData_) {
109         HGM_LOGW("HgmCore no parsed xml configuration found, failed to apply refreshrate mode");
110         return HGM_ERROR;
111     }
112 
113     std::string settingTag = std::to_string(customFrameRateMode_);
114     auto mapIter = mParsedConfigData_->customerSettingConfig_.find(settingTag);
115     if (mapIter == mParsedConfigData_->customerSettingConfig_.end()) {
116         HGM_LOGW("HgmCore failed to find strategy for customer setting : %{public}d", customFrameRateMode_);
117         return HGM_ERROR;
118     }
119 
120     std::string strat = mParsedConfigData_->customerSettingConfig_[settingTag];
121     auto strategy = mParsedConfigData_->detailedStrategies_.find(strat);
122     if (strategy == mParsedConfigData_->detailedStrategies_.end()) {
123         HGM_LOGW("HgmCore failed to find strategy detail for strat : %{public}s", strat.c_str());
124         return HGM_ERROR;
125     }
126     int32_t rateToSwitch = std::stoi(mParsedConfigData_->detailedStrategies_[strat].max);
127     int32_t rateFloor = std::stoi(mParsedConfigData_->detailedStrategies_[strat].min);
128 
129     HGM_LOGW("HgmCore switching to rate: %{public}d via refreshrate mode, range min: %{public}d, max: %{public}d",
130         rateToSwitch, rateFloor, rateToSwitch);
131     if (rateToSwitch <= 0 || rateFloor <= 0) {
132         HGM_LOGW("HgmCore get an illegal rate via parsed config data : %{public}d", rateToSwitch);
133         return HGM_ERROR;
134     }
135 
136     rateToSwitch = RequestBundlePermission(rateToSwitch);
137     for (auto &screen : screenList_) {
138         int32_t setRange = screen->SetRefreshRateRange(
139             static_cast<uint32_t>(rateFloor), static_cast<uint32_t>(rateToSwitch));
140         int32_t setThisScreen = SetScreenRefreshRate(screen->GetId(), 0, rateToSwitch);
141         if (setThisScreen != EXEC_SUCCESS || setRange != EXEC_SUCCESS) {
142             HGM_LOGW("HgmCore failed to apply refreshrate mode to screen : " PUBU64 "", screen->GetId());
143             return HGM_ERROR;
144         }
145     }
146 
147     return EXEC_SUCCESS;
148 }
149 
RequestBundlePermission(int32_t rate)150 int32_t HgmCore::RequestBundlePermission(int32_t rate)
151 {
152     if (rate <= OLED_60_HZ) {
153         return rate;
154     }
155 
156     // black_list conatrol at 90hz, return 60 if in the list
157     if (customFrameRateMode_ == HGM_REFRESHRATE_MODE_MEDIUM) {
158         auto bundle = mParsedConfigData_->bundle_black_list_.find(currentBundleName_);
159         if (bundle != mParsedConfigData_->bundle_black_list_.end()) {
160             return OLED_60_HZ;
161         }
162         return rate;
163     }
164 
165     // white_list control at 120hz, return 60 if not in the list
166     if (customFrameRateMode_ == HGM_REFRESHRATE_MODE_HIGH) {
167         auto bundle = mParsedConfigData_->bundle_white_list_.find(currentBundleName_);
168         if (bundle == mParsedConfigData_->bundle_white_list_.end()) {
169             return OLED_60_HZ;
170         }
171         return rate;
172     }
173 
174     return rate;
175 }
176 
SetScreenRefreshRate(ScreenId id,int32_t sceneId,int32_t rate)177 int32_t HgmCore::SetScreenRefreshRate(ScreenId id, int32_t sceneId, int32_t rate)
178 {
179     // set the screen to the desired refreshrate
180     HGM_LOGD("HgmCore setting screen " PUBU64 " to the rate of %{public}d", id, rate);
181     auto screen = GetScreen(id);
182     if (!screen) {
183         HGM_LOGW("HgmCore failed to get screen of : " PUBU64 "", id);
184         return HGM_ERROR;
185     }
186 
187     if (rate <= 0) {
188         HGM_LOGW("HgmCore refuse an illegal framerate: %{public}d", rate);
189         return HGM_ERROR;
190     }
191 
192     int32_t modeToSwitch = screen->SetActiveRefreshRate(sceneId, static_cast<uint32_t>(rate));
193     if (modeToSwitch < 0) {
194         return modeToSwitch;
195     }
196 
197     std::lock_guard<std::mutex> lock(modeListMutex_);
198 
199     // the rate is accepted and passed to a list, will be applied by hardwarethread before sending the composition
200     HGM_LOGI("HgmCore the rate of %{public}d is accepted, the target mode is %{public}d", rate, modeToSwitch);
201     if (modeListToApply_ == nullptr) {
202         HGM_LOGD("HgmCore modeListToApply_ is invalid, buiding a new mode list");
203         modeListToApply_ = std::make_unique<std::unordered_map<ScreenId, int32_t>>();
204     }
205     auto modeList = modeListToApply_.get();
206     (*modeList)[id] = modeToSwitch;
207     return modeToSwitch;
208 }
209 
SetRateAndResolution(ScreenId id,int32_t sceneId,int32_t rate,int32_t width,int32_t height)210 int32_t HgmCore::SetRateAndResolution(ScreenId id, int32_t sceneId, int32_t rate, int32_t width, int32_t height)
211 {
212     // reserved
213     return HGM_ERROR;
214 }
215 
SetRefreshRateMode(RefreshRateMode refreshRateMode)216 int32_t HgmCore::SetRefreshRateMode(RefreshRateMode refreshRateMode)
217 {
218     HGM_LOGD("HgmCore set refreshrate mode to : %{public}d", refreshRateMode);
219     // change refreshrate mode by setting application
220     if (SetCustomRateMode(refreshRateMode) != EXEC_SUCCESS) {
221         return HGM_ERROR;
222     }
223 
224     // apply the refreshrate mode to the screen
225     if (SetModeBySettingConfig() != EXEC_SUCCESS) {
226         return HGM_ERROR;
227     }
228 
229     return EXEC_SUCCESS;
230 }
231 
SetDefaultRefreshRateMode()232 int32_t HgmCore::SetDefaultRefreshRateMode()
233 {
234     if (!mParsedConfigData_) {
235         HGM_LOGW("HgmCore no parsed xml configuration found, failed to apply refreshrate mode");
236         return HGM_ERROR;
237     }
238     int32_t mode = std::stoi(mParsedConfigData_->defaultRefreshRateMode_);
239     HGM_LOGD("HgmCore set default refreshrate mode to : %{public}d", mode);
240 
241     if (mode == 0) {
242         return EXEC_SUCCESS;
243     }
244 
245     return SetRefreshRateMode(static_cast<RefreshRateMode>(mode));
246 }
247 
AddScreen(ScreenId id,int32_t defaultMode)248 int32_t HgmCore::AddScreen(ScreenId id, int32_t defaultMode)
249 {
250     // add a physical screen to hgm during hotplug event
251     HGM_LOGI("HgmCore adding screen : " PUBI64 "", id);
252     bool removeId = false;
253     for (auto screen : screenIds_) {
254         if (screen == id) {
255             removeId = true;
256             break;
257         }
258     }
259     if (removeId) {
260         if (RemoveScreen(id) != EXEC_SUCCESS) {
261             HGM_LOGW("HgmCore failed to remove the existing screen, not adding : " PUBI64 "", id);
262             return HGM_BASE_REMOVE_FAILED;
263         }
264     }
265 
266     sptr<HgmScreen> newScreen = new HgmScreen(id, defaultMode);
267 
268     std::lock_guard<std::mutex> lock(listMutex_);
269     screenList_.push_back(newScreen);
270     screenIds_.push_back(id);
271 
272     int32_t screenNum = GetScreenListSize();
273     HGM_LOGI("HgmCore num of screen is %{public}d", screenNum);
274     return EXEC_SUCCESS;
275 }
276 
RemoveScreen(ScreenId id)277 int32_t HgmCore::RemoveScreen(ScreenId id)
278 {
279     std::lock_guard<std::mutex> lock(listMutex_);
280     // delete a screen during a hotplug event
281     HGM_LOGD("HgmCore deleting the screen : " PUBU64 "", id);
282     for (auto screen = screenIds_.begin(); screen != screenIds_.end(); ++screen) {
283         if (*screen == id) {
284             screenIds_.erase(screen);
285             break;
286         }
287     }
288     for (auto screen = screenList_.begin(); screen != screenList_.end(); ++screen) {
289         if ((*screen)->GetId() == id) {
290             screenList_.erase(screen);
291             break;
292         }
293     }
294     return EXEC_SUCCESS;
295 }
296 
AddScreenInfo(ScreenId id,int32_t width,int32_t height,uint32_t rate,int32_t mode)297 int32_t HgmCore::AddScreenInfo(ScreenId id, int32_t width, int32_t height, uint32_t rate, int32_t mode)
298 {
299     // add a supported screen mode to the screen
300     auto screen = GetScreen(id);
301     if (!screen) {
302         HGM_LOGW("HgmCore failed to get screen of : " PUBU64 "", id);
303         return HGM_NO_SCREEN;
304     }
305 
306     if (screen->AddScreenModeInfo(width, height, rate, mode) == EXEC_SUCCESS) {
307         return EXEC_SUCCESS;
308     }
309 
310     HGM_LOGW("HgmCore failed to add screen mode info of screen : " PUBU64 "", id);
311     return HGM_SCREEN_PARAM_ERROR;
312 }
313 
RefreshBundleName(std::string name)314 int32_t HgmCore::RefreshBundleName(std::string name)
315 {
316     if (name == currentBundleName_) {
317         return EXEC_SUCCESS;
318     }
319 
320     currentBundleName_ = name;
321 
322     if (customFrameRateMode_ == HGM_REFRESHRATE_MODE_AUTO) {
323         return EXEC_SUCCESS;
324     }
325 
326     int resetResult = SetRefreshRateMode(customFrameRateMode_);
327     if (resetResult == EXEC_SUCCESS) {
328         HGM_LOGI("HgmCore reset current refreshrate mode: %{public}d due to bundlename: %{public}s",
329             customFrameRateMode_, currentBundleName_.c_str());
330     }
331     return EXEC_SUCCESS;
332 }
333 
GetScreenCurrentRefreshRate(ScreenId id)334 uint32_t HgmCore::GetScreenCurrentRefreshRate(ScreenId id)
335 {
336     auto screen = GetScreen(id);
337     if (!screen) {
338         HGM_LOGW("HgmCore failed to find screen " PUBU64 "", id);
339         return static_cast<uint32_t>(EXEC_SUCCESS);
340     }
341 
342     return screen->GetActiveRefreshRate();
343 }
344 
GetScreen(ScreenId id) const345 sptr<HgmScreen> HgmCore::GetScreen(ScreenId id) const
346 {
347     std::lock_guard<std::mutex> lock(listMutex_);
348     for (auto screen = screenList_.begin(); screen != screenList_.end(); ++screen) {
349         if ((*screen)->GetId() == id) {
350             return *screen;
351         }
352     }
353 
354     return nullptr;
355 }
356 
GetScreenSupportedRefreshRates(ScreenId id)357 std::vector<uint32_t> HgmCore::GetScreenSupportedRefreshRates(ScreenId id)
358 {
359     auto screen = GetScreen(id);
360     if (!screen) {
361         HGM_LOGW("HgmCore failed to find screen " PUBU64 "", id);
362         return std::vector<uint32_t>(static_cast<uint32_t>(EXEC_SUCCESS));
363     }
364 
365     auto supportedRates = screen->GetSupportedRates();
366     std::vector<uint32_t> retVec;
367     retVec.assign(supportedRates.begin(), supportedRates.end());
368     return retVec;
369 }
370 
GetModesToApply()371 std::unique_ptr<std::unordered_map<ScreenId, int32_t>> HgmCore::GetModesToApply()
372 {
373     std::lock_guard<std::mutex> lock(modeListMutex_);
374     return std::move(modeListToApply_);
375 }
376 
AddScreenProfile(ScreenId id,int32_t width,int32_t height,int32_t phyWidth,int32_t phyHeight)377 int32_t HgmCore::AddScreenProfile(ScreenId id, int32_t width, int32_t height, int32_t phyWidth, int32_t phyHeight)
378 {
379     return hgmFrameRateTool_->AddScreenProfile(id, width, height, phyWidth, phyHeight);
380 }
381 
RemoveScreenProfile(ScreenId id)382 int32_t HgmCore::RemoveScreenProfile(ScreenId id)
383 {
384     return hgmFrameRateTool_->RemoveScreenProfile(id);
385 }
386 
CalModifierPreferred(HgmModifierProfile & hgmModifierProfile) const387 int32_t HgmCore::CalModifierPreferred(HgmModifierProfile &hgmModifierProfile) const
388 {
389     return hgmFrameRateTool_->CalModifierPreferred(activeScreenId_, hgmModifierProfile, mParsedConfigData_);
390 }
391 
SetActiveScreenId(ScreenId id)392 void HgmCore::SetActiveScreenId(ScreenId id)
393 {
394     activeScreenId_ = id;
395 }
396 
397 } // namespace OHOS::Rosen
398