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