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