• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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_frame_voter.h"
17 
18 #include "hgm_core.h"
19 
20 namespace OHOS {
21 namespace Rosen {
22 namespace {
23 constexpr uint32_t DEFAULT_PRIORITY = 0;
24 constexpr uint32_t VOTER_SCENE_PRIORITY_BEFORE_PACKAGES = 1;
25 constexpr uint32_t VOTER_LTPO_PRIORITY_BEFORE_PACKAGES = 2;
26 // CAUTION: with priority
27 const std::string VOTER_NAME[] = {
28     "VOTER_THERMAL",
29     "VOTER_VIRTUALDISPLAY_FOR_CAR",
30     "VOTER_VIRTUALDISPLAY",
31     "VOTER_MUTIPHYSICALSCREEN",
32     "VOTER_MULTISELFOWNEDSCREEN",
33     "VOTER_POWER_MODE",
34     "VOTER_DISPLAY_ENGINE",
35     "VOTER_GAMES",
36     "VOTER_ANCO",
37 
38     "VOTER_PAGE_URL",
39     "VOTER_PACKAGES",
40     "VOTER_LTPO",
41     "VOTER_TOUCH",
42     "VOTER_POINTER",
43     "VOTER_SCENE",
44     "VOTER_VIDEO",
45     "VOTER_IDLE"
46 };
47 }
48 
HgmFrameVoter(HgmMultiAppStrategy & multiAppStrategy)49 HgmFrameVoter::HgmFrameVoter(HgmMultiAppStrategy& multiAppStrategy)
50     : voters_(std::begin(VOTER_NAME), std::end(VOTER_NAME)), multiAppStrategy_(multiAppStrategy)
51 {
52     HGM_LOGI("Construction of HgmFrameVoter");
53     for (auto& voter : voters_) {
54         voteRecord_[voter] = {{}, true};
55     }
56 }
57 
CleanVote(pid_t pid)58 void HgmFrameVoter::CleanVote(pid_t pid)
59 {
60     if (pidRecord_.count(pid) == 0) {
61         return;
62     }
63     HGM_LOGW("CleanVote: i am [%{public}d], i died, clean my votes please.", pid);
64     pidRecord_.erase(pid);
65 
66     for (auto& [voterName, voterInfo] : voteRecord_) {
67         for (auto iter = voterInfo.first.begin(); iter != voterInfo.first.end();) {
68             if (iter->pid == pid) {
69                 auto voter = iter->voterName;
70                 iter = voterInfo.first.erase(iter);
71                 MarkVoteChange(voter);
72                 break;
73             }
74             ++iter;
75         }
76     }
77 }
78 
DeliverVote(const VoteInfo & voteInfo,bool eventStatus)79 void HgmFrameVoter::DeliverVote(const VoteInfo& voteInfo, bool eventStatus)
80 {
81     RS_TRACE_NAME_FMT("Deliver voter:%s(pid:%d extInfo:%s), status:%u, value:[%d-%d]",
82         voteInfo.voterName.c_str(), voteInfo.pid, voteInfo.extInfo.c_str(),
83         eventStatus, voteInfo.min, voteInfo.max);
84     if (voteInfo.min > voteInfo.max) {
85         HGM_LOGW("HgmFrameRateManager:invalid vote %{public}s(%{public}d %{public}s):[%{public}d, %{public}d]",
86             voteInfo.voterName.c_str(), voteInfo.pid, voteInfo.extInfo.c_str(), voteInfo.min, voteInfo.max);
87         return;
88     }
89 
90     voteRecord_.try_emplace(voteInfo.voterName, std::pair<std::vector<VoteInfo>, bool>({{}, true}));
91     auto& vec = voteRecord_[voteInfo.voterName].first;
92 
93     auto voter = voteInfo.voterName != "VOTER_PACKAGES" ? voteInfo.voterName : "";
94 
95     // clear
96     if ((voteInfo.pid == 0) && (eventStatus == REMOVE_VOTE)) {
97         if (!vec.empty()) {
98             vec.clear();
99             MarkVoteChange(voter);
100         }
101         return;
102     }
103 
104     for (auto it = vec.begin(); it != vec.end(); it++) {
105         if ((*it).pid != voteInfo.pid) {
106             continue;
107         }
108 
109         if (eventStatus == REMOVE_VOTE) {
110             // remove
111             it = vec.erase(it);
112             MarkVoteChange(voter);
113             return;
114         }
115 
116         if ((*it).min != voteInfo.min || (*it).max != voteInfo.max) {
117             // modify
118             vec.erase(it);
119             vec.push_back(voteInfo);
120             MarkVoteChange(voter);
121         } else if (voteInfo.voterName == "VOTER_PACKAGES") {
122             // force update cause VOTER_PACKAGES is flag of safe_voter
123             MarkVoteChange(voter);
124         }
125         return;
126     }
127 
128     // add
129     if (eventStatus == ADD_VOTE) {
130         pidRecord_.insert(voteInfo.pid);
131         vec.push_back(voteInfo);
132         MarkVoteChange(voter);
133     }
134 }
135 
ProcessVoteLog(const VoteInfo & curVoteInfo,bool isSkip)136 void HgmFrameVoter::ProcessVoteLog(const VoteInfo& curVoteInfo, bool isSkip)
137 {
138     RS_TRACE_NAME_FMT("Process voter:%s(pid:%d), value:[%d-%d]%s",
139         curVoteInfo.voterName.c_str(), curVoteInfo.pid, curVoteInfo.min, curVoteInfo.max, isSkip ? " skip" : "");
140     HGM_LOGD("Process: %{public}s(%{public}d):[%{public}d, %{public}d]%{public}s",
141         curVoteInfo.voterName.c_str(), curVoteInfo.pid, curVoteInfo.min, curVoteInfo.max, isSkip ? " skip" : "");
142 }
143 
MergeLtpo2IdleVote(std::vector<std::string>::iterator & voterIter,VoteInfo & resultVoteInfo,VoteRange & mergedVoteRange)144 bool HgmFrameVoter::MergeLtpo2IdleVote(
145     std::vector<std::string>::iterator& voterIter, VoteInfo& resultVoteInfo, VoteRange& mergedVoteRange)
146 {
147     bool mergeSuccess = false;
148     bool existVoterLTPO = false;
149     // [VOTER_LTPO, VOTER_IDLE)
150     for (; voterIter != voters_.end() - 1; voterIter++) {
151         if (voteRecord_.find(*voterIter) == voteRecord_.end()) {
152             continue;
153         }
154         voteRecord_[*voterIter].second = true;
155         auto vec = voteRecord_[*voterIter].first;
156         if (vec.empty()) {
157             continue;
158         }
159 
160         VoteInfo curVoteInfo = vec.back();
161         if (!multiAppStrategy_.CheckPidValid(curVoteInfo.pid)) {
162             ProcessVoteLog(curVoteInfo, true);
163             continue;
164         }
165         if (checkVote_ != nullptr && !checkVote_(*voterIter, curVoteInfo)) {
166             ProcessVoteLog(curVoteInfo, true);
167             continue;
168         }
169         if ((isDragScene_ || NeedSkipVoterTouch(existVoterLTPO)) && curVoteInfo.voterName == "VOTER_TOUCH") {
170             continue;
171         }
172         if (curVoteInfo.voterName == "VOTER_LTPO") {
173             existVoterLTPO = true;
174         }
175         ProcessVoteLog(curVoteInfo, false);
176         if (mergeSuccess) {
177             mergedVoteRange.first = mergedVoteRange.first > curVoteInfo.min ? mergedVoteRange.first : curVoteInfo.min;
178             if (curVoteInfo.max >= mergedVoteRange.second) {
179                 mergedVoteRange.second = curVoteInfo.max;
180                 resultVoteInfo.Merge(curVoteInfo);
181             }
182         } else {
183             resultVoteInfo.Merge(curVoteInfo);
184             mergedVoteRange = {curVoteInfo.min, curVoteInfo.max};
185         }
186         mergeSuccess = true;
187     }
188     return mergeSuccess;
189 }
190 
ProcessVoteIter(std::vector<std::string>::iterator & voterIter,VoteInfo & resultVoteInfo,VoteRange & voteRange,bool & voterGamesEffective)191 bool HgmFrameVoter::ProcessVoteIter(std::vector<std::string>::iterator& voterIter,
192     VoteInfo& resultVoteInfo, VoteRange& voteRange, bool &voterGamesEffective)
193 {
194     VoteRange range;
195     VoteInfo info;
196     if (*voterIter == "VOTER_LTPO" && MergeLtpo2IdleVote(voterIter, info, range)) {
197         auto [mergeVoteRange, mergeVoteInfo] = HgmVoter::MergeRangeByPriority(voteRange, range);
198         if (mergeVoteInfo) {
199             resultVoteInfo.Merge(info);
200         }
201         if (mergeVoteRange) {
202             return true;
203         }
204     }
205 
206     auto& voter = *voterIter;
207     if (voteRecord_.find(voter) == voteRecord_.end()) {
208         return false;
209     }
210     voteRecord_[voter].second = true;
211     auto& voteInfos = voteRecord_[voter].first;
212     auto firstValidVoteInfoIter = std::find_if(voteInfos.begin(), voteInfos.end(), [this](auto& voteInfo) {
213         if (!multiAppStrategy_.CheckPidValid(voteInfo.pid)) {
214             ProcessVoteLog(voteInfo, true);
215             return false;
216         }
217         return true;
218     });
219     if (firstValidVoteInfoIter == voteInfos.end()) {
220         return false;
221     }
222     auto curVoteInfo = *firstValidVoteInfoIter;
223     if (checkVote_ != nullptr && !checkVote_(voter, curVoteInfo)) {
224         ProcessVoteLog(curVoteInfo, true);
225         return false;
226     }
227     if (voter == "VOTER_GAMES") {
228         voterGamesEffective = true;
229     }
230     ProcessVoteLog(curVoteInfo, false);
231     auto [mergeVoteRange, mergeVoteInfo] =
232         HgmVoter::MergeRangeByPriority(voteRange, {curVoteInfo.min, curVoteInfo.max});
233     if (mergeVoteInfo) {
234         resultVoteInfo.Merge(curVoteInfo);
235     }
236     if (mergeVoteRange) {
237         return true;
238     }
239     return false;
240 }
241 
ProcessVote(const std::string & curScreenStrategyId,ScreenId curScreenId,int32_t curRefreshRateMode)242 std::pair<VoteInfo, VoteRange> HgmFrameVoter::ProcessVote(const std::string& curScreenStrategyId,
243     ScreenId curScreenId, int32_t curRefreshRateMode)
244 {
245     if (updateVoteRule_ != nullptr) {
246         voters_ = std::vector<std::string>(std::begin(VOTER_NAME), std::end(VOTER_NAME));
247         updateVoteRule_(voters_);
248     }
249 
250     VoteInfo resultVoteInfo;
251     VoteRange voteRange = { OLED_MIN_HZ, OLED_MAX_HZ };
252     auto& [min, max] = voteRange;
253 
254     bool voterGamesEffective = false;
255     auto voterIter = voters_.begin();
256     for (; voterIter != voters_.end(); ++voterIter) {
257         if (ProcessVoteIter(voterIter, resultVoteInfo, voteRange, voterGamesEffective)) {
258             break;
259         }
260     }
261     voterGamesEffective_ = voterGamesEffective;
262     // update effective status
263     if (voterIter != voters_.end()) {
264         ++voterIter;
265         for (; voterIter != voters_.end(); ++voterIter) {
266             if (auto iter = voteRecord_.find(*voterIter); iter != voteRecord_.end()) {
267                 iter->second.second = false;
268             }
269         }
270     }
271     if (voteRecord_["VOTER_PACKAGES"].second || voteRecord_["VOTER_LTPO"].second) {
272         voteRecord_["VOTER_SCENE"].second = true;
273     }
274     HGM_LOGD("Process: Strategy:%{public}s Screen:%{public}d Mode:%{public}d -- VoteResult:{%{public}d-%{public}d}",
275         curScreenStrategyId.c_str(), static_cast<int>(curScreenId), curRefreshRateMode, min, max);
276     return {resultVoteInfo, voteRange};
277 }
278 } // namespace Rosen
279 } // namespace OHOS
280