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