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