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_config_callback_manager.h"
17
18 #include "hgm_core.h"
19 #include "hgm_frame_rate_manager.h"
20 #include "hgm_log.h"
21
22 namespace OHOS::Rosen {
23 std::once_flag HgmConfigCallbackManager::createFlag_;
24 sptr<HgmConfigCallbackManager> HgmConfigCallbackManager::instance_ = nullptr;
25 namespace {
26 constexpr int32_t DESTROYED_XCOMPONENT_FRAMERATE = -1;
27 constexpr int32_t MAX_XCOMPONENT_ID_NUMS = 50;
28 }
29
GetInstance()30 sptr<HgmConfigCallbackManager> HgmConfigCallbackManager::GetInstance() noexcept
31 {
32 std::call_once(createFlag_, []() {
33 instance_ = new HgmConfigCallbackManager();
34 });
35 return instance_;
36 }
37
HgmConfigCallbackManager()38 HgmConfigCallbackManager::HgmConfigCallbackManager()
39 {
40 }
41
~HgmConfigCallbackManager()42 HgmConfigCallbackManager::~HgmConfigCallbackManager() noexcept
43 {
44 animDynamicCfgCallbacks_.clear();
45 pendingAnimDynamicCfgCallbacks_.clear();
46 refreshRateModeCallbacks_.clear();
47 }
48
RegisterHgmConfigChangeCallback(pid_t pid,const sptr<RSIHgmConfigChangeCallback> & callback)49 void HgmConfigCallbackManager::RegisterHgmConfigChangeCallback(
50 pid_t pid, const sptr<RSIHgmConfigChangeCallback>& callback)
51 {
52 if (callback == nullptr) {
53 HGM_LOGE("HgmConfigCallbackManager %{public}s : callback is null.", __func__);
54 return;
55 }
56 animDynamicCfgCallbacks_[pid] = callback;
57 HGM_LOGD("HgmConfigCallbackManager %{public}s : add a remote callback succeed.", __func__);
58
59 auto& hgmCore = HgmCore::Instance();
60 auto data = std::make_shared<RSHgmConfigData>();
61
62 auto screenType = hgmCore.GetFrameRateMgr()->GetCurScreenStrategyId();
63 auto settingMode = std::to_string(hgmCore.GetCurrentRefreshRateMode());
64 auto configData = hgmCore.GetPolicyConfigData();
65 if (configData != nullptr) {
66 auto dynamicSettingMap = configData->GetAceSceneDynamicSettingMap(screenType, settingMode);
67 for (auto& [animType, dynamicSetting] : dynamicSettingMap) {
68 for (auto& [animName, dynamicConfig] : dynamicSetting) {
69 data->AddAnimDynamicItem({
70 animType, animName, dynamicConfig.min, dynamicConfig.max, dynamicConfig.preferredFps});
71 }
72 }
73 }
74
75 if (configData != nullptr) {
76 for (auto item : configData->pageNameList_) {
77 data->AddPageName(item);
78 }
79 }
80
81 auto screen = hgmCore.GetActiveScreen();
82 if (screen != nullptr) {
83 data->SetPpi(screen->GetPpi());
84 data->SetXDpi(screen->GetXDpi());
85 data->SetYDpi(screen->GetYDpi());
86 }
87 callback->OnHgmConfigChanged(data);
88 }
89
RegisterHgmRefreshRateModeChangeCallback(pid_t pid,const sptr<RSIHgmConfigChangeCallback> & callback)90 void HgmConfigCallbackManager::RegisterHgmRefreshRateModeChangeCallback(
91 pid_t pid, const sptr<RSIHgmConfigChangeCallback>& callback)
92 {
93 if (callback == nullptr) {
94 HGM_LOGE("HgmRefreshRateModeCallbackManager %{public}s : callback is null.", __func__);
95 return;
96 }
97 refreshRateModeCallbacks_[pid] = callback;
98 HGM_LOGD("HgmRefreshRateModeCallbackManager %{public}s : add a remote callback succeed.", __func__);
99
100 int32_t currentRefreshRateModeName = HgmCore::Instance().GetCurrentRefreshRateModeName();
101 callback->OnHgmRefreshRateModeChanged(currentRefreshRateModeName);
102 }
103
RegisterHgmRefreshRateUpdateCallback(pid_t pid,const sptr<RSIHgmConfigChangeCallback> & callback)104 void HgmConfigCallbackManager::RegisterHgmRefreshRateUpdateCallback(
105 pid_t pid, const sptr<RSIHgmConfigChangeCallback>& callback)
106 {
107 if (callback == nullptr) {
108 if (refreshRateUpdateCallbacks_.find(pid) != refreshRateUpdateCallbacks_.end()) {
109 refreshRateUpdateCallbacks_.erase(pid);
110 HGM_LOGD("refreshRateUpdateCallbacks unregister succ, remove pid %{public}u", pid);
111 }
112 return;
113 }
114 refreshRateUpdateCallbacks_[pid] = callback;
115 uint32_t currentRefreshRate =
116 HgmCore::Instance().GetScreenCurrentRefreshRate(HgmCore::Instance().GetActiveScreenId());
117 HGM_LOGD("%{public}s : currentRefreshRate = %{public}d", __func__, currentRefreshRate);
118 callback->OnHgmRefreshRateUpdate(currentRefreshRate);
119 }
120
RegisterXComponentExpectedFrameRateCallback(pid_t listenerPid,pid_t dstPid,const sptr<RSIFrameRateLinkerExpectedFpsUpdateCallback> & callback)121 void HgmConfigCallbackManager::RegisterXComponentExpectedFrameRateCallback(pid_t listenerPid, pid_t dstPid,
122 const sptr<RSIFrameRateLinkerExpectedFpsUpdateCallback>& callback)
123 {
124 HGM_LOGI("%{public}d:[%{public}d,%{public}d]", listenerPid, dstPid, callback == nullptr);
125 if (callback == nullptr) {
126 if (auto iter = xcomponentExpectedFrameRateCallbacks_.find(dstPid);
127 iter != xcomponentExpectedFrameRateCallbacks_.end()) {
128 iter->second.erase(listenerPid);
129 HGM_LOGI("refreshRateUpdateCallbacks unregister succ, remove pid %{public}u", listenerPid);
130 }
131 return;
132 }
133 xcomponentExpectedFrameRateCallbacks_[dstPid][listenerPid] = callback;
134 if (auto iter = xcomponentExpectedFrameRate_.find(dstPid); iter != xcomponentExpectedFrameRate_.end()) {
135 for (auto& [xcomponentId, frameRate] : iter->second) {
136 HGM_LOGI("%{public}d:[%{public}s,%{public}d]", dstPid, xcomponentId.c_str(), frameRate);
137 callback->OnFrameRateLinkerExpectedFpsUpdate(dstPid, xcomponentId, frameRate);
138 }
139 }
140 }
141
SyncHgmConfigChangeCallback()142 void HgmConfigCallbackManager::SyncHgmConfigChangeCallback()
143 {
144 pendingAnimDynamicCfgCallbacks_ = animDynamicCfgCallbacks_;
145 auto frameRateMgr = HgmCore::Instance().GetFrameRateMgr();
146 if (frameRateMgr == nullptr) {
147 return;
148 }
149 SyncHgmConfigChangeCallback(frameRateMgr->GetMultiAppStrategy().GetForegroundPidApp());
150 }
151
SyncHgmConfigChangeCallback(const std::unordered_map<pid_t,std::pair<int32_t,std::string>> & pids)152 void HgmConfigCallbackManager::SyncHgmConfigChangeCallback(
153 const std::unordered_map<pid_t, std::pair<int32_t, std::string>>& pids)
154 {
155 if (pendingAnimDynamicCfgCallbacks_.empty()) {
156 return;
157 }
158 decltype(pendingAnimDynamicCfgCallbacks_) callbacks;
159 for (const auto& [pid, _] : pids) {
160 if (pendingAnimDynamicCfgCallbacks_.find(pid) == pendingAnimDynamicCfgCallbacks_.end()) {
161 continue;
162 }
163 callbacks[pid] = pendingAnimDynamicCfgCallbacks_[pid];
164 pendingAnimDynamicCfgCallbacks_.erase(pid);
165 }
166 if (callbacks.empty()) {
167 return;
168 }
169
170 auto& hgmCore = HgmCore::Instance();
171 auto frameRateMgr = hgmCore.GetFrameRateMgr();
172 if (frameRateMgr == nullptr) {
173 return;
174 }
175 auto data = std::make_shared<RSHgmConfigData>();
176
177 auto screenType = frameRateMgr->GetCurScreenStrategyId();
178 auto settingMode = std::to_string(hgmCore.GetCurrentRefreshRateMode());
179 auto configData = hgmCore.GetPolicyConfigData();
180 if (configData != nullptr) {
181 auto dynamicSettingMap = configData->GetAceSceneDynamicSettingMap(screenType, settingMode);
182 for (auto& [animType, dynamicSetting] : dynamicSettingMap) {
183 for (auto& [animName, dynamicConfig] : dynamicSetting) {
184 data->AddAnimDynamicItem({
185 animType, animName, dynamicConfig.min, dynamicConfig.max, dynamicConfig.preferredFps});
186 }
187 }
188 }
189
190 if (configData != nullptr) {
191 for (auto item : configData->pageNameList_) {
192 data->AddPageName(item);
193 }
194 }
195
196 auto screen = hgmCore.GetActiveScreen();
197 if (screen != nullptr) {
198 data->SetPpi(screen->GetPpi());
199 data->SetXDpi(screen->GetXDpi());
200 data->SetYDpi(screen->GetYDpi());
201 }
202
203 for (auto& [pid, callback] : callbacks) {
204 HGM_LOGD("pid:%{public}d", pid);
205 callback->OnHgmConfigChanged(data);
206 }
207 }
208
SyncRefreshRateModeChangeCallback(int32_t refreshRateMode)209 void HgmConfigCallbackManager::SyncRefreshRateModeChangeCallback(int32_t refreshRateMode)
210 {
211 for (const auto& [_, callback] : refreshRateModeCallbacks_) {
212 if (callback) {
213 callback->OnHgmRefreshRateModeChanged(refreshRateMode);
214 }
215 }
216 }
217
SyncRefreshRateUpdateCallback(int32_t refreshRate)218 void HgmConfigCallbackManager::SyncRefreshRateUpdateCallback(int32_t refreshRate)
219 {
220 for (const auto& callback : refreshRateUpdateCallbacks_) {
221 if (callback.second != nullptr) {
222 callback.second->OnHgmRefreshRateUpdate(refreshRate);
223 }
224 }
225 }
226
SyncXComponentExpectedFrameRateCallback(pid_t pid,const std::string & xcomponentId,int32_t expectedFrameRate)227 void HgmConfigCallbackManager::SyncXComponentExpectedFrameRateCallback(
228 pid_t pid, const std::string& xcomponentId, int32_t expectedFrameRate)
229 {
230 HGM_LOGI("%{public}d:[%{public}s,%{public}d]", pid, xcomponentId.c_str(), expectedFrameRate);
231 if (expectedFrameRate == DESTROYED_XCOMPONENT_FRAMERATE) {
232 DestroyXComponent(pid, xcomponentId);
233 return;
234 }
235
236 if (expectedFrameRate < OLED_NULL_HZ) {
237 // invalid framerate
238 return;
239 }
240
241 // return if lastExpectedFrameRate == expectedFrameRate
242 if (auto iter = xcomponentExpectedFrameRate_.find(pid); iter != xcomponentExpectedFrameRate_.end()) {
243 auto& xcomponentIdFps = iter->second;
244 auto frameRateIter = xcomponentIdFps.find(xcomponentId);
245 if (frameRateIter != xcomponentIdFps.end() && frameRateIter->second == expectedFrameRate) {
246 return;
247 }
248 if (xcomponentIdFps.size() >= MAX_XCOMPONENT_ID_NUMS) {
249 HGM_LOGE("HgmConfigCallbackManager xcomponentIdNums is largest");
250 return;
251 }
252 }
253
254 // store framerate
255 xcomponentExpectedFrameRate_[pid][xcomponentId] = expectedFrameRate;
256
257 // cb
258 if (auto iter = xcomponentExpectedFrameRateCallbacks_.find(pid);
259 iter != xcomponentExpectedFrameRateCallbacks_.end()) {
260 for (auto& [listenerPid, cb] : iter->second) {
261 if (cb == nullptr) {
262 continue;
263 }
264 HGM_LOGI("notify %{public}d: %{public}d:[%{public}s,%{public}d]",
265 listenerPid, pid, xcomponentId.c_str(), expectedFrameRate);
266 cb->OnFrameRateLinkerExpectedFpsUpdate(pid, xcomponentId, expectedFrameRate);
267 }
268 }
269 }
270
UnRegisterHgmConfigChangeCallback(pid_t pid)271 void HgmConfigCallbackManager::UnRegisterHgmConfigChangeCallback(pid_t pid)
272 {
273 if (animDynamicCfgCallbacks_.find(pid) != animDynamicCfgCallbacks_.end()) {
274 animDynamicCfgCallbacks_.erase(pid);
275 HGM_LOGD("HgmConfigCallbackManager %{public}s : remove animDynamicCfgCallback", __func__);
276 }
277 if (pendingAnimDynamicCfgCallbacks_.find(pid) != pendingAnimDynamicCfgCallbacks_.end()) {
278 pendingAnimDynamicCfgCallbacks_.erase(pid);
279 HGM_LOGD("HgmConfigCallbackManager %{public}s : remove pendingAnimDynamicCfgCallback", __func__);
280 }
281
282 if (refreshRateModeCallbacks_.find(pid) != refreshRateModeCallbacks_.end()) {
283 refreshRateModeCallbacks_.erase(pid);
284 HGM_LOGD("HgmConfigCallbackManager %{public}s : remove refreshRateModeCallback", __func__);
285 }
286
287 if (refreshRateUpdateCallbacks_.find(pid) != refreshRateUpdateCallbacks_.end()) {
288 refreshRateUpdateCallbacks_.erase(pid);
289 HGM_LOGD("HgmConfigCallbackManager %{public}s : remove refreshRateUpdateCallback", __func__);
290 }
291
292 // clean xcomponent framerate cb
293 // app exit
294 if (auto iter = xcomponentExpectedFrameRate_.find(pid); iter != xcomponentExpectedFrameRate_.end()) {
295 for (auto& [xcomponentId, _] : iter->second) {
296 SyncXComponentExpectedFrameRateCallback(pid, xcomponentId, OLED_NULL_HZ);
297 }
298 xcomponentExpectedFrameRate_.erase(pid);
299 }
300
301 // game server exit
302 for (auto iter = xcomponentExpectedFrameRateCallbacks_.begin();
303 iter != xcomponentExpectedFrameRateCallbacks_.end();) {
304 auto& listenerPidCb = iter->second;
305 listenerPidCb.erase(pid);
306 if (listenerPidCb.empty()) {
307 iter = xcomponentExpectedFrameRateCallbacks_.erase(iter);
308 } else {
309 ++iter;
310 }
311 }
312 }
313
DestroyXComponent(pid_t pid,const std::string & xcomponentId)314 void HgmConfigCallbackManager::DestroyXComponent(pid_t pid, const std::string& xcomponentId)
315 {
316 HGM_LOGI("Destroy XComponent: %{public}d:%{public}s", pid, xcomponentId.c_str());
317 SyncXComponentExpectedFrameRateCallback(pid, xcomponentId, OLED_NULL_HZ);
318
319 if (auto iter = xcomponentExpectedFrameRate_.find(pid); iter != xcomponentExpectedFrameRate_.end()) {
320 iter->second.erase(xcomponentId);
321 }
322 }
323 } // namespace OHOS::Rosen
324