1 /*
2 * Copyright (c) 2021-2022 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 "string_operation.h"
27
28 using namespace OHOS::AppExecFwk;
29 namespace OHOS {
30 namespace PowerMgr {
31 namespace {
32 auto g_service = DelayedSpSingleton<ThermalService>::GetInstance();
33 TypeTempMap typeTempMap;
34 constexpr const char* LEVEL_PATH = "/data/service/el0/thermal/config/configLevel";
35 const int MAX_PATH = 256;
36 }
37
ThermalPolicy()38 ThermalPolicy::ThermalPolicy() {};
39
Init()40 bool ThermalPolicy::Init()
41 {
42 THERMAL_HILOGD(COMP_SVC, "Enter");
43 DumpConfigInfo();
44 SortLevel();
45 if (g_service == nullptr) {
46 return false;
47 }
48 handler_ = g_service->GetHandler();
49 RegisterObserver();
50 return true;
51 }
52
RegisterObserver()53 void ThermalPolicy::RegisterObserver()
54 {
55 THERMAL_HILOGD(COMP_SVC, "Enter");
56 ThermalObserver::Callback callback = std::bind(&ThermalPolicy::GetSensorInfomation, this, std::placeholders::_1);
57 g_service->GetObserver()->SetRegisterCallback(callback);
58 }
59
GetSensorInfomation(TypeTempMap info)60 void ThermalPolicy::GetSensorInfomation(TypeTempMap info)
61 {
62 typeTempMap = info;
63
64 LevelDecision();
65 WriteLevel();
66 PolicyDecision(clusterLevelMap_);
67 }
68
LevelDecision()69 void ThermalPolicy::LevelDecision()
70 {
71 for (auto cluster = msc_.begin(); cluster != msc_.end(); cluster++) {
72 cluster->second->UpdateThermalLevel(typeTempMap);
73 uint32_t level = cluster->second->GetCurrentLevel();
74 clusterLevelMap_[cluster->first] = level;
75 }
76 }
77
WriteLevel()78 void ThermalPolicy::WriteLevel()
79 {
80 std::list<uint32_t> levelList;
81 int32_t ret = -1;
82 char levelBuf[MAX_PATH] = {0};
83 for (auto iter = clusterLevelMap_.begin(); iter != clusterLevelMap_.end(); iter++) {
84 levelList.push_back(iter->second);
85 }
86 auto level = *max_element(levelList.begin(), levelList.end());
87
88 ret = snprintf_s(levelBuf, MAX_PATH, sizeof(levelBuf) - 1, LEVEL_PATH);
89 if (ret < EOK) {
90 return;
91 }
92 std::string valueString = std::to_string(level) + "\n";
93 ret = FileOperation::WriteFile(levelBuf, valueString, valueString.length());
94 if (ret != ERR_OK) {
95 return;
96 }
97 }
98
PolicyDecision(std::map<std::string,uint32_t> & clusterLevelMap)99 void ThermalPolicy::PolicyDecision(std::map<std::string, uint32_t> &clusterLevelMap)
100 {
101 THERMAL_HILOGD(COMP_SVC, "policySize = %{public}zu, clusterSize = %{public}zu",
102 clusterPolicyMap_.size(), clusterLevelMap.size());
103 for (auto clusterPolicy = clusterPolicyMap_.begin(); clusterPolicy != clusterPolicyMap_.end(); clusterPolicy++) {
104 if (clusterPolicy->first.empty() && clusterPolicy->second.empty()) {
105 continue;
106 }
107 auto clusterIter = clusterLevelMap.find(clusterPolicy->first);
108 if (clusterIter != clusterLevelMap.end()) {
109 for (auto levelAction = clusterPolicy->second.rbegin(); levelAction != clusterPolicy->second.rend();
110 levelAction++) {
111 if (clusterIter->second >= levelAction->level) {
112 ActionDecision(levelAction->vPolicyAction);
113 break;
114 }
115 }
116 } else {
117 continue;
118 }
119 }
120
121 /* Action Execute */
122 if (!ActionExecution()) {
123 THERMAL_HILOGW(COMP_SVC, "failed to execute action");
124 return;
125 }
126
127 ActionCharger::ExecuteCurrentLimit();
128 ActionVoltage::ExecuteVoltageLimit();
129 }
130
ActionDecision(std::vector<PolicyAction> & vAction)131 void ThermalPolicy::ActionDecision(std::vector<PolicyAction> &vAction)
132 {
133 THERMAL_HILOGD(COMP_SVC, "action.size=%{public}zu", vAction.size());
134 for (auto action = vAction.begin(); action != vAction.end(); action++) {
135 THERMAL_HILOGD(COMP_SVC, "actionName: %{public}s", action->actionName.c_str());
136 ThermalActionManager::ThermalActionMap actionMap = g_service->GetActionManagerObj()->GetActionMap();
137 auto actionIter = actionMap.find(action->actionName);
138 if (actionIter != actionMap.end()) {
139 THERMAL_HILOGD(COMP_SVC, "action Iter Name = %{public}s", actionIter->first.c_str());
140 if (actionIter->second == nullptr) {
141 THERMAL_HILOGE(COMP_SVC, "action instance is nullptr");
142 continue;
143 }
144 if (action->isProp) {
145 THERMAL_HILOGD(COMP_SVC, "start state decision");
146 if (StateMachineDecision(action->mActionProp)) {
147 actionIter->second->AddActionValue(action->actionValue);
148 actionIter->second->SetXmlScene(action->mActionProp.begin()->second, action->actionValue);
149 } else {
150 THERMAL_HILOGW(COMP_SVC, "failed to decide state");
151 }
152 } else {
153 THERMAL_HILOGD(COMP_SVC, "add action value");
154 actionIter->second->AddActionValue(action->actionValue);
155 }
156 } else {
157 THERMAL_HILOGE(COMP_SVC, "failed to find action");
158 continue;
159 }
160 }
161 }
162
FindSubscribeActionValue()163 void ThermalPolicy::FindSubscribeActionValue()
164 {
165 THERMAL_HILOGD(COMP_SVC, "Enter");
166 if (g_service == nullptr) {
167 THERMAL_HILOGI(COMP_SVC, "g_service is nullptr");
168 return;
169 }
170 if (g_service->GetObserver() ==nullptr) {
171 THERMAL_HILOGI(COMP_SVC, "g_service->GetObserver() is nullptr");
172 return;
173 }
174
175 g_service->GetObserver()->FindSubscribeActionValue();
176 }
177
StateMachineDecision(std::map<std::string,std::string> & stateMap)178 bool ThermalPolicy::StateMachineDecision(std::map<std::string, std::string> &stateMap)
179 {
180 THERMAL_HILOGD(COMP_SVC, "Enter");
181 bool ret = true;
182
183 for (auto prop = stateMap.begin(); prop != stateMap.end(); prop++) {
184 StateMachine::StateMachineMap stateMachineMap = g_service->GetStateMachineObj()->GetStateCollectionMap();
185 auto stateIter = stateMachineMap.find(prop->first);
186 THERMAL_HILOGD(COMP_SVC, "statename = %{public}s stateItername = %{public}s",
187 prop->first.c_str(), stateIter->first.c_str());
188 if (stateIter != stateMachineMap.end()) {
189 if (stateIter->second == nullptr) {
190 THERMAL_HILOGE(COMP_SVC, "state instance is nullptr");
191 continue;
192 }
193 if (stateIter->second->DecideState(prop->second)) {
194 continue;
195 } else {
196 ret = false;
197 break;
198 }
199 }
200 }
201 return ret;
202 }
203
ActionExecution()204 bool ThermalPolicy::ActionExecution()
205 {
206 THERMAL_HILOGD(COMP_SVC, "Enter");
207 auto actionMgr = g_service->GetActionManagerObj();
208 if (actionMgr == nullptr) {
209 return false;
210 }
211
212 if (!actionFallbackSet_.empty()) {
213 for (auto currentIter = actionFallbackSet_.begin(); currentIter != actionFallbackSet_.end(); currentIter++) {
214 preExecuteList_.insert(*currentIter);
215 }
216 actionFallbackSet_.clear();
217 }
218
219 ThermalActionManager::ThermalActionMap actionMap = actionMgr->GetActionMap();
220 for (auto iter = actionMap.begin(); iter != actionMap.end(); iter++) {
221 iter->second->Execute();
222 actionFallbackSet_.insert(iter->second);
223 }
224 handler_->SendEvent(ThermalsrvEventHandler::SEND_ACTION_HUB_LISTENER, 0, 0);
225 return true;
226 }
227
ActionFallbackDecision()228 bool ThermalPolicy::ActionFallbackDecision()
229 {
230 THERMAL_HILOGD(COMP_SVC, "Enter");
231 if (!preExecuteList_.empty()) {
232 for (auto preAction = preExecuteList_.begin(); preAction != preExecuteList_.end(); preAction++) {
233 auto currentAction = actionFallbackSet_.find(*preAction);
234 if (currentAction != actionFallbackSet_.end()) {
235 (*currentAction)->AddActionValue(FALLBACK_ACTION_VALUE);
236 (*currentAction)->Execute();
237 preExecuteList_.erase(preAction);
238 return true;
239 } else {
240 return false;
241 }
242 }
243 }
244 return false;
245 }
246
SortLevel()247 void ThermalPolicy::SortLevel()
248 {
249 THERMAL_HILOGD(COMP_SVC, "Enter");
250 for (auto clusterPolicy = clusterPolicyMap_.begin(); clusterPolicy != clusterPolicyMap_.end(); clusterPolicy++) {
251 sort(clusterPolicy->second.begin(), clusterPolicy->second.end(), LevelCompare);
252 }
253 }
254
SetPolicyMap(PolicyConfigMap & policyConfigMap)255 void ThermalPolicy::SetPolicyMap(PolicyConfigMap &policyConfigMap)
256 {
257 clusterPolicyMap_ = policyConfigMap;
258 }
259
SetSensorClusterMap(std::map<std::string,std::shared_ptr<ThermalConfigSensorCluster>> & msc)260 void ThermalPolicy::SetSensorClusterMap(std::map<std::string, std::shared_ptr<ThermalConfigSensorCluster>> &msc)
261 {
262 msc_ = msc;
263 }
264
GetClusterLevelMap()265 std::map<std::string, uint32_t> ThermalPolicy::GetClusterLevelMap()
266 {
267 return clusterLevelMap_;
268 }
269
DumpConfigInfo()270 void ThermalPolicy::DumpConfigInfo()
271 {
272 THERMAL_HILOGD(COMP_SVC, "Enter");
273 for (auto cluster : msc_) {
274 THERMAL_HILOGD(COMP_SVC, "name: %{public}s", cluster.first.c_str());
275 for (auto levelinfo : cluster.second->GetSensorInfoList()) {
276 THERMAL_HILOGD(COMP_SVC, "type %{public}s", levelinfo.first.c_str());
277 for (auto item : levelinfo.second) {
278 THERMAL_HILOGD(COMP_SVC,
279 "threshold:%{public}d, clr:%{public}d, tempRiseRate:%{public}f, level:%{public}d",
280 item.threshold, item.thresholdClr, item.tempRiseRate, item.level);
281 }
282 }
283 for (auto auxlevelinfo : cluster.second->GetAuxSensorInfoList()) {
284 THERMAL_HILOGD(COMP_SVC, "type: %{public}s", auxlevelinfo.first.c_str());
285 for (auto item : auxlevelinfo.second) {
286 THERMAL_HILOGD(COMP_SVC, "lowerTemp: %{public}d, upperTemp: %{public}d",
287 item.lowerTemp, item.upperTemp);
288 }
289 }
290 }
291
292 for (auto policy : clusterPolicyMap_) {
293 if (policy.first.empty() && policy.second.empty()) continue;
294 THERMAL_HILOGD(COMP_SVC, "clusterName = %{public}s", policy.first.c_str());
295 for (auto policyConfig : policy.second) {
296 THERMAL_HILOGD(COMP_SVC, "level = %{public}d", policyConfig.level);
297 for (auto action : policyConfig.vPolicyAction) {
298 THERMAL_HILOGD(COMP_SVC, "actionName = %{public}s, actionValue = %{public}s, prop = %{public}d",
299 action.actionName.c_str(), action.actionValue.c_str(), action.isProp);
300 for (auto prop : action.mActionProp) {
301 THERMAL_HILOGD(COMP_SVC, "propName = %{public}s, propValue = %{public}s",
302 prop.first.c_str(), prop.second.c_str());
303 }
304 }
305 }
306 }
307 }
308 } // namespace PowerMgr
309 } // namespace OHOS
310