1 /*
2  * Copyright (c) 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_device_mitigation.h"
17 
18 #include <cstdio>
19 #include <cstdlib>
20 #include <fcntl.h>
21 #include <fstream>
22 #include <unistd.h>
23 
24 #include "hdf_base.h"
25 #include "securec.h"
26 #include "hdf_log.h"
27 #include "thermal_log.h"
28 #include "thermal_hdf_config.h"
29 
30 #define HDF_LOG_TAG ThermalDeviceMitigation
31 
32 namespace OHOS {
33 namespace HDI {
34 namespace Thermal {
35 namespace V1_1 {
36 namespace {
37 const int32_t MAX_PATH = 256;
38 const int32_t MAX_BUF_PATH = 256;
39 const std::string SIM_CPU_FREQ_PATH = "/data/service/el0/thermal/cooling/cpu/freq";
40 const std::string GPU_FREQ_PATH = "/data/service/el0/thermal/cooling/gpu/freq";
41 const std::string BATTERY_CHARGER_CURRENT_PATH = "/data/service/el0/thermal/cooling/charger/current";
42 const std::string SIM_BATTERY_CURRENT_PATH = "/data/service/el0/thermal/cooling/battery/current";
43 const std::string BATTERY_VOLTAGE_PATH = "/data/service/el0/thermal/cooling/battery/voltage";
44 const std::string ACTUAL_BATTERY_CURRENT_PATH = "/sys/class/power_supply/battery/input_current_limited";
45 const int32_t NUM_ZERO = 0;
46 }
WriteSysfsFd(int32_t fd,std::string buf,size_t bytesSize)47 int32_t ThermalDeviceMitigation::WriteSysfsFd(int32_t fd, std::string buf, size_t bytesSize)
48 {
49     ssize_t pos = 0;
50     do {
51         ssize_t recever = write(fd, buf.c_str() + (size_t) pos, bytesSize - (size_t)pos);
52         if (recever < NUM_ZERO) {
53             return recever;
54         }
55         pos += recever;
56     } while ((ssize_t)bytesSize > pos);
57 
58     return (int32_t)bytesSize;
59 }
60 
OpenSysfsFile(std::string filePath,int32_t flags)61 int32_t ThermalDeviceMitigation::OpenSysfsFile(std::string filePath, int32_t flags)
62 {
63     int32_t ret;
64 
65     if (filePath.empty()) {
66         return HDF_ERR_INVALID_PARAM;
67     }
68 
69     ret = open(filePath.c_str(), flags);
70     if (ret < NUM_ZERO) {
71         THERMAL_HILOGE(COMP_HDI, "failed to open file");
72         return ret;
73     }
74     return ret;
75 }
76 
WriteSysfsFile(std::string filePath,std::string buf,size_t bytesSize)77 int32_t ThermalDeviceMitigation::WriteSysfsFile(std::string filePath, std::string buf, size_t bytesSize)
78 {
79     std::fstream file(filePath.c_str(), std::ios::out | std::ios::trunc);
80     file.close();
81     int32_t fd = OpenSysfsFile(filePath.c_str(), O_RDWR);
82     if (fd < NUM_ZERO) {
83         THERMAL_HILOGE(COMP_HDI, "failed to open SysfsFile");
84         return HDF_ERR_IO;
85     }
86     int32_t ret = WriteSysfsFd(fd, buf.c_str(), bytesSize);
87     close(fd);
88     return ret;
89 }
90 
SetFlag(bool flag)91 int32_t ThermalDeviceMitigation::SetFlag(bool flag)
92 {
93     flag_ = flag;
94     return HDF_SUCCESS;
95 }
96 
ExecuteCpuRequest(uint32_t freq,const std::string & path)97 int32_t ThermalDeviceMitigation::ExecuteCpuRequest(uint32_t freq, const std::string &path)
98 {
99     int32_t ret = HDF_FAILURE;
100     char freqBuf[MAX_PATH] = {0};
101     char nodeBuf[MAX_BUF_PATH] = {0};
102     if (access(path.c_str(), 0) != NUM_ZERO) {
103         return ret;
104     }
105     std::lock_guard<std::mutex> lock(mutex_);
106     if (snprintf_s(nodeBuf, MAX_BUF_PATH, sizeof(nodeBuf) - 1, "%s", path.c_str()) < EOK) {
107         return ret;
108     }
109     if (snprintf_s(freqBuf, MAX_PATH, sizeof(freqBuf) - 1, "%u", freq) < EOK) {
110         return ret;
111     }
112     if (WriteSysfsFile(nodeBuf, freqBuf, strlen(freqBuf)) > NUM_ZERO) {
113         THERMAL_HILOGI(COMP_HDI, "Set freq to %{public}d", freq);
114         ret = HDF_SUCCESS;
115     } else {
116         THERMAL_HILOGE(COMP_HDI, "failed to set freq");
117         ret = HDF_FAILURE;
118     }
119     return ret;
120 }
121 
CpuRequest(uint32_t freq)122 int32_t ThermalDeviceMitigation::CpuRequest(uint32_t freq)
123 {
124     int32_t ret = ExecuteCpuRequest(freq, SIM_CPU_FREQ_PATH);
125     if (ret != HDF_SUCCESS) {
126         return HDF_FAILURE;
127     }
128     return HDF_SUCCESS;
129 }
130 
ChargerRequest(uint32_t current)131 int32_t ThermalDeviceMitigation::ChargerRequest(uint32_t current)
132 {
133     int32_t ret = ExecuteChargerRequest(current, ACTUAL_BATTERY_CURRENT_PATH);
134     if (ret != HDF_SUCCESS) {
135         THERMAL_HILOGE(COMP_HDI, "failed to really set current");
136     }
137     ret = ExecuteChargerRequest(current, SIM_BATTERY_CURRENT_PATH);
138     if (ret != HDF_SUCCESS) {
139         return HDF_FAILURE;
140     }
141     return HDF_SUCCESS;
142 }
143 
GpuRequest(uint32_t freq)144 int32_t ThermalDeviceMitigation::GpuRequest(uint32_t freq)
145 {
146     int32_t ret = HDF_FAILURE;
147     char freqBuf[MAX_PATH] = {0};
148     char nodeBuf[MAX_BUF_PATH] = {0};
149 
150     std::lock_guard<std::mutex> lock(mutex_);
151     ret = snprintf_s(nodeBuf, MAX_BUF_PATH, sizeof(nodeBuf) - 1, "%s", GPU_FREQ_PATH.c_str());
152     if (ret < EOK) {
153         return ret;
154     }
155     ret = snprintf_s(freqBuf, MAX_PATH, sizeof(freqBuf) - 1, "%u", freq);
156     if (ret < EOK) {
157         return ret;
158     }
159     if (WriteSysfsFile(nodeBuf, freqBuf, strlen(freqBuf)) > NUM_ZERO) {
160         THERMAL_HILOGI(COMP_HDI, "Set freq to %{public}d", freq);
161         ret = HDF_SUCCESS;
162     } else {
163         THERMAL_HILOGE(COMP_HDI, "failed to set freq");
164         ret = HDF_FAILURE;
165     }
166     return ret;
167 }
168 
ExecuteChargerRequest(uint32_t current,const std::string & path)169 int32_t ThermalDeviceMitigation::ExecuteChargerRequest(uint32_t current, const std::string &path)
170 {
171     int32_t ret = HDF_FAILURE;
172     char currentBuf[MAX_PATH] = {0};
173     char nodeBuf[MAX_BUF_PATH] = {0};
174     if (access(path.c_str(), 0) != NUM_ZERO) {
175         return ret;
176     }
177 
178     std::lock_guard<std::mutex> lock(mutex_);
179     ret = snprintf_s(nodeBuf, MAX_BUF_PATH, sizeof(nodeBuf) - 1, "%s", path.c_str());
180     if (ret < EOK) {
181         return ret;
182     }
183     ret = snprintf_s(currentBuf, MAX_PATH, sizeof(currentBuf) - 1, "%u%s", current, "\n");
184     if (ret < EOK) {
185         return ret;
186     }
187     if (WriteSysfsFile(nodeBuf, currentBuf, strlen(currentBuf)) > NUM_ZERO) {
188         THERMAL_HILOGI(COMP_HDI, "Set current to %{public}d", current);
189         ret = HDF_SUCCESS;
190     } else {
191         THERMAL_HILOGE(COMP_HDI, "failed to set current");
192         ret = HDF_FAILURE;
193     }
194     return ret;
195 }
196 
BatteryCurrentRequest(uint32_t current)197 int32_t ThermalDeviceMitigation::BatteryCurrentRequest(uint32_t current)
198 {
199     int32_t ret = HDF_FAILURE;
200     char currentBuf[MAX_PATH] = {0};
201     char nodeBuf[MAX_BUF_PATH] = {0};
202 
203     std::lock_guard<std::mutex> lock(mutex_);
204     ret = snprintf_s(nodeBuf, MAX_BUF_PATH, sizeof(nodeBuf) - 1, "%s", SIM_BATTERY_CURRENT_PATH.c_str());
205     if (ret < EOK) {
206         return ret;
207     }
208     ret = snprintf_s(currentBuf, MAX_PATH, sizeof(currentBuf) - 1, "%u", current);
209     if (ret < EOK) {
210         return ret;
211     }
212     if (WriteSysfsFile(nodeBuf, currentBuf, strlen(currentBuf)) > NUM_ZERO) {
213         THERMAL_HILOGI(COMP_HDI, "Set current to %{public}d", current);
214         ret = HDF_SUCCESS;
215     } else {
216         THERMAL_HILOGE(COMP_HDI, "failed to set current");
217         ret = HDF_FAILURE;
218     }
219     return ret;
220 }
221 
BatteryVoltageRequest(uint32_t voltage)222 int32_t ThermalDeviceMitigation::BatteryVoltageRequest(uint32_t voltage)
223 {
224     int32_t ret = HDF_FAILURE;
225     char voltageBuf[MAX_PATH] = {0};
226     char voltageNode[MAX_BUF_PATH] = {0};
227 
228     std::lock_guard<std::mutex> lock(mutex_);
229     ret = snprintf_s(voltageNode, MAX_BUF_PATH, sizeof(voltageNode) - 1, "%s", BATTERY_VOLTAGE_PATH.c_str());
230     if (ret < EOK) {
231         return ret;
232     }
233     ret = snprintf_s(voltageBuf, MAX_PATH, sizeof(voltageBuf) - 1, "%u", voltage);
234     if (ret < EOK) {
235         return ret;
236     }
237     if (WriteSysfsFile(voltageNode, voltageBuf, strlen(voltageBuf)) > NUM_ZERO) {
238         THERMAL_HILOGI(COMP_HDI, "Set current to %{public}d", voltage);
239         ret = HDF_SUCCESS;
240     } else {
241         THERMAL_HILOGE(COMP_HDI, "failed to set current");
242         ret = HDF_FAILURE;
243     }
244     return ret;
245 }
246 
IsolateCpu(int32_t num)247 int32_t ThermalDeviceMitigation::IsolateCpu(int32_t num)
248 {
249     int32_t ret = HDF_FAILURE;
250     char valueBuf[MAX_PATH] = {0};
251     char isolateCpuPath[MAX_BUF_PATH] = {0};
252     std::string type = "soc";
253     std::string path;
254 
255     ret = ThermalHdfConfig::GetInstance().GetIsolateCpuNodePath(flag_, type, path);
256     if (ret != HDF_SUCCESS) {
257         THERMAL_HILOGE(COMP_HDI, "get Isolate Cpu config path is null");
258         return HDF_FAILURE;
259     }
260 
261     ret = snprintf_s(isolateCpuPath, MAX_BUF_PATH, sizeof(isolateCpuPath) - 1, "%s", path.c_str());
262     if (ret < EOK) {
263         return ret;
264     }
265 
266     ret = snprintf_s(valueBuf, MAX_PATH, sizeof(valueBuf) - 1, "%d", num);
267     if (ret < EOK) {
268         return ret;
269     }
270 
271     std::lock_guard<std::mutex> lock(mutex_);
272     if (WriteSysfsFile(isolateCpuPath, valueBuf, strlen(valueBuf)) > NUM_ZERO) {
273         THERMAL_HILOGI(COMP_HDI, "isolate cpu %{public}d", num);
274         ret = HDF_SUCCESS;
275     } else {
276         THERMAL_HILOGE(COMP_HDI, "failed to isolate cpu");
277         ret = HDF_FAILURE;
278     }
279     return ret;
280 }
281 } // V1_1
282 } // Thermal
283 } // HDI
284 } // OHOS
285