blob: 9ca5148dd3cff931294077cf194419457ebd9641 [file] [log] [blame]
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -07001/*
2 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <cstdio>
32#include <cinttypes>
33#include <string>
34#include <dirent.h>
35#include <unordered_map>
36#include <fstream>
37
38#include <android-base/logging.h>
39#include "thermalCommon.h"
40
41#define MAX_LENGTH 50
42#define MAX_PATH (256)
43#define DEFAULT_HYSTERESIS 5000
44#define THERMAL_SYSFS "/sys/class/thermal/"
45#define TZ_DIR_NAME "thermal_zone"
46#define TZ_DIR_FMT "thermal_zone%d"
47#define TEMPERATURE_FILE_FORMAT "/sys/class/thermal/thermal_zone%d/temp"
48#define POLICY_FILE_FORMAT "/sys/class/thermal/thermal_zone%d/policy"
49#define TRIP_FILE_FORMAT "/sys/class/thermal/thermal_zone%d/trip_point_1_temp"
50#define HYST_FILE_FORMAT "/sys/class/thermal/thermal_zone%d/trip_point_1_hyst"
51#define USER_SPACE_POLICY "user_space"
52#define TZ_TYPE "type"
53#define CDEV_DIR_NAME "cooling_device"
54#define CDEV_DIR_FMT "cooling_device%d"
55#define CDEV_CUR_STATE_PATH "/sys/class/thermal/cooling_device%d/cur_state"
56#define CPU_USAGE_FILE "/proc/stat"
57#define CPU_ONLINE_FILE_FORMAT "/sys/devices/system/cpu/cpu%d/online"
58
59namespace android {
60namespace hardware {
61namespace thermal {
62namespace V2_0 {
63namespace implementation {
64
65static std::unordered_map<std::string, cdevType> cdev_map = {
66 {"thermal-cpufreq-0", cdevType::CPU},
67 {"thermal-cpufreq-1", cdevType::CPU},
68 {"thermal-cpufreq-2", cdevType::CPU},
69 {"thermal-cpufreq-3", cdevType::CPU},
70 {"thermal-cpufreq-4", cdevType::CPU},
71 {"thermal-cpufreq-5", cdevType::CPU},
72 {"thermal-cpufreq-6", cdevType::CPU},
73 {"thermal-cpufreq-7", cdevType::CPU},
74 {"thermal-cluster-7-4", cdevType::CPU},
75 {"cpu-isolate0", cdevType::CPU},
76 {"cpu-isolate1", cdevType::CPU},
77 {"cpu-isolate2", cdevType::CPU},
78 {"cpu-isolate3", cdevType::CPU},
79 {"cpu-isolate4", cdevType::CPU},
80 {"cpu-isolate5", cdevType::CPU},
81 {"cpu-isolate6", cdevType::CPU},
82 {"cpu-isolate7", cdevType::CPU},
83 {"thermal-devfreq-0", cdevType::GPU},
84 {"modem_tj", cdevType::MODEM},
85 {"cdsp", cdevType::NPU},
86 {"cdsp_hw", cdevType::NPU},
87 {"battery", cdevType::BATTERY},
88};
89
90ThermalCommon::ThermalCommon()
91{
92 LOG(DEBUG) << "Entering " << __func__;
93 ncpus = (int)sysconf(_SC_NPROCESSORS_CONF);
94 if (ncpus < 1)
95 LOG(ERROR) << "Error retrieving number of cores";
96}
97
98static int writeToFile(std::string_view path, std::string data)
99{
100 std::fstream outFile;
101
102 outFile.open(std::string(path).c_str(),
103 std::fstream::binary | std::fstream::out);
104 if (outFile.is_open()) {
105 LOG(DEBUG) << "writing: "<< data << " in path:" << path
106 << std::endl;
107 outFile << data;
108 outFile.close();
109 return data.length();
110 }
111
112 LOG(ERROR) << "Error opening file: "<< path << std::endl;
113 return -1;
114}
115
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800116static int readLineFromFile(std::string_view path, std::string& out)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700117{
118 char *fgets_ret;
119 FILE *fd;
120 int rv;
121 char buf[MAX_LENGTH];
122
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800123 out.clear();
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700124
125 fd = fopen(std::string(path).c_str(), "r");
126 if (fd == NULL) {
127 LOG(ERROR) << "Path:" << std::string(path) << " file open error.err:"
128 << strerror(errno) << std::endl;
129 return errno;
130 }
131
132 fgets_ret = fgets(buf, MAX_LENGTH, fd);
133 if (NULL != fgets_ret) {
134 rv = (int)strlen(buf);
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800135 out.append(buf, rv);
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700136 } else {
137 rv = ferror(fd);
138 }
139
140 fclose(fd);
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800141 out.erase(std::remove(out.begin(), out.end(), '\n'), out.end());
142 LOG(DEBUG) << "Path:" << std::string(path) << " Val:" << out << std::endl;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700143
144 return rv;
145}
146
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800147int ThermalCommon::readFromFile(std::string_view path, std::string& out)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700148{
149 return readLineFromFile(path, out);
150}
151
152static int get_tzn(std::string sensor_name)
153{
154 DIR *tdir = NULL;
155 struct dirent *tdirent = NULL;
156 int found = -1;
157 int tzn = 0;
158 char name[MAX_PATH] = {0};
159 char cwd[MAX_PATH] = {0};
160 int ret = 0;
161
162 if (!getcwd(cwd, sizeof(cwd)))
163 return found;
164
165 /* Change dir to read the entries. Doesnt work otherwise */
166 ret = chdir(THERMAL_SYSFS);
167 if (ret) {
168 LOG(ERROR) << "Unable to change to " << THERMAL_SYSFS << std::endl;
169 return found;
170 }
171 tdir = opendir(THERMAL_SYSFS);
172 if (!tdir) {
173 LOG(ERROR) << "Unable to open " << THERMAL_SYSFS << std::endl;
174 return found;
175 }
176
177 while ((tdirent = readdir(tdir))) {
178 std::string buf;
179
180 if (strncmp(tdirent->d_name, TZ_DIR_NAME,
181 strlen(TZ_DIR_NAME)) != 0)
182 continue;
183
184 snprintf(name, MAX_PATH, "%s%s/%s", THERMAL_SYSFS,
185 tdirent->d_name, TZ_TYPE);
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800186 ret = readLineFromFile(std::string_view(name), buf);
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700187 if (ret <= 0) {
188 LOG(ERROR) <<
189 "get_tzn: sensor name read error for tz:" <<
190 tdirent->d_name << std::endl;
191 continue;
192 }
193 if (!strncmp(buf.c_str(), sensor_name.c_str(),
194 sensor_name.length())) {
195 found = 1;
196 break;
197 }
198 }
199
200 if (found == 1) {
201 sscanf(tdirent->d_name, TZ_DIR_FMT, &tzn);
202 LOG(DEBUG) << "Sensor: " << sensor_name <<
203 " found at tz: " << tzn << std::endl;
204 found = tzn;
205 }
206
207 closedir(tdir);
208 /* Restore current working dir */
209 ret = chdir(cwd);
210
211 return found;
212}
213
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800214int ThermalCommon::initialize_sensor(struct target_therm_cfg& cfg, int sens_idx)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700215{
216 struct therm_sensor sensor;
217 int idx = 0;
218
219 sensor.tzn = get_tzn(cfg.sensor_list[sens_idx]);
220 if (sensor.tzn < 0) {
221 LOG(ERROR) << "No thermal zone for sensor: " <<
222 cfg.sensor_list[sens_idx] << ", ret:" <<
223 sensor.tzn << std::endl;
224 return -1;
225 }
226 if (cfg.type == TemperatureType::CPU)
227 sensor.thresh.name = sensor.t.name =
228 std::string("CPU") + std::to_string(sens_idx);
229 else
230 sensor.thresh.name = sensor.t.name = cfg.label;
231
232 if (cfg.type == TemperatureType::BCL_PERCENTAGE)
233 sensor.mulFactor = 1;
234 else
235 sensor.mulFactor = 1000;
236
237 sensor.sensor_name = cfg.sensor_list[sens_idx];
238 sensor.positiveThresh = cfg.positive_thresh_ramp;
239 sensor.lastThrottleStatus = sensor.t.throttlingStatus =
240 ThrottlingSeverity::NONE;
241 sensor.thresh.type = sensor.t.type = cfg.type;
242 sensor.thresh.vrThrottlingThreshold =
243 UNKNOWN_TEMPERATURE;
Ram Chandrasekarf61c6142020-08-31 15:05:42 -0700244 for (idx = 0; idx <= (size_t)ThrottlingSeverity::SHUTDOWN; idx++) {
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700245 sensor.thresh.hotThrottlingThresholds[idx] =
246 sensor.thresh.coldThrottlingThresholds[idx] =
247 UNKNOWN_TEMPERATURE;
248 }
249
250 if (cfg.throt_thresh != 0 && cfg.positive_thresh_ramp)
Ram Chandrasekarf61c6142020-08-31 15:05:42 -0700251 sensor.thresh.hotThrottlingThresholds[(size_t)ThrottlingSeverity::SEVERE] =
Ram Chandrasekarf020a1d2020-08-25 14:25:14 -0700252 cfg.throt_thresh / (float)sensor.mulFactor;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700253 else if (cfg.throt_thresh != 0 && !cfg.positive_thresh_ramp)
Ram Chandrasekarf61c6142020-08-31 15:05:42 -0700254 sensor.thresh.coldThrottlingThresholds[(size_t)ThrottlingSeverity::SEVERE] =
Ram Chandrasekarf020a1d2020-08-25 14:25:14 -0700255 cfg.throt_thresh / (float)sensor.mulFactor;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700256
257 if (cfg.shutdwn_thresh != 0 && cfg.positive_thresh_ramp)
Ram Chandrasekarf61c6142020-08-31 15:05:42 -0700258 sensor.thresh.hotThrottlingThresholds[(size_t)ThrottlingSeverity::SHUTDOWN] =
Ram Chandrasekarf020a1d2020-08-25 14:25:14 -0700259 cfg.shutdwn_thresh / (float)sensor.mulFactor;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700260 else if (cfg.shutdwn_thresh != 0 && !cfg.positive_thresh_ramp)
Ram Chandrasekarf61c6142020-08-31 15:05:42 -0700261 sensor.thresh.coldThrottlingThresholds[(size_t)ThrottlingSeverity::SHUTDOWN] =
Ram Chandrasekarf020a1d2020-08-25 14:25:14 -0700262 cfg.shutdwn_thresh / (float)sensor.mulFactor;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700263
264 if (cfg.vr_thresh != 0)
265 sensor.thresh.vrThrottlingThreshold =
Ram Chandrasekarf020a1d2020-08-25 14:25:14 -0700266 cfg.vr_thresh / (float)sensor.mulFactor;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700267 sens.push_back(sensor);
268 //read_temperature((struct therm_sensor *)sensor);
269
270 return 0;
271}
272
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800273int ThermalCommon::initializeCpuSensor(struct target_therm_cfg& cpu_cfg)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700274{
275 int cpu = 0;
276
277 for (;cpu < ncpus; cpu++) {
278 if (initialize_sensor(cpu_cfg, cpu) < 0)
279 return -1;
280 }
281
282 return 0;
283}
284
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800285int ThermalCommon::initThermalZones(std::vector<struct target_therm_cfg>& cfg)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700286{
287 std::vector<struct target_therm_cfg>::iterator it;
288
289 if (cfg.empty()) {
290 LOG(ERROR) << std::string(__func__) +":Invalid input";
291 return -1;
292 }
293
294 for (it = cfg.begin(); it != cfg.end(); it++)
295 {
296 if (it->type == TemperatureType::CPU) {
297 if (initializeCpuSensor(*it) < 0)
298 return -1;
299 continue;
300 }
301 if (initialize_sensor(*it, 0) < 0) {
302 return -1;
303 }
304 }
305
306 return sens.size();
307}
308
309int ThermalCommon::initCdev()
310{
311 DIR *tdir = NULL;
312 struct dirent *tdirent = NULL;
313 int cdevn = 0;
314 char name[MAX_PATH] = {0};
315 char cwd[MAX_PATH] = {0};
316 int ret = 0;
317
318 if (!getcwd(cwd, sizeof(cwd)))
319 return 0;
320
321 /* Change dir to read the entries. Doesnt work otherwise */
322 ret = chdir(THERMAL_SYSFS);
323 if (ret) {
324 LOG(ERROR) << "Unable to change to " << THERMAL_SYSFS << std::endl;
325 return 0;
326 }
327 tdir = opendir(THERMAL_SYSFS);
328 if (!tdir) {
329 LOG(ERROR) << "Unable to open " << THERMAL_SYSFS << std::endl;
330 return 0;
331 }
332
333 while ((tdirent = readdir(tdir))) {
334 std::string buf;
335 struct dirent *tzdirent;
336 std::unordered_map<std::string, cdevType>::iterator it;
337 struct therm_cdev cdevInst;
338
339 if (strncmp(tdirent->d_name, CDEV_DIR_NAME,
340 strlen(CDEV_DIR_NAME)) != 0)
341 continue;
342
343 snprintf(name, MAX_PATH, "%s%s/%s", THERMAL_SYSFS,
344 tdirent->d_name, TZ_TYPE);
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800345 ret = readLineFromFile(std::string_view(name), buf);
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700346 if (ret <= 0) {
347 LOG(ERROR) <<
348 "init_cdev: cdev type read error for cdev:" <<
349 tdirent->d_name << std::endl;
350 }
351 it = cdev_map.find(buf);
352 if (it == cdev_map.end())
353 continue;
354 sscanf(tdirent->d_name, CDEV_DIR_FMT, &cdevn);
355 LOG(DEBUG) << "cdev: " << it->first <<
356 " found at cdev number: " << cdevn << std::endl;
357 cdevInst.c.name = it->first;
358 cdevInst.c.type = it->second;
359 cdevInst.cdevn = cdevn;
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800360 read_cdev_state(cdevInst);
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700361 cdev.push_back(cdevInst);
362 }
363
364 closedir(tdir);
365 /* Restore current working dir */
366 ret = chdir(cwd);
367
368 return cdev.size();
369}
370
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800371int ThermalCommon::read_cdev_state(struct therm_cdev& cdev)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700372{
373 char file_name[MAX_PATH];
374 std::string buf;
Gopala Krishna Nuthaki774bf102022-03-17 17:55:17 +0530375 int ret = 0, ct = 0;
376 bool read_ok = false;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700377
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700378 snprintf(file_name, sizeof(file_name), CDEV_CUR_STATE_PATH,
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800379 cdev.cdevn);
Gopala Krishna Nuthaki774bf102022-03-17 17:55:17 +0530380 do {
381 ret = readLineFromFile(std::string(file_name), buf);
382 if (ret <= 0) {
383 LOG(ERROR) << "Cdev state read error:"<< ret <<
384 " for cdev: " << cdev.c.name;
385 return -1;
386 }
387 try {
388 cdev.c.value = std::stoi(buf, nullptr, 0);
389 read_ok = true;
390 }
391 catch (std::exception &err) {
392 LOG(ERROR) << "Cdev read stoi error:" << err.what()
393 << " cdev:" << cdev.c.name << " ID:"
394 << cdev.cdevn << " buf:" << buf <<
395 std::endl;
396 }
397 ct++;
398 } while (!read_ok && ct < RETRY_CT);
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800399 LOG(DEBUG) << "cdev Name:" << cdev.c.name << ". state:" <<
400 cdev.c.value << std::endl;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700401
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800402 return cdev.c.value;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700403}
404
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800405int ThermalCommon::estimateSeverity(struct therm_sensor& sensor)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700406{
407 int idx = 0;
408 ThrottlingSeverity severity = ThrottlingSeverity::NONE;
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800409 float temp = sensor.t.value;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700410
Ram Chandrasekarf61c6142020-08-31 15:05:42 -0700411 for (idx = (int)ThrottlingSeverity::SHUTDOWN; idx >= 0; idx--) {
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800412 /* If a particular threshold is hit already, check if the
413 * hysteresis is cleared before changing the severity */
414 if (idx == (int)sensor.t.throttlingStatus) {
415 if ((sensor.positiveThresh &&
416 !isnan(sensor.thresh.hotThrottlingThresholds[idx]) &&
417 temp >=
418 (sensor.thresh.hotThrottlingThresholds[idx] -
419 DEFAULT_HYSTERESIS / sensor.mulFactor)) ||
420 (!sensor.positiveThresh &&
421 !isnan(sensor.thresh.coldThrottlingThresholds[idx]) &&
422 temp <=
423 (sensor.thresh.coldThrottlingThresholds[idx] +
424 DEFAULT_HYSTERESIS / sensor.mulFactor)))
425 break;
426 continue;
427 }
428 if ((sensor.positiveThresh &&
429 !isnan(sensor.thresh.hotThrottlingThresholds[idx]) &&
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700430 temp >=
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800431 sensor.thresh.hotThrottlingThresholds[idx]) ||
432 (!sensor.positiveThresh &&
433 !isnan(sensor.thresh.coldThrottlingThresholds[idx]) &&
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700434 temp <=
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800435 sensor.thresh.coldThrottlingThresholds[idx]))
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700436 break;
437 }
438 if (idx >= 0)
Ram Chandrasekarf61c6142020-08-31 15:05:42 -0700439 severity = (ThrottlingSeverity)(idx);
Gopala Krishna Nuthaki774bf102022-03-17 17:55:17 +0530440 LOG(INFO) << "Sensor Name:" << sensor.t.name << "temp: " <<
441 temp << ". prev severity:" <<
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800442 (int)sensor.lastThrottleStatus << ". cur severity:" <<
443 (int)sensor.t.throttlingStatus << " New severity:" <<
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700444 (int)severity << std::endl;
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800445 if (severity == sensor.t.throttlingStatus)
446 return -1;
447 sensor.lastThrottleStatus = sensor.t.throttlingStatus;
448 sensor.t.throttlingStatus = severity;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700449
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800450 return (int)severity;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700451}
452
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800453int ThermalCommon::read_temperature(struct therm_sensor& sensor)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700454{
455 char file_name[MAX_PATH];
456 float temp;
457 std::string buf;
Gopala Krishna Nuthaki774bf102022-03-17 17:55:17 +0530458 int ret = 0, ct = 0;
459 bool read_ok = false;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700460
Gopala Krishna Nuthaki774bf102022-03-17 17:55:17 +0530461 do {
462 snprintf(file_name, sizeof(file_name), TEMPERATURE_FILE_FORMAT,
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800463 sensor.tzn);
Gopala Krishna Nuthaki774bf102022-03-17 17:55:17 +0530464 ret = readLineFromFile(std::string(file_name), buf);
465 if (ret <= 0) {
466 LOG(ERROR) << "Temperature read error:"<< ret <<
467 " for sensor " << sensor.t.name;
468 return -1;
469 }
470 try {
471 sensor.t.value = (float)std::stoi(buf, nullptr, 0) /
472 (float)sensor.mulFactor;
473 read_ok = true;
474 }
475 catch (std::exception &err) {
476 LOG(ERROR) << "Temperature buf stoi error: "
477 << err.what()
478 << " buf:" << buf << " sensor:"
479 << sensor.t.name << " TZ:" <<
480 sensor.tzn << std::endl;
481 }
482 ct++;
483 } while (!read_ok && ct < RETRY_CT);
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800484 LOG(DEBUG) << "Sensor Name:" << sensor.t.name << ". Temperature:" <<
485 (float)sensor.t.value << std::endl;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700486
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800487 return ret;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700488}
489
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800490void ThermalCommon::initThreshold(struct therm_sensor& sensor)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700491{
492 char file_name[MAX_PATH] = "";
493 std::string buf;
494 int ret = 0, idx;
495 ThrottlingSeverity severity = ThrottlingSeverity::NONE;
496 int next_trip, curr_trip, hyst_temp = 0;
497
498 LOG(DEBUG) << "Entering " <<__func__;
499 if (!sensor.positiveThresh) {
500 LOG(ERROR) << "negative temperature ramp for sensor:"<<
501 sensor.t.name;
502 return;
503 }
504 snprintf(file_name, sizeof(file_name), POLICY_FILE_FORMAT,
505 sensor.tzn);
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800506 ret = readLineFromFile(std::string(file_name), buf);
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700507 if (ret <= 0) {
508 LOG(ERROR) << "Policy read error:"<< ret <<
509 " for sensor " << sensor.t.name;
510 return;
511 }
512 if (buf != std::string(USER_SPACE_POLICY)) {
513 LOG(ERROR) << "Policy error:"<< buf << " sensor:" <<
514 sensor.t.name << std::endl;
515 return;
516 }
517
518 next_trip = UNKNOWN_TEMPERATURE;
Ram Chandrasekarf61c6142020-08-31 15:05:42 -0700519 for (idx = 0;idx <= (int)ThrottlingSeverity::SHUTDOWN; idx++) {
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700520 if (isnan(sensor.thresh.hotThrottlingThresholds[idx])
Ram Chandrasekarf61c6142020-08-31 15:05:42 -0700521 || idx <= (int)sensor.t.throttlingStatus)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700522 continue;
523
Ram Chandrasekarf020a1d2020-08-25 14:25:14 -0700524 next_trip = sensor.thresh.hotThrottlingThresholds[idx] *
525 sensor.mulFactor;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700526 break;
527 }
528
529 if (!isnan(next_trip)) {
530 LOG(DEBUG) << "Sensor: " << sensor.t.name << " high trip:"
531 << next_trip << std::endl;
532 snprintf(file_name, sizeof(file_name), TRIP_FILE_FORMAT,
533 sensor.tzn);
534 writeToFile(std::string_view(file_name), std::to_string(next_trip));
535 }
536 if (sensor.t.throttlingStatus != ThrottlingSeverity::NONE) {
537 curr_trip = sensor.thresh.hotThrottlingThresholds[
Ram Chandrasekarf61c6142020-08-31 15:05:42 -0700538 (int)sensor.t.throttlingStatus]
Ram Chandrasekarf020a1d2020-08-25 14:25:14 -0700539 * sensor.mulFactor;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700540 if (!isnan(next_trip))
541 hyst_temp = (next_trip - curr_trip) + DEFAULT_HYSTERESIS;
542 else
543 hyst_temp = DEFAULT_HYSTERESIS;
544 LOG(DEBUG) << "Sensor: " << sensor.t.name << " hysteresis:"
545 << hyst_temp << std::endl;
546 snprintf(file_name, sizeof(file_name), HYST_FILE_FORMAT,
547 sensor.tzn);
548 writeToFile(std::string_view(file_name), std::to_string(hyst_temp));
549 }
550
551 return;
552}
553
Ram Chandrasekar72110b52020-08-06 14:39:40 -0700554int ThermalCommon::get_cpu_usages(hidl_vec<CpuUsage>& list) {
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700555 int vals, cpu_num, online;
556 ssize_t read;
557 uint64_t user, nice, system, idle, active, total;
558 char *line = NULL;
559 size_t len = 0;
560 size_t cpu = 0;
561 char file_name[MAX_LENGTH];
562 FILE *file;
563 FILE *cpu_file;
564
Ram Chandrasekar72110b52020-08-06 14:39:40 -0700565 list.resize(ncpus);
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700566 file = fopen(CPU_USAGE_FILE, "r");
567 if (file == NULL) {
568 LOG(ERROR) << "failed to open:" << CPU_USAGE_FILE <<
569 " err:" << strerror(errno);
570 return -errno;
571 }
572
573 while ((read = getline(&line, &len, file)) != -1) {
574 if (strnlen(line, read) < 4 || strncmp(line, "cpu", 3) != 0 ||
575 !isdigit(line[3])) {
576 free(line);
577 line = NULL;
578 len = 0;
579 continue;
580 }
581 vals = sscanf(line, \
582 "cpu%d %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64, \
583 &cpu_num, &user, &nice, &system, &idle);
584
585 free(line);
586 line = NULL;
587 len = 0;
588
589 if (vals != 5 || cpu == ncpus) {
590 if (vals != 5) {
591 LOG(ERROR) <<
592 "failed to read CPU information from file: "
593 << strerror(errno);
594 } else {
595 LOG(ERROR) <<
596 "/proc/stat file has incorrect format.";
597 }
598 fclose(file);
599 return errno ? -errno : -EIO;
600 }
601
602 active = user + nice + system;
603 total = active + idle;
604
605 // Read online CPU information.
606 snprintf(file_name, MAX_LENGTH, CPU_ONLINE_FILE_FORMAT,
607 cpu_num);
608 cpu_file = fopen(file_name, "r");
609 online = 0;
610 if (cpu_file == NULL) {
611 LOG(ERROR) << "failed to open file:" << file_name <<
612 " err: " << strerror(errno);
613 fclose(file);
614 return -errno;
615 }
616 if (1 != fscanf(cpu_file, "%d", &online)) {
617 LOG(ERROR) << "failed to read CPU online information" << strerror(errno);
618 fclose(file);
619 fclose(cpu_file);
620 return errno ? -errno : -EIO;
621 }
622 fclose(cpu_file);
623
Ram Chandrasekar72110b52020-08-06 14:39:40 -0700624 list[cpu_num].name = std::string("CPU") + std::to_string(cpu_num);
625 list[cpu_num].active = active;
626 list[cpu_num].total = total;
627 list[cpu_num].isOnline = online;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700628 cpu++;
629 }
630 fclose(file);
631 if (cpu != ncpus) {
632 LOG(ERROR) <<"/proc/stat file has incorrect format.";
633 return -EIO;
634 }
635 return ncpus;
636}
637
638} // namespace implementation
639} // namespace V2_0
640} // namespace thermal
641} // namespace hardware
642} // namespace android