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