blob: 2870a7acd2855f08b4457b1c71e43bde6b10424e [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;
375 int ret = 0;
376
377 LOG(DEBUG) << "Entering " <<__func__;
378 snprintf(file_name, sizeof(file_name), CDEV_CUR_STATE_PATH,
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800379 cdev.cdevn);
380 ret = readLineFromFile(std::string(file_name), buf);
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700381 if (ret <= 0) {
382 LOG(ERROR) << "Cdev state read error:"<< ret <<
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800383 " for cdev: " << cdev.c.name;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700384 return -1;
385 }
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800386 cdev.c.value = std::stoi(buf, nullptr, 0);
387 LOG(DEBUG) << "cdev Name:" << cdev.c.name << ". state:" <<
388 cdev.c.value << std::endl;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700389
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800390 return cdev.c.value;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700391}
392
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800393int ThermalCommon::estimateSeverity(struct therm_sensor& sensor)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700394{
395 int idx = 0;
396 ThrottlingSeverity severity = ThrottlingSeverity::NONE;
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800397 float temp = sensor.t.value;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700398
Ram Chandrasekarf61c6142020-08-31 15:05:42 -0700399 for (idx = (int)ThrottlingSeverity::SHUTDOWN; idx >= 0; idx--) {
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800400 /* If a particular threshold is hit already, check if the
401 * hysteresis is cleared before changing the severity */
402 if (idx == (int)sensor.t.throttlingStatus) {
403 if ((sensor.positiveThresh &&
404 !isnan(sensor.thresh.hotThrottlingThresholds[idx]) &&
405 temp >=
406 (sensor.thresh.hotThrottlingThresholds[idx] -
407 DEFAULT_HYSTERESIS / sensor.mulFactor)) ||
408 (!sensor.positiveThresh &&
409 !isnan(sensor.thresh.coldThrottlingThresholds[idx]) &&
410 temp <=
411 (sensor.thresh.coldThrottlingThresholds[idx] +
412 DEFAULT_HYSTERESIS / sensor.mulFactor)))
413 break;
414 continue;
415 }
416 if ((sensor.positiveThresh &&
417 !isnan(sensor.thresh.hotThrottlingThresholds[idx]) &&
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700418 temp >=
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800419 sensor.thresh.hotThrottlingThresholds[idx]) ||
420 (!sensor.positiveThresh &&
421 !isnan(sensor.thresh.coldThrottlingThresholds[idx]) &&
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700422 temp <=
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800423 sensor.thresh.coldThrottlingThresholds[idx]))
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700424 break;
425 }
426 if (idx >= 0)
Ram Chandrasekarf61c6142020-08-31 15:05:42 -0700427 severity = (ThrottlingSeverity)(idx);
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800428 LOG(DEBUG) << "Sensor Name:" << sensor.t.name << ". prev severity:" <<
429 (int)sensor.lastThrottleStatus << ". cur severity:" <<
430 (int)sensor.t.throttlingStatus << " New severity:" <<
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700431 (int)severity << std::endl;
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800432 if (severity == sensor.t.throttlingStatus)
433 return -1;
434 sensor.lastThrottleStatus = sensor.t.throttlingStatus;
435 sensor.t.throttlingStatus = severity;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700436
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800437 return (int)severity;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700438}
439
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800440int ThermalCommon::read_temperature(struct therm_sensor& sensor)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700441{
442 char file_name[MAX_PATH];
443 float temp;
444 std::string buf;
445 int ret = 0;
446
447 LOG(DEBUG) << "Entering " <<__func__;
448 snprintf(file_name, sizeof(file_name), TEMPERATURE_FILE_FORMAT,
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800449 sensor.tzn);
450 ret = readLineFromFile(std::string(file_name), buf);
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700451 if (ret <= 0) {
452 LOG(ERROR) << "Temperature read error:"<< ret <<
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800453 " for sensor " << sensor.t.name;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700454 return -1;
455 }
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800456 sensor.t.value = (float)std::stoi(buf, nullptr, 0) / (float)sensor.mulFactor;
457 LOG(DEBUG) << "Sensor Name:" << sensor.t.name << ". Temperature:" <<
458 (float)sensor.t.value << std::endl;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700459
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800460 return ret;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700461}
462
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800463void ThermalCommon::initThreshold(struct therm_sensor& sensor)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700464{
465 char file_name[MAX_PATH] = "";
466 std::string buf;
467 int ret = 0, idx;
468 ThrottlingSeverity severity = ThrottlingSeverity::NONE;
469 int next_trip, curr_trip, hyst_temp = 0;
470
471 LOG(DEBUG) << "Entering " <<__func__;
472 if (!sensor.positiveThresh) {
473 LOG(ERROR) << "negative temperature ramp for sensor:"<<
474 sensor.t.name;
475 return;
476 }
477 snprintf(file_name, sizeof(file_name), POLICY_FILE_FORMAT,
478 sensor.tzn);
Ram Chandrasekardbc52fc2020-11-17 13:57:40 -0800479 ret = readLineFromFile(std::string(file_name), buf);
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700480 if (ret <= 0) {
481 LOG(ERROR) << "Policy read error:"<< ret <<
482 " for sensor " << sensor.t.name;
483 return;
484 }
485 if (buf != std::string(USER_SPACE_POLICY)) {
486 LOG(ERROR) << "Policy error:"<< buf << " sensor:" <<
487 sensor.t.name << std::endl;
488 return;
489 }
490
491 next_trip = UNKNOWN_TEMPERATURE;
Ram Chandrasekarf61c6142020-08-31 15:05:42 -0700492 for (idx = 0;idx <= (int)ThrottlingSeverity::SHUTDOWN; idx++) {
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700493 if (isnan(sensor.thresh.hotThrottlingThresholds[idx])
Ram Chandrasekarf61c6142020-08-31 15:05:42 -0700494 || idx <= (int)sensor.t.throttlingStatus)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700495 continue;
496
Ram Chandrasekarf020a1d2020-08-25 14:25:14 -0700497 next_trip = sensor.thresh.hotThrottlingThresholds[idx] *
498 sensor.mulFactor;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700499 break;
500 }
501
502 if (!isnan(next_trip)) {
503 LOG(DEBUG) << "Sensor: " << sensor.t.name << " high trip:"
504 << next_trip << std::endl;
505 snprintf(file_name, sizeof(file_name), TRIP_FILE_FORMAT,
506 sensor.tzn);
507 writeToFile(std::string_view(file_name), std::to_string(next_trip));
508 }
509 if (sensor.t.throttlingStatus != ThrottlingSeverity::NONE) {
510 curr_trip = sensor.thresh.hotThrottlingThresholds[
Ram Chandrasekarf61c6142020-08-31 15:05:42 -0700511 (int)sensor.t.throttlingStatus]
Ram Chandrasekarf020a1d2020-08-25 14:25:14 -0700512 * sensor.mulFactor;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700513 if (!isnan(next_trip))
514 hyst_temp = (next_trip - curr_trip) + DEFAULT_HYSTERESIS;
515 else
516 hyst_temp = DEFAULT_HYSTERESIS;
517 LOG(DEBUG) << "Sensor: " << sensor.t.name << " hysteresis:"
518 << hyst_temp << std::endl;
519 snprintf(file_name, sizeof(file_name), HYST_FILE_FORMAT,
520 sensor.tzn);
521 writeToFile(std::string_view(file_name), std::to_string(hyst_temp));
522 }
523
524 return;
525}
526
Ram Chandrasekar72110b52020-08-06 14:39:40 -0700527int ThermalCommon::get_cpu_usages(hidl_vec<CpuUsage>& list) {
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700528 int vals, cpu_num, online;
529 ssize_t read;
530 uint64_t user, nice, system, idle, active, total;
531 char *line = NULL;
532 size_t len = 0;
533 size_t cpu = 0;
534 char file_name[MAX_LENGTH];
535 FILE *file;
536 FILE *cpu_file;
537
Ram Chandrasekar72110b52020-08-06 14:39:40 -0700538 list.resize(ncpus);
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700539 file = fopen(CPU_USAGE_FILE, "r");
540 if (file == NULL) {
541 LOG(ERROR) << "failed to open:" << CPU_USAGE_FILE <<
542 " err:" << strerror(errno);
543 return -errno;
544 }
545
546 while ((read = getline(&line, &len, file)) != -1) {
547 if (strnlen(line, read) < 4 || strncmp(line, "cpu", 3) != 0 ||
548 !isdigit(line[3])) {
549 free(line);
550 line = NULL;
551 len = 0;
552 continue;
553 }
554 vals = sscanf(line, \
555 "cpu%d %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64, \
556 &cpu_num, &user, &nice, &system, &idle);
557
558 free(line);
559 line = NULL;
560 len = 0;
561
562 if (vals != 5 || cpu == ncpus) {
563 if (vals != 5) {
564 LOG(ERROR) <<
565 "failed to read CPU information from file: "
566 << strerror(errno);
567 } else {
568 LOG(ERROR) <<
569 "/proc/stat file has incorrect format.";
570 }
571 fclose(file);
572 return errno ? -errno : -EIO;
573 }
574
575 active = user + nice + system;
576 total = active + idle;
577
578 // Read online CPU information.
579 snprintf(file_name, MAX_LENGTH, CPU_ONLINE_FILE_FORMAT,
580 cpu_num);
581 cpu_file = fopen(file_name, "r");
582 online = 0;
583 if (cpu_file == NULL) {
584 LOG(ERROR) << "failed to open file:" << file_name <<
585 " err: " << strerror(errno);
586 fclose(file);
587 return -errno;
588 }
589 if (1 != fscanf(cpu_file, "%d", &online)) {
590 LOG(ERROR) << "failed to read CPU online information" << strerror(errno);
591 fclose(file);
592 fclose(cpu_file);
593 return errno ? -errno : -EIO;
594 }
595 fclose(cpu_file);
596
Ram Chandrasekar72110b52020-08-06 14:39:40 -0700597 list[cpu_num].name = std::string("CPU") + std::to_string(cpu_num);
598 list[cpu_num].active = active;
599 list[cpu_num].total = total;
600 list[cpu_num].isOnline = online;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700601 cpu++;
602 }
603 fclose(file);
604 if (cpu != ncpus) {
605 LOG(ERROR) <<"/proc/stat file has incorrect format.";
606 return -EIO;
607 }
608 return ncpus;
609}
610
611} // namespace implementation
612} // namespace V2_0
613} // namespace thermal
614} // namespace hardware
615} // namespace android