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