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_policy.h"
17 
18 #include <algorithm>
19 #include "action_charger.h"
20 #include "action_voltage.h"
21 #include "constants.h"
22 #include "file_operation.h"
23 #include "thermal_common.h"
24 #include "thermal_service.h"
25 #include "securec.h"
26 #include "ffrt_utils.h"
27 #include "string_operation.h"
28 
29 using namespace OHOS::AppExecFwk;
30 namespace OHOS {
31 namespace PowerMgr {
32 namespace {
33 constexpr const char* LEVEL_PATH = "/data/service/el0/thermal/config/configLevel";
34 const int MAX_PATH = 256;
35 }
36 
Init()37 bool ThermalPolicy::Init()
38 {
39     SortLevel();
40     auto tms = ThermalService::GetInstance();
41     if (tms == nullptr) {
42         return false;
43     }
44     RegisterObserver();
45     return true;
46 }
47 
OnSensorInfoReported(const TypeTempMap & info)48 void ThermalPolicy::OnSensorInfoReported(const TypeTempMap& info)
49 {
50     typeTempMap_ = info;
51     LevelDecision();
52     WriteLevel();
53     PolicyDecision();
54 }
55 
ExecutePolicy()56 void ThermalPolicy::ExecutePolicy()
57 {
58     LevelDecision();
59     PolicyDecision();
60 }
61 
SetPolicyMap(PolicyConfigMap & pcm)62 void ThermalPolicy::SetPolicyMap(PolicyConfigMap& pcm)
63 {
64     clusterPolicyMap_ = pcm;
65 }
66 
SetSensorClusterMap(SensorClusterMap & scm)67 void ThermalPolicy::SetSensorClusterMap(SensorClusterMap& scm)
68 {
69     sensorClusterMap_ = scm;
70 }
71 
GetClusterLevelMap()72 std::map<std::string, uint32_t> ThermalPolicy::GetClusterLevelMap()
73 {
74     return clusterLevelMap_;
75 }
76 
77 
SortLevel()78 void ThermalPolicy::SortLevel()
79 {
80     for (auto clusterPolicy = clusterPolicyMap_.begin(); clusterPolicy != clusterPolicyMap_.end(); clusterPolicy++) {
81         sort(clusterPolicy->second.begin(), clusterPolicy->second.end(), LevelCompare);
82     }
83 }
84 
RegisterObserver()85 void ThermalPolicy::RegisterObserver()
86 {
87     ThermalObserver::Callback callback = [this](const TypeTempMap& info) { this->OnSensorInfoReported(info); };
88     auto tms = ThermalService::GetInstance();
89     tms->GetObserver()->SetRegisterCallback(callback);
90 }
91 
LevelDecision()92 void ThermalPolicy::LevelDecision()
93 {
94     for (auto cluster = sensorClusterMap_.begin(); cluster != sensorClusterMap_.end(); cluster++) {
95         THERMAL_HILOGD(COMP_SVC, "update [%{public}s] level", cluster->first.c_str());
96         cluster->second->UpdateThermalLevel(typeTempMap_);
97         uint32_t level = cluster->second->GetCurrentLevel();
98         clusterLevelMap_[cluster->first] = level;
99     }
100 }
101 
WriteLevel()102 void ThermalPolicy::WriteLevel()
103 {
104     auto tms = ThermalService::GetInstance();
105     if (!tms->GetSimulationXml()) {
106         return;
107     }
108     std::list<uint32_t> levelList;
109     int32_t ret = -1;
110     char levelBuf[MAX_PATH] = {0};
111     for (auto iter = clusterLevelMap_.begin(); iter != clusterLevelMap_.end(); iter++) {
112         levelList.push_back(iter->second);
113     }
114     auto level = *max_element(levelList.begin(), levelList.end());
115 
116     ret = snprintf_s(levelBuf, MAX_PATH, sizeof(levelBuf) - 1, LEVEL_PATH);
117     if (ret < EOK) {
118         return;
119     }
120     std::string valueString = std::to_string(level) + "\n";
121     ret = FileOperation::WriteFile(levelBuf, valueString, valueString.length());
122     if (ret != ERR_OK) {
123         return;
124     }
125 }
126 
PolicyDecision()127 void ThermalPolicy::PolicyDecision()
128 {
129     for (auto clusterPolicy = clusterPolicyMap_.begin(); clusterPolicy != clusterPolicyMap_.end(); clusterPolicy++) {
130         const std::string& clusterName = clusterPolicy->first;
131         const std::vector<PolicyConfig>& policyConfig = clusterPolicy->second;
132         if (clusterName.empty() || policyConfig.empty()) {
133             continue;
134         }
135         auto clusterIter = clusterLevelMap_.find(clusterName);
136         if (clusterIter == clusterLevelMap_.end()) {
137             continue;
138         }
139         uint32_t clusterCurrLev = clusterIter->second;
140         for (auto levelAction = policyConfig.rbegin(); levelAction != policyConfig.rend(); levelAction++) {
141             if (clusterCurrLev >= levelAction->level) {
142                 ActionDecision(levelAction->policyActionList);
143                 break;
144             }
145         }
146     }
147 
148     PrintPolicyState();
149 
150     if (!ActionExecution()) {
151         THERMAL_HILOGW(COMP_SVC, "failed to execute action");
152         return;
153     }
154 
155     ActionCharger::ExecuteCurrentLimit();
156     ActionVoltage::ExecuteVoltageLimit();
157 }
158 
ActionDecision(const std::vector<PolicyAction> & actionList)159 void ThermalPolicy::ActionDecision(const std::vector<PolicyAction>& actionList)
160 {
161     std::map<std::string, std::string> actionPolicyMap;
162     for (auto action = actionList.begin(); action != actionList.end(); action++) {
163         if (action->isProp && !StateMachineDecision(action->actionPropMap)) {
164             continue;
165         }
166         actionPolicyMap[action->actionName] = action->actionValue;
167     }
168     auto tms = ThermalService::GetInstance();
169     ThermalActionManager::ThermalActionMap actionMap = tms->GetActionManagerObj()->GetActionMap();
170     for (auto& actionPolicy : actionPolicyMap) {
171         auto actionIter = actionMap.find(actionPolicy.first);
172         if (actionIter == actionMap.end() || actionIter->second == nullptr) {
173             THERMAL_HILOGE(COMP_SVC, "can't find action [%{public}s] ability", actionPolicy.first.c_str());
174             continue;
175         }
176         actionIter->second->AddActionValue(actionPolicy.second);
177     }
178 }
179 
FindSubscribeActionValue()180 void ThermalPolicy::FindSubscribeActionValue()
181 {
182     THERMAL_HILOGD(COMP_SVC, "Enter");
183     auto tms = ThermalService::GetInstance();
184     if (tms == nullptr) {
185         THERMAL_HILOGI(COMP_SVC, "tms is nullptr");
186         return;
187     }
188     if (tms->GetObserver() ==nullptr) {
189         THERMAL_HILOGI(COMP_SVC, "tms->GetObserver() is nullptr");
190         return;
191     }
192 
193     tms->GetObserver()->FindSubscribeActionValue();
194 }
195 
StateMachineDecision(const std::map<std::string,std::string> & stateMap)196 bool ThermalPolicy::StateMachineDecision(const std::map<std::string, std::string>& stateMap)
197 {
198     auto tms = ThermalService::GetInstance();
199     for (auto prop = stateMap.begin(); prop != stateMap.end(); prop++) {
200         StateMachine::StateMachineMap stateMachineMap = tms->GetStateMachineObj()->GetStateCollectionMap();
201         auto stateIter = stateMachineMap.find(prop->first);
202         if (stateIter == stateMachineMap.end() || stateIter->second == nullptr) {
203             THERMAL_HILOGE(COMP_SVC, "can't find state machine [%{public}s]", prop->first.c_str());
204             return false;
205         }
206         if (stateIter->second->DecideState(prop->second)) {
207             continue;
208         } else {
209             return false;
210         }
211     }
212     return true;
213 }
214 
ActionExecution()215 bool ThermalPolicy::ActionExecution()
216 {
217     auto tms = ThermalService::GetInstance();
218     auto actionMgr = tms->GetActionManagerObj();
219     if (actionMgr == nullptr) {
220         return false;
221     }
222 
223     ThermalActionManager::ThermalActionMap actionMap = actionMgr->GetActionMap();
224     for (auto iter = actionMap.begin(); iter != actionMap.end(); iter++) {
225         iter->second->Execute();
226     }
227 
228     FFRTUtils::SubmitTask([this] {
229         return FindSubscribeActionValue();
230     });
231     return true;
232 }
233 
PrintPolicyState()234 void ThermalPolicy::PrintPolicyState()
235 {
236     std::string levInfo = "";
237     for (auto clusterIter = clusterLevelMap_.begin(); clusterIter != clusterLevelMap_.end(); clusterIter++) {
238         levInfo.append(clusterIter->first).append("-").append(std::to_string(clusterIter->second)).append(" ");
239     }
240     auto tms = ThermalService::GetInstance();
241     tms->GetObserver()->UpdatePolicyState(levInfo);
242     THERMAL_HILOGD(COMP_SVC, "current level: %{public}s", levInfo.c_str());
243 }
244 
DumpLevel(std::string & result)245 void ThermalPolicy::DumpLevel(std::string& result)
246 {
247     for (auto iter = clusterLevelMap_.begin(); iter != clusterLevelMap_.end(); ++iter) {
248         result.append("name: ");
249         result.append(iter->first);
250         result.append("\t");
251         result.append("level: ");
252         result.append(std::to_string(iter->second));
253         result.append("\n");
254     }
255 }
256 
PrintPolicyAction(std::vector<PolicyAction> policyActionList,std::string & result)257 void ThermalPolicy::PrintPolicyAction(std::vector<PolicyAction> policyActionList, std::string& result)
258 {
259     for (auto iter = policyActionList.begin(); iter != policyActionList.end(); ++iter) {
260         result.append("actionName: ");
261         result.append(iter->actionName);
262         result.append("\t");
263         result.append("actionValue: ");
264         result.append(iter->actionValue);
265         result.append("\t");
266         for (auto it = iter->actionPropMap.begin(); it != iter->actionPropMap.end(); ++it) {
267             result.append(it->first);
268             result.append(": ");
269             result.append(it->second);
270             result.append("\t");
271         }
272         result.append("isProp: ");
273         result.append(std::to_string(iter->isProp));
274         result.append("\n");
275     }
276 }
277 
DumpPolicy(std::string & result)278 void ThermalPolicy::DumpPolicy(std::string& result)
279 {
280     for (auto iter = clusterPolicyMap_.begin(); iter != clusterPolicyMap_.end(); ++iter) {
281         result.append("name: ");
282         result.append(iter->first);
283         result.append("\t");
284         for (auto it = iter->second.begin(); it != iter->second.end(); ++it) {
285             result.append("level: ");
286             result.append(std::to_string(it->level));
287             result.append("\n");
288             PrintPolicyAction(it->policyActionList, result);
289             result.append("\n");
290         }
291         result.append("\n");
292     }
293 }
294 } // namespace PowerMgr
295 } // namespace OHOS
296