1 /*
2 * Copyright (c) 2021-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 "thermal_config_sensor_cluster.h"
17
18 #include <algorithm>
19
20 #include "string_operation.h"
21 #include "thermal_service.h"
22 #include "thermal_common.h"
23
24 namespace OHOS {
25 namespace PowerMgr {
26 namespace {
27 }
28
CheckStandard()29 bool ThermalConfigSensorCluster::CheckStandard()
30 {
31 if (sensorInfolist_.empty()) {
32 THERMAL_HILOGE(COMP_SVC, "sensor info is empty");
33 return false;
34 }
35 uint32_t expectedLevSize = static_cast<uint32_t>(sensorInfolist_.begin()->second.size());
36 for (auto sensorInfo = sensorInfolist_.begin(); sensorInfo != sensorInfolist_.end(); ++sensorInfo) {
37 uint32_t actualLevSize = static_cast<uint32_t>(sensorInfo->second.size());
38 if (actualLevSize != expectedLevSize) {
39 THERMAL_HILOGE(COMP_SVC, "sensor [%{public}s] lev size mismatch", sensorInfo->first.c_str());
40 return false;
41 }
42 for (uint32_t i = 0; i < sensorInfo->second.size(); ++i) {
43 uint32_t expectedLev = i + 1;
44 if (sensorInfo->second.at(i).level != expectedLev) {
45 THERMAL_HILOGE(COMP_SVC, "sensor [%{public}s] lev mismatch", sensorInfo->first.c_str());
46 return false;
47 }
48 }
49 }
50 for (auto sensorInfo = auxSensorInfolist_.begin(); sensorInfo != auxSensorInfolist_.end(); ++sensorInfo) {
51 uint32_t actualLevSize = static_cast<uint32_t>(sensorInfo->second.size());
52 if (actualLevSize == 0 || actualLevSize == expectedLevSize) {
53 continue;
54 }
55 THERMAL_HILOGE(COMP_SVC, "sensor [%{public}s] aux lev size mismatch", sensorInfo->first.c_str());
56 return false;
57 }
58 return true;
59 }
60
UpdateThermalLevel(const TypeTempMap & typeTempInfo)61 void ThermalConfigSensorCluster::UpdateThermalLevel(const TypeTempMap& typeTempInfo)
62 {
63 std::vector<uint32_t> levelList;
64
65 if (!CheckState()) {
66 latestLevel_ = 0;
67 return;
68 }
69
70 CalculateSensorLevel(typeTempInfo, levelList);
71
72 if (levelList.empty()) {
73 return;
74 }
75
76 latestLevel_ = *std::max_element(levelList.begin(), levelList.end());
77 THERMAL_HILOGD(COMP_SVC, "final latestLevel = %{public}u", latestLevel_);
78 }
79
CheckState()80 bool ThermalConfigSensorCluster::CheckState()
81 {
82 if (stateMap_.empty()) {
83 return true;
84 }
85 auto tms = ThermalService::GetInstance();
86 for (auto prop = stateMap_.begin(); prop != stateMap_.end(); prop++) {
87 StateMachine::StateMachineMap stateMachineMap = tms->GetStateMachineObj()->GetStateCollectionMap();
88 auto stateIter = stateMachineMap.find(prop->first);
89 if (stateIter == stateMachineMap.end() || stateIter->second == nullptr) {
90 THERMAL_HILOGE(COMP_SVC, "can't find state machine [%{public}s]", prop->first.c_str());
91 return false;
92 }
93 if (stateIter->second->DecideState(prop->second)) {
94 continue;
95 } else {
96 return false;
97 }
98 }
99 return true;
100 }
101
CalculateSensorLevel(const TypeTempMap & typeTempInfo,std::vector<uint32_t> & levelList)102 void ThermalConfigSensorCluster::CalculateSensorLevel(const TypeTempMap& typeTempInfo,
103 std::vector<uint32_t>& levelList)
104 {
105 if (sensorInfolist_.empty()) {
106 return;
107 }
108
109 for (auto sensorInfo = sensorInfolist_.begin(); sensorInfo != sensorInfolist_.end(); ++sensorInfo) {
110 auto iter = typeTempInfo.find(sensorInfo->first);
111 if (iter == typeTempInfo.end()) {
112 continue;
113 }
114 uint32_t level = latestLevel_;
115 if (descFlag_) {
116 DescJudgment(sensorInfo->second, iter->second, level);
117 CheckExtraCondition(typeTempInfo, level);
118 levelList.push_back(level);
119 } else {
120 AscJudgment(sensorInfo->second, iter->second, level);
121 CheckExtraCondition(typeTempInfo, level);
122 levelList.push_back(level);
123 }
124 }
125 }
126
AscendLevelToThreshold(std::vector<LevelItem> & levItems,uint32_t & level,uint32_t end,int32_t curTemp)127 void ThermalConfigSensorCluster::AscendLevelToThreshold(std::vector<LevelItem>& levItems, uint32_t& level,
128 uint32_t end, int32_t curTemp)
129 {
130 for (uint32_t i = level; i < end; i++) {
131 if (curTemp < levItems.at(i).threshold) {
132 break;
133 }
134 level = levItems.at(i).level;
135 }
136 }
137
DescendLevelToThresholdClr(std::vector<LevelItem> & levItems,uint32_t & level,int32_t curTemp)138 void ThermalConfigSensorCluster::DescendLevelToThresholdClr(std::vector<LevelItem>& levItems,
139 uint32_t& level, int32_t curTemp)
140 {
141 for (uint32_t i = level; i >= 1; i--) {
142 if (curTemp >= levItems.at(i - 1).thresholdClr) {
143 break;
144 }
145 level = (levItems.at(i - 1).level > 0) ? (levItems.at(i - 1).level - 1) : 0;
146 }
147 }
148
DescendLevelToThreshold(std::vector<LevelItem> & levItems,uint32_t & level,int32_t curTemp)149 void ThermalConfigSensorCluster::DescendLevelToThreshold(std::vector<LevelItem>& levItems,
150 uint32_t& level, int32_t curTemp)
151 {
152 for (uint32_t i = level; i >= 1; i--) {
153 if (curTemp < levItems.at(i - 1).thresholdClr) {
154 level = (levItems.at(i - 1).level > 0) ? (levItems.at(i - 1).level - 1) : 0;
155 } else {
156 break;
157 }
158 }
159 }
160
AscendLevelToThresholdClr(std::vector<LevelItem> & levItems,uint32_t & level,uint32_t end,int32_t curTemp)161 void ThermalConfigSensorCluster::AscendLevelToThresholdClr(std::vector<LevelItem>& levItems,
162 uint32_t& level, uint32_t end, int32_t curTemp)
163 {
164 for (uint32_t i = level; i < end; i++) {
165 if (curTemp >= levItems.at(i).threshold) {
166 level = levItems.at(i).level;
167 } else {
168 break;
169 }
170 }
171 }
172
LevelUpwardsSearch(std::vector<LevelItem> & levItems,uint32_t & level,uint32_t end,int32_t curTemp)173 void ThermalConfigSensorCluster::LevelUpwardsSearch(std::vector<LevelItem>& levItems,
174 uint32_t& level, uint32_t end, int32_t curTemp)
175 {
176 for (uint32_t i = level; i < end; i++) {
177 if (curTemp > levItems.at(i).threshold) {
178 break;
179 }
180 level = levItems.at(i).level;
181 }
182 }
183
LevelDownwardsSearch(std::vector<LevelItem> & levItems,uint32_t & level,int32_t curTemp)184 void ThermalConfigSensorCluster::LevelDownwardsSearch(std::vector<LevelItem>& levItems,
185 uint32_t& level, int32_t curTemp)
186 {
187 for (uint32_t i = level; i >= 1; i--) {
188 if (curTemp <= levItems.at(i - 1).thresholdClr) {
189 break;
190 }
191 level = (levItems.at(i - 1).level > 0) ? (levItems.at(i - 1).level - 1) : 0;
192 }
193 }
194
LevelDownwardsSearchWithThreshold(std::vector<LevelItem> & levItems,uint32_t & level,int32_t curTemp)195 void ThermalConfigSensorCluster::LevelDownwardsSearchWithThreshold(std::vector<LevelItem>& levItems,
196 uint32_t& level, int32_t curTemp)
197 {
198 for (uint32_t i = level; i >= 1; i--) {
199 if (curTemp > levItems.at(i - 1).thresholdClr) {
200 level = (levItems.at(i - 1).level > 0) ? (levItems.at(i - 1).level - 1) : 0;
201 } else {
202 break;
203 }
204 }
205 }
206
LevelUpwardsSearchWithThreshold(std::vector<LevelItem> & levItems,uint32_t & level,uint32_t end,int32_t curTemp)207 void ThermalConfigSensorCluster::LevelUpwardsSearchWithThreshold(std::vector<LevelItem>& levItems,
208 uint32_t& level, uint32_t end, int32_t curTemp)
209 {
210 for (uint32_t i = level; i < end; i++) {
211 if (curTemp <= levItems.at(i).threshold) {
212 level = levItems.at(i).level;
213 } else {
214 break;
215 }
216 }
217 }
218
AscJudgment(std::vector<LevelItem> & levItems,int32_t curTemp,uint32_t & level)219 void ThermalConfigSensorCluster::AscJudgment(std::vector<LevelItem>& levItems, int32_t curTemp, uint32_t& level)
220 {
221 if (level > 0 && level < levItems.size()) {
222 int32_t curDownTemp = levItems.at(level - 1).thresholdClr;
223 int32_t nextUptemp = levItems.at(level).threshold;
224 if (curTemp >= nextUptemp) {
225 AscendLevelToThreshold(levItems, level, levItems.size(), curTemp);
226 } else if (curTemp < curDownTemp) {
227 DescendLevelToThresholdClr(levItems, level, curTemp);
228 }
229 } else if (level == levItems.size()) {
230 int32_t curDownTemp = levItems.at(level - 1).thresholdClr;
231 if (curTemp < curDownTemp) {
232 DescendLevelToThreshold(levItems, level, curTemp);
233 }
234 } else {
235 int32_t nextUptemp = levItems.at(level).threshold;
236 if (curTemp >= nextUptemp) {
237 AscendLevelToThresholdClr(levItems, level, levItems.size(), curTemp);
238 }
239 }
240 }
241
DescJudgment(std::vector<LevelItem> & levItems,int32_t curTemp,uint32_t & level)242 void ThermalConfigSensorCluster::DescJudgment(std::vector<LevelItem>& levItems, int32_t curTemp, uint32_t& level)
243 {
244 if (level != 0 && level < levItems.size()) {
245 int32_t curDownTemp = levItems.at(level - 1).thresholdClr;
246 int32_t nextUptemp = levItems.at(level).threshold;
247 if (curTemp <= nextUptemp) {
248 LevelUpwardsSearch(levItems, level, levItems.size(), curTemp);
249 } else if (curTemp > curDownTemp) {
250 LevelDownwardsSearch(levItems, level, curTemp);
251 }
252 } else if (level == levItems.size()) {
253 int32_t curDownTemp = levItems.at(level - 1).thresholdClr;
254 if (curTemp > curDownTemp) {
255 LevelDownwardsSearchWithThreshold(levItems, level, curTemp);
256 }
257 } else {
258 int32_t nextUptemp = levItems.at(level).threshold;
259 if (curTemp <= nextUptemp) {
260 LevelUpwardsSearchWithThreshold(levItems, level, levItems.size(), curTemp);
261 }
262 }
263 }
264
CheckExtraCondition(const TypeTempMap & typeTempInfo,uint32_t & level)265 void ThermalConfigSensorCluster::CheckExtraCondition(const TypeTempMap& typeTempInfo, uint32_t& level)
266 {
267 if (auxFlag_) {
268 if (!IsAuxSensorTrigger(typeTempInfo, level)) {
269 THERMAL_HILOGD(COMP_SVC, "aux sensor isn't satisfied, fallback");
270 }
271 }
272
273 if (rateFlag_) {
274 if (!IsTempRateTrigger(level)) {
275 THERMAL_HILOGD(COMP_SVC, "temp rise rate isn't satisfied, fallback");
276 }
277 }
278 }
279
IsTempRateTrigger(uint32_t & level)280 bool ThermalConfigSensorCluster::IsTempRateTrigger(uint32_t& level)
281 {
282 if (level == 0) {
283 return true;
284 }
285 auto tms = ThermalService::GetInstance();
286 const auto& rateMap = tms->GetSubscriber()->GetSensorsRate();
287 for (auto sensorInfo = sensorInfolist_.begin(); sensorInfo != sensorInfolist_.end(); ++sensorInfo) {
288 auto rateIter = rateMap.find(sensorInfo->first);
289 if (rateIter == rateMap.end()) {
290 continue;
291 }
292 for (const auto& levItem : sensorInfo->second) {
293 if (levItem.level != level) {
294 continue;
295 }
296 if (rateIter->second > levItem.tempRiseRate) {
297 continue;
298 } else {
299 level = 0;
300 return false;
301 }
302 }
303 }
304 return true;
305 }
306
IsAuxSensorTrigger(const TypeTempMap & typeTempInfo,uint32_t & level)307 bool ThermalConfigSensorCluster::IsAuxSensorTrigger(const TypeTempMap& typeTempInfo, uint32_t& level)
308 {
309 if (level == 0) {
310 return true;
311 }
312 for (auto sensorInfo = auxSensorInfolist_.begin(); sensorInfo != auxSensorInfolist_.end(); ++sensorInfo) {
313 auto auxIter = typeTempInfo.find(sensorInfo->first);
314 if (auxIter == typeTempInfo.end()) {
315 continue;
316 }
317 int32_t lowerTemp = sensorInfo->second.at(level - 1).lowerTemp;
318 int32_t upperTemp = sensorInfo->second.at(level - 1).upperTemp;
319 if (auxIter->second >= lowerTemp && auxIter->second <= upperTemp) {
320 continue;
321 } else {
322 level = 0;
323 return false;
324 }
325 }
326 return true;
327 }
328
GetCurrentLevel()329 uint32_t ThermalConfigSensorCluster::GetCurrentLevel()
330 {
331 return latestLevel_;
332 }
333
SetSensorLevelInfo(SensorInfoMap & sensorInfolist)334 void ThermalConfigSensorCluster::SetSensorLevelInfo(SensorInfoMap& sensorInfolist)
335 {
336 sensorInfolist_ = sensorInfolist;
337 }
338
SetAuxSensorLevelInfo(AuxSensorInfoMap & auxSensorInfolist)339 void ThermalConfigSensorCluster::SetAuxSensorLevelInfo(AuxSensorInfoMap& auxSensorInfolist)
340 {
341 auxSensorInfolist_ = auxSensorInfolist;
342 }
343
SetDescFlag(bool descflag)344 void ThermalConfigSensorCluster::SetDescFlag(bool descflag)
345 {
346 descFlag_ = descflag;
347 }
348
SetAuxFlag(bool auxflag)349 void ThermalConfigSensorCluster::SetAuxFlag(bool auxflag)
350 {
351 auxFlag_ = auxflag;
352 }
353
SetRateFlag(bool rateFlag)354 void ThermalConfigSensorCluster::SetRateFlag(bool rateFlag)
355 {
356 rateFlag_ = rateFlag;
357 }
358 } // namespace PowerMgr
359 } // namespace OHOS
360