• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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