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