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 uint32_t tempDiffLevSize = static_cast<uint32_t>(tempDiffInfoList_.size());
59 if (tempDiffFlag_ && tempDiffLevSize != expectedLevSize) {
60 THERMAL_HILOGE(COMP_SVC, "temp diff sensor lev size mismatch");
61 return false;
62 }
63
64 return true;
65 }
66
UpdateThermalLevel(const TypeTempMap & typeTempInfo)67 void ThermalConfigSensorCluster::UpdateThermalLevel(const TypeTempMap& typeTempInfo)
68 {
69 std::vector<uint32_t> levelList;
70
71 if (!CheckState()) {
72 latestLevel_ = 0;
73 return;
74 }
75
76 CalculateSensorLevel(typeTempInfo, levelList);
77
78 if (levelList.empty()) {
79 return;
80 }
81
82 latestLevel_ = *std::max_element(levelList.begin(), levelList.end());
83 THERMAL_HILOGD(COMP_SVC, "final latestLevel = %{public}u", latestLevel_);
84 }
85
CheckState()86 bool ThermalConfigSensorCluster::CheckState()
87 {
88 if (stateMap_.empty()) {
89 return true;
90 }
91 auto tms = ThermalService::GetInstance();
92 for (auto prop = stateMap_.begin(); prop != stateMap_.end(); prop++) {
93 StateMachine::StateMachineMap stateMachineMap = tms->GetStateMachineObj()->GetStateCollectionMap();
94 auto stateIter = stateMachineMap.find(prop->first);
95 if (stateIter == stateMachineMap.end() || stateIter->second == nullptr) {
96 THERMAL_HILOGE(COMP_SVC, "can't find state machine [%{public}s]", prop->first.c_str());
97 return false;
98 }
99 if (stateIter->second->DecideState(prop->second)) {
100 continue;
101 } else {
102 return false;
103 }
104 }
105 return true;
106 }
107
CalculateSensorLevel(const TypeTempMap & typeTempInfo,std::vector<uint32_t> & levelList)108 void ThermalConfigSensorCluster::CalculateSensorLevel(const TypeTempMap& typeTempInfo,
109 std::vector<uint32_t>& levelList)
110 {
111 if (sensorInfolist_.empty()) {
112 return;
113 }
114
115 for (auto sensorInfo = sensorInfolist_.begin(); sensorInfo != sensorInfolist_.end(); ++sensorInfo) {
116 auto iter = typeTempInfo.find(sensorInfo->first);
117 if (iter == typeTempInfo.end()) {
118 continue;
119 }
120 uint32_t level = latestLevel_;
121 if (descFlag_) {
122 DescJudgment(sensorInfo->second, iter->second, level, typeTempInfo, sensorInfo->first);
123 levelList.push_back(level);
124 } else {
125 AscJudgment(sensorInfo->second, iter->second, level, typeTempInfo, sensorInfo->first);
126 levelList.push_back(level);
127 }
128 }
129 }
130
AscendLevelToThreshold(std::vector<LevelItem> & levItems,uint32_t & level,const int32_t & curTemp,const TypeTempMap & typeTempInfo,const std::string & type)131 void ThermalConfigSensorCluster::AscendLevelToThreshold(std::vector<LevelItem>& levItems, uint32_t& level,
132 const int32_t& curTemp, const TypeTempMap& typeTempInfo, const std::string& type)
133 {
134 for (uint32_t i = level; i < levItems.size(); i++) {
135 if (curTemp < levItems.at(i).threshold ||
136 !CheckExtraCondition(typeTempInfo, levItems.at(i).level, type, levItems, true)) {
137 break;
138 }
139 level = levItems.at(i).level;
140 }
141 }
142
DescendLevelToThresholdClr(std::vector<LevelItem> & levItems,uint32_t & level,const int32_t & curTemp,const TypeTempMap & typeTempInfo,const std::string & type)143 void ThermalConfigSensorCluster::DescendLevelToThresholdClr(std::vector<LevelItem>& levItems,
144 uint32_t& level, const int32_t& curTemp, const TypeTempMap& typeTempInfo, const std::string& type)
145 {
146 for (uint32_t i = level; i >= 1; i--) {
147 if (curTemp >= levItems.at(i - 1).thresholdClr &&
148 CheckExtraCondition(typeTempInfo, levItems.at(i - 1).level, type, levItems, false)) {
149 break;
150 }
151 level = (levItems.at(i - 1).level > 0) ? (levItems.at(i - 1).level - 1) : 0;
152 }
153 }
154
DescendLevelToThreshold(std::vector<LevelItem> & levItems,uint32_t & level,const int32_t & curTemp,const TypeTempMap & typeTempInfo,const std::string & type)155 void ThermalConfigSensorCluster::DescendLevelToThreshold(std::vector<LevelItem>& levItems,
156 uint32_t& level, const int32_t& curTemp, const TypeTempMap& typeTempInfo, const std::string& type)
157 {
158 for (uint32_t i = level; i >= 1; i--) {
159 if (curTemp < levItems.at(i - 1).thresholdClr ||
160 !CheckExtraCondition(typeTempInfo, levItems.at(i - 1).level, type, levItems, false)) {
161 level = (levItems.at(i - 1).level > 0) ? (levItems.at(i - 1).level - 1) : 0;
162 } else {
163 break;
164 }
165 }
166 }
167
AscendLevelToThresholdClr(std::vector<LevelItem> & levItems,uint32_t & level,const int32_t & curTemp,const TypeTempMap & typeTempInfo,const std::string & type)168 void ThermalConfigSensorCluster::AscendLevelToThresholdClr(std::vector<LevelItem>& levItems,
169 uint32_t& level, const int32_t& curTemp, const TypeTempMap& typeTempInfo, const std::string& type)
170 {
171 for (uint32_t i = level; i < levItems.size(); i++) {
172 if (curTemp >= levItems.at(i).threshold &&
173 CheckExtraCondition(typeTempInfo, levItems.at(i).level, type, levItems, true)) {
174 level = levItems.at(i).level;
175 } else {
176 break;
177 }
178 }
179 }
180
LevelUpwardsSearch(std::vector<LevelItem> & levItems,uint32_t & level,const int32_t & curTemp,const TypeTempMap & typeTempInfo,const std::string & type)181 void ThermalConfigSensorCluster::LevelUpwardsSearch(std::vector<LevelItem>& levItems,
182 uint32_t& level, const int32_t& curTemp, const TypeTempMap& typeTempInfo, const std::string& type)
183 {
184 for (uint32_t i = level; i < levItems.size(); i++) {
185 if (curTemp > levItems.at(i).threshold ||
186 !CheckExtraCondition(typeTempInfo, levItems.at(i).level, type, levItems, true)) {
187 break;
188 }
189 level = levItems.at(i).level;
190 }
191 }
192
LevelDownwardsSearch(std::vector<LevelItem> & levItems,uint32_t & level,const int32_t & curTemp,const TypeTempMap & typeTempInfo,const std::string & type)193 void ThermalConfigSensorCluster::LevelDownwardsSearch(std::vector<LevelItem>& levItems,
194 uint32_t& level, const int32_t& curTemp, const TypeTempMap& typeTempInfo, const std::string& type)
195 {
196 for (uint32_t i = level; i >= 1; i--) {
197 if (curTemp <= levItems.at(i - 1).thresholdClr &&
198 CheckExtraCondition(typeTempInfo, levItems.at(i - 1).level, type, levItems, false)) {
199 break;
200 }
201 level = (levItems.at(i - 1).level > 0) ? (levItems.at(i - 1).level - 1) : 0;
202 }
203 }
204
LevelDownwardsSearchWithThreshold(std::vector<LevelItem> & levItems,uint32_t & level,const int32_t & curTemp,const TypeTempMap & typeTempInfo,const std::string & type)205 void ThermalConfigSensorCluster::LevelDownwardsSearchWithThreshold(std::vector<LevelItem>& levItems,
206 uint32_t& level, const int32_t& curTemp, const TypeTempMap& typeTempInfo, const std::string& type)
207 {
208 for (uint32_t i = level; i >= 1; i--) {
209 if (curTemp > levItems.at(i - 1).thresholdClr ||
210 !CheckExtraCondition(typeTempInfo, levItems.at(i - 1).level, type, levItems, false)) {
211 level = (levItems.at(i - 1).level > 0) ? (levItems.at(i - 1).level - 1) : 0;
212 } else {
213 break;
214 }
215 }
216 }
217
LevelUpwardsSearchWithThreshold(std::vector<LevelItem> & levItems,uint32_t & level,const int32_t & curTemp,const TypeTempMap & typeTempInfo,const std::string & type)218 void ThermalConfigSensorCluster::LevelUpwardsSearchWithThreshold(std::vector<LevelItem>& levItems,
219 uint32_t& level, const int32_t& curTemp, const TypeTempMap& typeTempInfo, const std::string& type)
220 {
221 for (uint32_t i = level; i < levItems.size(); i++) {
222 if (curTemp <= levItems.at(i).threshold &&
223 CheckExtraCondition(typeTempInfo, levItems.at(i).level, type, levItems, true)) {
224 level = levItems.at(i).level;
225 } else {
226 break;
227 }
228 }
229 }
230
AscJudgment(std::vector<LevelItem> & levItems,const int32_t & curTemp,uint32_t & level,const TypeTempMap & typeTempInfo,const std::string & type)231 void ThermalConfigSensorCluster::AscJudgment(std::vector<LevelItem>& levItems, const int32_t& curTemp, uint32_t& level,
232 const TypeTempMap& typeTempInfo, const std::string& type)
233 {
234 if (level > 0 && level < levItems.size()) {
235 int32_t curDownTemp = levItems.at(level - 1).thresholdClr;
236 int32_t nextUptemp = levItems.at(level).threshold;
237 if (curTemp >= nextUptemp) {
238 AscendLevelToThreshold(levItems, level, curTemp, typeTempInfo, type);
239 } else if (curTemp < curDownTemp || !CheckExtraCondition(typeTempInfo, level, type, levItems, false)) {
240 DescendLevelToThresholdClr(levItems, level, curTemp, typeTempInfo, type);
241 }
242 } else if (level == levItems.size()) {
243 int32_t curDownTemp = levItems.at(level - 1).thresholdClr;
244 if (curTemp < curDownTemp || !CheckExtraCondition(typeTempInfo, level, type, levItems, false)) {
245 DescendLevelToThreshold(levItems, level, curTemp, typeTempInfo, type);
246 }
247 } else {
248 int32_t nextUptemp = levItems.at(level).threshold;
249 if (curTemp >= nextUptemp) {
250 AscendLevelToThresholdClr(levItems, level, curTemp, typeTempInfo, type);
251 }
252 }
253 }
254
DescJudgment(std::vector<LevelItem> & levItems,const int32_t & curTemp,uint32_t & level,const TypeTempMap & typeTempInfo,const std::string & type)255 void ThermalConfigSensorCluster::DescJudgment(std::vector<LevelItem>& levItems, const int32_t& curTemp, uint32_t& level,
256 const TypeTempMap& typeTempInfo, const std::string& type)
257 {
258 if (level != 0 && level < levItems.size()) {
259 int32_t curDownTemp = levItems.at(level - 1).thresholdClr;
260 int32_t nextUptemp = levItems.at(level).threshold;
261 if (curTemp <= nextUptemp) {
262 LevelUpwardsSearch(levItems, level, curTemp, typeTempInfo, type);
263 } else if (curTemp > curDownTemp || !CheckExtraCondition(typeTempInfo, level, type, levItems, false)) {
264 LevelDownwardsSearch(levItems, level, curTemp, typeTempInfo, type);
265 }
266 } else if (level == levItems.size()) {
267 int32_t curDownTemp = levItems.at(level - 1).thresholdClr;
268 if (curTemp > curDownTemp || !CheckExtraCondition(typeTempInfo, level, type, levItems, false)) {
269 LevelDownwardsSearchWithThreshold(levItems, level, curTemp, typeTempInfo, type);
270 }
271 } else {
272 int32_t nextUptemp = levItems.at(level).threshold;
273 if (curTemp <= nextUptemp) {
274 LevelUpwardsSearchWithThreshold(levItems, level, curTemp, typeTempInfo, type);
275 }
276 }
277 }
278
CheckExtraCondition(const TypeTempMap & typeTempInfo,uint32_t & level,const std::string & type,std::vector<LevelItem> & levItems,bool isCritical)279 bool ThermalConfigSensorCluster::CheckExtraCondition(const TypeTempMap& typeTempInfo, uint32_t& level,
280 const std::string& type, std::vector<LevelItem>& levItems, bool isCritical)
281 {
282 if (auxFlag_) {
283 if (!IsAuxSensorTrigger(typeTempInfo, level)) {
284 THERMAL_HILOGD(COMP_SVC, "aux sensor isn't satisfied, fallback");
285 return false;
286 }
287 }
288
289 if (rateFlag_) {
290 if (!IsTempRateTrigger(level, type, levItems, isCritical)) {
291 THERMAL_HILOGD(COMP_SVC, "temp rise rate isn't satisfied, fallback");
292 return false;
293 }
294 }
295
296 if (tempDiffFlag_ && !IsTempDiffTrigger(typeTempInfo, level)) {
297 THERMAL_HILOGD(COMP_SVC, "temp diff isn't satisfied, fallback");
298 return false;
299 }
300 return true;
301 }
302
IsTempRateTrigger(uint32_t & level,const std::string & type,std::vector<LevelItem> & levItems,bool & isCritical)303 bool ThermalConfigSensorCluster::IsTempRateTrigger(uint32_t& level, const std::string& type,
304 std::vector<LevelItem>& levItems, bool& isCritical)
305 {
306 if (level == 0) {
307 return true;
308 }
309 auto tms = ThermalService::GetInstance();
310 const auto& rateMap = tms->GetSubscriber()->GetSensorsRate();
311 auto rateIter = rateMap.find(type);
312 if (rateIter == rateMap.end()) {
313 return false;
314 }
315 ThermalStatus trend = GetRateTrend(levItems.at(level - 1).tempRiseRate, rateIter->second,
316 tms->GetSubscriber()->GetRateCount());
317 if (isCritical) {
318 return trend == ThermalStatus::STATUS_CRITICAL;
319 } else {
320 return trend != ThermalStatus::STATUS_IDEAL;
321 }
322 }
323
IsAuxSensorTrigger(const TypeTempMap & typeTempInfo,uint32_t & level)324 bool ThermalConfigSensorCluster::IsAuxSensorTrigger(const TypeTempMap& typeTempInfo, uint32_t& level)
325 {
326 if (level == 0) {
327 return true;
328 }
329 for (auto sensorInfo = auxSensorInfolist_.begin(); sensorInfo != auxSensorInfolist_.end(); ++sensorInfo) {
330 auto auxIter = typeTempInfo.find(sensorInfo->first);
331 if (auxIter == typeTempInfo.end()) {
332 return false;
333 }
334 int32_t lowerTemp = sensorInfo->second.at(level - 1).lowerTemp;
335 int32_t upperTemp = sensorInfo->second.at(level - 1).upperTemp;
336 if (auxIter->second >= lowerTemp && auxIter->second <= upperTemp) {
337 continue;
338 } else {
339 return false;
340 }
341 }
342 return true;
343 }
344
IsTempDiffTrigger(const TypeTempMap & typeTempInfo,uint32_t & level)345 bool ThermalConfigSensorCluster::IsTempDiffTrigger(const TypeTempMap& typeTempInfo, uint32_t& level)
346 {
347 if (level == 0) {
348 THERMAL_HILOGD(COMP_SVC, "initial level is zero, temp diff not triggered");
349 return true;
350 }
351 uint32_t levSize = static_cast<uint32_t>(tempDiffInfoList_.size());
352 if (level <= 0 || level > levSize) {
353 THERMAL_HILOGE(COMP_SVC, "target level or level size is illegal.");
354 return false;
355 }
356 sort(tempDiffInfoList_.begin(), tempDiffInfoList_.end(),
357 [](const TempDiffItem& t1, const TempDiffItem& t2) {
358 return t1.level < t2.level;
359 });
360 auto& tempDiffInfo = tempDiffInfoList_.at(level - 1);
361 auto& sensor1 = tempDiffInfo.sensor1;
362 auto& sensor2 = tempDiffInfo.sensor2;
363
364 std::map<std::string, int>::const_iterator ite1 = typeTempInfo.end();
365 std::map<std::string, int>::const_iterator ite2 = typeTempInfo.end();
366 if ((ite1 = typeTempInfo.find(sensor1)) == typeTempInfo.end()
367 || (ite2 = typeTempInfo.find(sensor2)) == typeTempInfo.end()) {
368 THERMAL_HILOGE(COMP_SVC, "No temperature info about the target sensor: %{public}s and %{public}s.",
369 sensor1.c_str(), sensor2.c_str());
370 return false;
371 }
372
373 const auto& tempSensor1 = ite1->second;
374 const auto& tempSensor2 = ite2->second;
375 if ((tempSensor1 - tempSensor2) > tempDiffInfo.tempDiff) {
376 THERMAL_HILOGE(COMP_SVC, "temp diff of target sensors do not meet the requirements.");
377 return false;
378 }
379
380 THERMAL_HILOGD(COMP_SVC, "Temperature difference triggered successfully.");
381 return true;
382 }
383
GetRateTrend(const double targetRate,const std::deque<double> & rateList,const uint32_t & maxRateCount)384 ThermalStatus ThermalConfigSensorCluster::GetRateTrend(const double targetRate, const std::deque<double>& rateList,
385 const uint32_t& maxRateCount)
386 {
387 ThermalStatus trend = ThermalStatus::STATUS_STABLE;
388 double r1;
389 double r2;
390 if (rateList.size() < maxRateCount) {
391 return trend;
392 }
393
394 if (targetRate >= 0) {
395 r1 = targetRate;
396 r2 = 0;
397 } else {
398 r1 = 0;
399 r2 = targetRate;
400 }
401 bool isCritical = true;
402 bool isIdeal = true;
403
404 for (double rate : rateList) {
405 if (rate >= r2) {
406 isIdeal = false;
407 }
408 if (rate < r1) {
409 isCritical = false;
410 }
411 }
412
413 if (isCritical) {
414 trend = ThermalStatus::STATUS_CRITICAL;
415 } else if (isIdeal) {
416 trend = ThermalStatus::STATUS_IDEAL;
417 } else {
418 trend = ThermalStatus::STATUS_STABLE;
419 }
420 return trend;
421 }
422
GetCurrentLevel()423 uint32_t ThermalConfigSensorCluster::GetCurrentLevel()
424 {
425 return latestLevel_;
426 }
427
SetSensorLevelInfo(SensorInfoMap & sensorInfolist)428 void ThermalConfigSensorCluster::SetSensorLevelInfo(SensorInfoMap& sensorInfolist)
429 {
430 sensorInfolist_ = sensorInfolist;
431 }
432
SetAuxSensorLevelInfo(AuxSensorInfoMap & auxSensorInfolist)433 void ThermalConfigSensorCluster::SetAuxSensorLevelInfo(AuxSensorInfoMap& auxSensorInfolist)
434 {
435 auxSensorInfolist_ = auxSensorInfolist;
436 }
437
SetDescFlag(bool descflag)438 void ThermalConfigSensorCluster::SetDescFlag(bool descflag)
439 {
440 descFlag_ = descflag;
441 }
442
SetAuxFlag(bool auxflag)443 void ThermalConfigSensorCluster::SetAuxFlag(bool auxflag)
444 {
445 auxFlag_ = auxflag;
446 }
447
SetRateFlag(bool rateFlag)448 void ThermalConfigSensorCluster::SetRateFlag(bool rateFlag)
449 {
450 rateFlag_ = rateFlag;
451 }
452
SetTempDiffFlag(bool tempDiffFlag)453 void ThermalConfigSensorCluster::SetTempDiffFlag(bool tempDiffFlag)
454 {
455 tempDiffFlag_ = tempDiffFlag;
456 }
457
SetTempDiffInfo(TempDiffInfoList & tempDiffInfoList)458 void ThermalConfigSensorCluster::SetTempDiffInfo(TempDiffInfoList& tempDiffInfoList)
459 {
460 tempDiffInfoList_ = tempDiffInfoList;
461 }
462 } // namespace PowerMgr
463 } // namespace OHOS
464