1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #define ATRACE_TAG (ATRACE_TAG_THERMAL | ATRACE_TAG_HAL)
17
18 #include "thermal-helper.h"
19
20 #include <android-base/file.h>
21 #include <android-base/logging.h>
22 #include <android-base/properties.h>
23 #include <android-base/stringprintf.h>
24 #include <android-base/strings.h>
25 #include <utils/Trace.h>
26
27 #include <iterator>
28 #include <set>
29 #include <sstream>
30 #include <thread>
31 #include <vector>
32
33 namespace aidl {
34 namespace android {
35 namespace hardware {
36 namespace thermal {
37 namespace implementation {
38
39 constexpr std::string_view kThermalSensorsRoot("/sys/devices/virtual/thermal");
40 constexpr std::string_view kSensorPrefix("thermal_zone");
41 constexpr std::string_view kCoolingDevicePrefix("cooling_device");
42 constexpr std::string_view kThermalNameFile("type");
43 constexpr std::string_view kSensorPolicyFile("policy");
44 constexpr std::string_view kSensorTempSuffix("temp");
45 constexpr std::string_view kSensorTripPointTempZeroFile("trip_point_0_temp");
46 constexpr std::string_view kSensorTripPointHystZeroFile("trip_point_0_hyst");
47 constexpr std::string_view kUserSpaceSuffix("user_space");
48 constexpr std::string_view kCoolingDeviceCurStateSuffix("cur_state");
49 constexpr std::string_view kCoolingDeviceMaxStateSuffix("max_state");
50 constexpr std::string_view kCoolingDeviceState2powerSuffix("state2power_table");
51 constexpr std::string_view kConfigProperty("vendor.thermal.config");
52 constexpr std::string_view kConfigDefaultFileName("thermal_info_config.json");
53 constexpr std::string_view kThermalGenlProperty("persist.vendor.enable.thermal.genl");
54 constexpr std::string_view kThermalDisabledProperty("vendor.disable.thermalhal.control");
55
56 namespace {
57 using ::android::base::StringPrintf;
58
parseThermalPathMap(std::string_view prefix)59 std::unordered_map<std::string, std::string> parseThermalPathMap(std::string_view prefix) {
60 std::unordered_map<std::string, std::string> path_map;
61 std::unique_ptr<DIR, int (*)(DIR *)> dir(opendir(kThermalSensorsRoot.data()), closedir);
62 if (!dir) {
63 return path_map;
64 }
65
66 // std::filesystem is not available for vendor yet
67 // see discussion: aosp/894015
68 while (struct dirent *dp = readdir(dir.get())) {
69 if (dp->d_type != DT_DIR) {
70 continue;
71 }
72
73 if (!::android::base::StartsWith(dp->d_name, prefix.data())) {
74 continue;
75 }
76
77 std::string path = ::android::base::StringPrintf("%s/%s/%s", kThermalSensorsRoot.data(),
78 dp->d_name, kThermalNameFile.data());
79 std::string name;
80 if (!::android::base::ReadFileToString(path, &name)) {
81 PLOG(ERROR) << "Failed to read from " << path;
82 continue;
83 }
84
85 path_map.emplace(
86 ::android::base::Trim(name),
87 ::android::base::StringPrintf("%s/%s", kThermalSensorsRoot.data(), dp->d_name));
88 }
89
90 return path_map;
91 }
92
93 } // namespace
94
95 // dump additional traces for a given sensor
dumpTraces(std::string_view sensor_name)96 void ThermalHelperImpl::dumpTraces(std::string_view sensor_name) {
97 if (!(sensor_info_map_.count(sensor_name.data()) &&
98 sensor_status_map_.count(sensor_name.data()))) {
99 LOG(ERROR) << sensor_name << " not part of sensor_info_map_ or sensor_status_map_";
100 return;
101 }
102
103 // add trace for current sensor
104 const auto &sensor_status = sensor_status_map_.at(sensor_name.data());
105 ATRACE_INT((sensor_name.data() + std::string("-cached")).c_str(),
106 static_cast<int>(sensor_status.thermal_cached.temp));
107
108 const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
109 if (!sensor_info.virtual_sensor_info) {
110 return;
111 }
112
113 if (sensor_info.virtual_sensor_info->vt_estimator) {
114 sensor_info.virtual_sensor_info->vt_estimator->DumpTraces();
115 }
116
117 // dump traces for all dependent/linked sensors
118 for (const auto &linked_sensor : sensor_info.virtual_sensor_info->linked_sensors) {
119 dumpTraces(linked_sensor);
120 }
121 }
122
123 // If the cdev_ceiling is higher than CDEV max_state, cap the cdev_ceiling to max_state.
maxCoolingRequestCheck(std::unordered_map<std::string,BindedCdevInfo> * binded_cdev_info_map)124 void ThermalHelperImpl::maxCoolingRequestCheck(
125 std::unordered_map<std::string, BindedCdevInfo> *binded_cdev_info_map) {
126 for (auto &binded_cdev_info_pair : *binded_cdev_info_map) {
127 const auto &cdev_info = cooling_device_info_map_.at(binded_cdev_info_pair.first);
128 for (auto &cdev_ceiling : binded_cdev_info_pair.second.cdev_ceiling) {
129 if (cdev_ceiling > cdev_info.max_state) {
130 if (cdev_ceiling != std::numeric_limits<int>::max()) {
131 LOG(ERROR) << binded_cdev_info_pair.first << " cdev_ceiling:" << cdev_ceiling
132 << " is higher than max state:" << cdev_info.max_state;
133 }
134 cdev_ceiling = cdev_info.max_state;
135 }
136 }
137 }
138 }
139
140 /*
141 * Populate the sensor_name_to_file_map_ map by walking through the file tree,
142 * reading the type file and assigning the temp file path to the map. If we do
143 * not succeed, abort.
144 */
ThermalHelperImpl(const NotificationCallback & cb)145 ThermalHelperImpl::ThermalHelperImpl(const NotificationCallback &cb)
146 : thermal_watcher_(new ThermalWatcher(std::bind(&ThermalHelperImpl::thermalWatcherCallbackFunc,
147 this, std::placeholders::_1))),
148 cb_(cb) {
149 const std::string config_path =
150 "/vendor/etc/" +
151 ::android::base::GetProperty(kConfigProperty.data(), kConfigDefaultFileName.data());
152 bool thermal_throttling_disabled =
153 ::android::base::GetBoolProperty(kThermalDisabledProperty.data(), false);
154 bool ret = true;
155 Json::Value config;
156 if (!ParseThermalConfig(config_path, &config)) {
157 LOG(ERROR) << "Failed to read JSON config";
158 ret = false;
159 }
160
161 if (!ParseCoolingDevice(config, &cooling_device_info_map_)) {
162 LOG(ERROR) << "Failed to parse cooling device info config";
163 ret = false;
164 }
165
166 if (!ParseSensorInfo(config, &sensor_info_map_)) {
167 LOG(ERROR) << "Failed to parse sensor info config";
168 ret = false;
169 }
170
171 auto tz_map = parseThermalPathMap(kSensorPrefix.data());
172 if (!initializeSensorMap(tz_map)) {
173 LOG(ERROR) << "Failed to initialize sensor map";
174 ret = false;
175 }
176
177 auto cdev_map = parseThermalPathMap(kCoolingDevicePrefix.data());
178 if (!initializeCoolingDevices(cdev_map)) {
179 LOG(ERROR) << "Failed to initialize cooling device map";
180 ret = false;
181 }
182
183 if (!power_files_.registerPowerRailsToWatch(config)) {
184 LOG(ERROR) << "Failed to register power rails";
185 ret = false;
186 }
187
188 if (ret) {
189 if (!thermal_stats_helper_.initializeStats(config, sensor_info_map_,
190 cooling_device_info_map_, this)) {
191 LOG(FATAL) << "Failed to initialize thermal stats";
192 }
193 }
194
195 for (auto &name_status_pair : sensor_info_map_) {
196 sensor_status_map_[name_status_pair.first] = {
197 .severity = ThrottlingSeverity::NONE,
198 .prev_hot_severity = ThrottlingSeverity::NONE,
199 .prev_cold_severity = ThrottlingSeverity::NONE,
200 .last_update_time = boot_clock::time_point::min(),
201 .thermal_cached = {NAN, boot_clock::time_point::min()},
202 .override_status = {nullptr, false, false},
203 };
204
205 if (name_status_pair.second.throttling_info != nullptr) {
206 if (!thermal_throttling_.registerThermalThrottling(
207 name_status_pair.first, name_status_pair.second.throttling_info,
208 cooling_device_info_map_)) {
209 LOG(ERROR) << name_status_pair.first << " failed to register thermal throttling";
210 ret = false;
211 break;
212 }
213
214 // Update cooling device max state for default mode
215 maxCoolingRequestCheck(&name_status_pair.second.throttling_info->binded_cdev_info_map);
216
217 // Update cooling device max state for each profile mode
218 for (auto &cdev_throttling_profile_pair :
219 name_status_pair.second.throttling_info->profile_map) {
220 maxCoolingRequestCheck(&cdev_throttling_profile_pair.second);
221 }
222 }
223 // Check the virtual sensor settings are valid
224 if (name_status_pair.second.virtual_sensor_info != nullptr) {
225 // Check if sub sensor setting is valid
226 for (size_t i = 0;
227 i < name_status_pair.second.virtual_sensor_info->linked_sensors.size(); i++) {
228 if (!isSubSensorValid(
229 name_status_pair.second.virtual_sensor_info->linked_sensors[i],
230 name_status_pair.second.virtual_sensor_info->linked_sensors_type[i])) {
231 LOG(ERROR) << name_status_pair.first << "'s link sensor "
232 << name_status_pair.second.virtual_sensor_info->linked_sensors[i]
233 << " is invalid";
234 ret = false;
235 break;
236 }
237 }
238
239 // Check if the backup sensor is valid
240 if (!name_status_pair.second.virtual_sensor_info->backup_sensor.empty()) {
241 if (!isSubSensorValid(name_status_pair.second.virtual_sensor_info->backup_sensor,
242 SensorFusionType::SENSOR)) {
243 LOG(ERROR) << name_status_pair.first << "'s backup sensor "
244 << name_status_pair.second.virtual_sensor_info->backup_sensor
245 << " is invalid";
246 ret = false;
247 break;
248 }
249 }
250
251 // Check if the trigger sensor is valid
252 if (!name_status_pair.second.virtual_sensor_info->trigger_sensors.empty() &&
253 name_status_pair.second.is_watch) {
254 for (size_t i = 0;
255 i < name_status_pair.second.virtual_sensor_info->trigger_sensors.size(); i++) {
256 if (sensor_info_map_.count(
257 name_status_pair.second.virtual_sensor_info->trigger_sensors[i])) {
258 sensor_info_map_[name_status_pair.second.virtual_sensor_info
259 ->trigger_sensors[i]]
260 .is_watch = true;
261 } else {
262 LOG(ERROR)
263 << name_status_pair.first << "'s trigger sensor: "
264 << name_status_pair.second.virtual_sensor_info->trigger_sensors[i]
265 << " is invalid";
266 ret = false;
267 break;
268 }
269 }
270 }
271 }
272 // Check predictor info config
273 if (name_status_pair.second.predictor_info != nullptr) {
274 std::string predict_sensor_name = name_status_pair.second.predictor_info->sensor;
275 if (!(sensor_info_map_.count(predict_sensor_name))) {
276 LOG(ERROR) << name_status_pair.first << "'s predictor " << predict_sensor_name
277 << " is not part of sensor_info_map_";
278 ret = false;
279 break;
280 }
281
282 const auto &predictor_sensor_info = sensor_info_map_.at(predict_sensor_name);
283 if (predictor_sensor_info.virtual_sensor_info == nullptr ||
284 predictor_sensor_info.virtual_sensor_info->vt_estimator == nullptr) {
285 LOG(ERROR) << name_status_pair.first << "'s predictor " << predict_sensor_name
286 << " does not support prediction";
287 ret = false;
288 break;
289 }
290
291 if (name_status_pair.second.predictor_info->support_pid_compensation) {
292 std::vector<float> output_template;
293 size_t prediction_weight_count =
294 name_status_pair.second.predictor_info->prediction_weights.size();
295 // read predictor out to get the size of output vector
296 ::thermal::vtestimator::VtEstimatorStatus predict_check =
297 predictor_sensor_info.virtual_sensor_info->vt_estimator->GetAllPredictions(
298 &output_template);
299
300 if (predict_check != ::thermal::vtestimator::kVtEstimatorOk) {
301 LOG(ERROR) << "Failed to get output size of " << name_status_pair.first
302 << "'s predictor " << predict_sensor_name
303 << " GetAllPredictions ret: " << ret << ")";
304 ret = false;
305 break;
306 }
307
308 if (prediction_weight_count != output_template.size()) {
309 LOG(ERROR) << "Sensor [" << name_status_pair.first << "]: "
310 << "prediction weights size (" << prediction_weight_count
311 << ") doesn't match predictor [" << predict_sensor_name
312 << "]'s output size (" << output_template.size() << ")";
313 ret = false;
314 break;
315 }
316 }
317 }
318 }
319
320 if (!power_hal_service_.connect()) {
321 LOG(ERROR) << "Fail to connect to Power Hal";
322 } else {
323 power_hal_service_.updateSupportedPowerHints(sensor_info_map_);
324 }
325
326 if (thermal_throttling_disabled) {
327 if (ret) {
328 clearAllThrottling();
329 is_initialized_ = ret;
330 return;
331 } else {
332 sensor_info_map_.clear();
333 cooling_device_info_map_.clear();
334 return;
335 }
336 } else if (!ret) {
337 LOG(FATAL) << "ThermalHAL could not be initialized properly.";
338 }
339 is_initialized_ = ret;
340
341 const bool thermal_genl_enabled =
342 ::android::base::GetBoolProperty(kThermalGenlProperty.data(), false);
343
344 std::set<std::string> monitored_sensors;
345 initializeTrip(tz_map, &monitored_sensors, thermal_genl_enabled);
346
347 if (thermal_genl_enabled) {
348 thermal_watcher_->registerFilesToWatchNl(monitored_sensors);
349 } else {
350 thermal_watcher_->registerFilesToWatch(monitored_sensors);
351 }
352
353 // Need start watching after status map initialized
354 is_initialized_ = thermal_watcher_->startWatchingDeviceFiles();
355 if (!is_initialized_) {
356 LOG(FATAL) << "ThermalHAL could not start watching thread properly.";
357 }
358 }
359
getThermalZoneTypeById(int tz_id,std::string * type)360 bool getThermalZoneTypeById(int tz_id, std::string *type) {
361 std::string tz_type;
362 std::string path =
363 ::android::base::StringPrintf("%s/%s%d/%s", kThermalSensorsRoot.data(),
364 kSensorPrefix.data(), tz_id, kThermalNameFile.data());
365 LOG(INFO) << "TZ Path: " << path;
366 if (!::android::base::ReadFileToString(path, &tz_type)) {
367 LOG(ERROR) << "Failed to read sensor: " << tz_type;
368 return false;
369 }
370
371 // Strip the newline.
372 *type = ::android::base::Trim(tz_type);
373 LOG(INFO) << "TZ type: " << *type;
374 return true;
375 }
376
checkUpdateSensorForEmul(std::string_view target_sensor,const bool max_throttling)377 void ThermalHelperImpl::checkUpdateSensorForEmul(std::string_view target_sensor,
378 const bool max_throttling) {
379 // Force update all the sensors which are related to the target emul sensor
380 for (auto &[sensor_name, sensor_info] : sensor_info_map_) {
381 if (sensor_info.virtual_sensor_info == nullptr || !sensor_info.is_watch) {
382 continue;
383 }
384
385 const auto &linked_sensors = sensor_info.virtual_sensor_info->linked_sensors;
386 if (std::find(linked_sensors.begin(), linked_sensors.end(), target_sensor) ==
387 linked_sensors.end()) {
388 continue;
389 }
390
391 auto &sensor_status = sensor_status_map_.at(sensor_name.data());
392 sensor_status.override_status.max_throttling = max_throttling;
393 sensor_status.override_status.pending_update = true;
394
395 checkUpdateSensorForEmul(sensor_name, max_throttling);
396 }
397 }
398
emulTemp(std::string_view target_sensor,const float temp,const bool max_throttling)399 bool ThermalHelperImpl::emulTemp(std::string_view target_sensor, const float temp,
400 const bool max_throttling) {
401 LOG(INFO) << "Set " << target_sensor.data() << " emul_temp: " << temp
402 << " max_throttling: " << max_throttling;
403
404 std::lock_guard<std::shared_mutex> _lock(sensor_status_map_mutex_);
405
406 // Check the target sensor is valid
407 if (!sensor_status_map_.count(target_sensor.data())) {
408 LOG(ERROR) << "Cannot find target emul sensor: " << target_sensor.data();
409 return false;
410 }
411
412 auto &sensor_status = sensor_status_map_.at(target_sensor.data());
413
414 sensor_status.override_status.emul_temp.reset(new EmulTemp{temp, -1});
415 sensor_status.override_status.max_throttling = max_throttling;
416 sensor_status.override_status.pending_update = true;
417
418 checkUpdateSensorForEmul(target_sensor.data(), max_throttling);
419
420 thermal_watcher_->wake();
421 return true;
422 }
423
emulSeverity(std::string_view target_sensor,const int severity,const bool max_throttling)424 bool ThermalHelperImpl::emulSeverity(std::string_view target_sensor, const int severity,
425 const bool max_throttling) {
426 LOG(INFO) << "Set " << target_sensor.data() << " emul_severity: " << severity
427 << " max_throttling: " << max_throttling;
428
429 std::lock_guard<std::shared_mutex> _lock(sensor_status_map_mutex_);
430 // Check the target sensor is valid
431 if (!sensor_status_map_.count(target_sensor.data()) ||
432 !sensor_info_map_.count(target_sensor.data())) {
433 LOG(ERROR) << "Cannot find target emul sensor: " << target_sensor.data();
434 return false;
435 }
436 const auto &sensor_info = sensor_info_map_.at(target_sensor.data());
437
438 // Check the emul severity is valid
439 if (severity > static_cast<int>(kThrottlingSeverityCount)) {
440 LOG(ERROR) << "Invalid emul severity value " << severity;
441 return false;
442 }
443
444 const auto temp = sensor_info.hot_thresholds[severity] / sensor_info.multiplier;
445
446 auto &sensor_status = sensor_status_map_.at(target_sensor.data());
447
448 sensor_status.override_status.emul_temp.reset(new EmulTemp{temp, severity});
449 sensor_status.override_status.max_throttling = max_throttling;
450 sensor_status.override_status.pending_update = true;
451
452 checkUpdateSensorForEmul(target_sensor.data(), max_throttling);
453
454 thermal_watcher_->wake();
455 return true;
456 }
457
emulClear(std::string_view target_sensor)458 bool ThermalHelperImpl::emulClear(std::string_view target_sensor) {
459 LOG(INFO) << "Clear " << target_sensor.data() << " emulation settings";
460
461 std::lock_guard<std::shared_mutex> _lock(sensor_status_map_mutex_);
462 if (target_sensor == "all") {
463 for (auto &[sensor_name, sensor_status] : sensor_status_map_) {
464 sensor_status.override_status = {
465 .emul_temp = nullptr, .max_throttling = false, .pending_update = true};
466 checkUpdateSensorForEmul(sensor_name, false);
467 }
468 } else if (sensor_status_map_.count(target_sensor.data())) {
469 auto &sensor_status = sensor_status_map_.at(target_sensor.data());
470 sensor_status.override_status = {
471 .emul_temp = nullptr, .max_throttling = false, .pending_update = true};
472 checkUpdateSensorForEmul(target_sensor.data(), false);
473 } else {
474 LOG(ERROR) << "Cannot find target emul sensor: " << target_sensor.data();
475 return false;
476 }
477
478 thermal_watcher_->wake();
479 return true;
480 }
481
readCoolingDevice(std::string_view cooling_device,CoolingDevice * out) const482 bool ThermalHelperImpl::readCoolingDevice(std::string_view cooling_device,
483 CoolingDevice *out) const {
484 // Read the file. If the file can't be read temp will be empty string.
485 std::string data;
486
487 if (!cooling_devices_.readThermalFile(cooling_device, &data)) {
488 LOG(ERROR) << "readCoolingDevice: failed to read cooling_device: " << cooling_device;
489 return false;
490 }
491
492 const CdevInfo &cdev_info = cooling_device_info_map_.at(cooling_device.data());
493 const CoolingType &type = cdev_info.type;
494
495 out->type = type;
496 out->name = cooling_device.data();
497 out->value = std::stoi(data);
498
499 return true;
500 }
501
readTemperature(std::string_view sensor_name,Temperature * out,std::pair<ThrottlingSeverity,ThrottlingSeverity> * throttling_status,const bool force_no_cache)502 bool ThermalHelperImpl::readTemperature(
503 std::string_view sensor_name, Temperature *out,
504 std::pair<ThrottlingSeverity, ThrottlingSeverity> *throttling_status,
505 const bool force_no_cache) {
506 // Return fail if the thermal sensor cannot be read.
507 float temp = NAN;
508 std::map<std::string, float> sensor_log_map;
509 auto &sensor_status = sensor_status_map_.at(sensor_name.data());
510
511 if (!readThermalSensor(sensor_name, &temp, force_no_cache, &sensor_log_map)) {
512 LOG(ERROR) << "Failed to read thermal sensor " << sensor_name.data();
513 thermal_stats_helper_.reportThermalAbnormality(
514 ThermalSensorAbnormalityDetected::TEMP_READ_FAIL, sensor_name, std::nullopt);
515 return false;
516 }
517
518 if (std::isnan(temp)) {
519 LOG(INFO) << "Sensor " << sensor_name.data() << " temperature is nan.";
520 return false;
521 }
522
523 const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
524 out->type = sensor_info.type;
525 out->name = sensor_name.data();
526 out->value = temp * sensor_info.multiplier;
527
528 std::pair<ThrottlingSeverity, ThrottlingSeverity> status =
529 std::make_pair(ThrottlingSeverity::NONE, ThrottlingSeverity::NONE);
530 // Only update status if the thermal sensor is being monitored
531 if (sensor_info.is_watch) {
532 ThrottlingSeverity prev_hot_severity, prev_cold_severity;
533 {
534 // reader lock, readTemperature will be called in Binder call and the watcher thread.
535 std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
536 prev_hot_severity = sensor_status.prev_hot_severity;
537 prev_cold_severity = sensor_status.prev_cold_severity;
538 }
539 status = getSeverityFromThresholds(sensor_info.hot_thresholds, sensor_info.cold_thresholds,
540 sensor_info.hot_hysteresis, sensor_info.cold_hysteresis,
541 prev_hot_severity, prev_cold_severity, out->value);
542 }
543
544 if (throttling_status) {
545 *throttling_status = status;
546 }
547
548 if (sensor_status.override_status.emul_temp != nullptr &&
549 sensor_status.override_status.emul_temp->severity >= 0) {
550 std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
551 out->throttlingStatus =
552 static_cast<ThrottlingSeverity>(sensor_status.override_status.emul_temp->severity);
553 } else {
554 out->throttlingStatus =
555 static_cast<size_t>(status.first) > static_cast<size_t>(status.second)
556 ? status.first
557 : status.second;
558 }
559 if (sensor_info.is_watch) {
560 std::ostringstream sensor_log;
561 for (const auto &sensor_log_pair : sensor_log_map) {
562 sensor_log << sensor_log_pair.first << ":" << sensor_log_pair.second << " ";
563 }
564 // Update sensor temperature time in state
565 thermal_stats_helper_.updateSensorTempStatsBySeverity(sensor_name, out->throttlingStatus);
566 LOG(INFO) << sensor_name.data() << ":" << out->value << " raw data: " << sensor_log.str();
567 }
568
569 return true;
570 }
571
readTemperatureThreshold(std::string_view sensor_name,TemperatureThreshold * out) const572 bool ThermalHelperImpl::readTemperatureThreshold(std::string_view sensor_name,
573 TemperatureThreshold *out) const {
574 // Read the file. If the file can't be read temp will be empty string.
575 std::string temp;
576 std::string path;
577
578 if (!sensor_info_map_.count(sensor_name.data())) {
579 LOG(ERROR) << __func__ << ": sensor not found: " << sensor_name;
580 return false;
581 }
582
583 const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
584
585 out->type = sensor_info.type;
586 out->name = sensor_name.data();
587 out->hotThrottlingThresholds =
588 std::vector(sensor_info.hot_thresholds.begin(), sensor_info.hot_thresholds.end());
589 out->coldThrottlingThresholds =
590 std::vector(sensor_info.cold_thresholds.begin(), sensor_info.cold_thresholds.end());
591 return true;
592 }
593
updateCoolingDevices(const std::vector<std::string> & updated_cdev)594 void ThermalHelperImpl::updateCoolingDevices(const std::vector<std::string> &updated_cdev) {
595 int max_state;
596
597 for (const auto &target_cdev : updated_cdev) {
598 if (thermal_throttling_.getCdevMaxRequest(target_cdev, &max_state)) {
599 if (cooling_devices_.writeCdevFile(target_cdev, std::to_string(max_state))) {
600 ATRACE_INT(target_cdev.c_str(), max_state);
601 LOG(INFO) << "Successfully update cdev " << target_cdev << " sysfs to "
602 << max_state;
603 } else {
604 LOG(ERROR) << "Failed to update cdev " << target_cdev << " sysfs to " << max_state;
605 }
606 }
607 }
608 }
609
getSeverityFromThresholds(const ThrottlingArray & hot_thresholds,const ThrottlingArray & cold_thresholds,const ThrottlingArray & hot_hysteresis,const ThrottlingArray & cold_hysteresis,ThrottlingSeverity prev_hot_severity,ThrottlingSeverity prev_cold_severity,float value) const610 std::pair<ThrottlingSeverity, ThrottlingSeverity> ThermalHelperImpl::getSeverityFromThresholds(
611 const ThrottlingArray &hot_thresholds, const ThrottlingArray &cold_thresholds,
612 const ThrottlingArray &hot_hysteresis, const ThrottlingArray &cold_hysteresis,
613 ThrottlingSeverity prev_hot_severity, ThrottlingSeverity prev_cold_severity,
614 float value) const {
615 ThrottlingSeverity ret_hot = ThrottlingSeverity::NONE;
616 ThrottlingSeverity ret_hot_hysteresis = ThrottlingSeverity::NONE;
617 ThrottlingSeverity ret_cold = ThrottlingSeverity::NONE;
618 ThrottlingSeverity ret_cold_hysteresis = ThrottlingSeverity::NONE;
619
620 // Here we want to control the iteration from high to low, and ::ndk::enum_range doesn't support
621 // a reverse iterator yet.
622 for (size_t i = static_cast<size_t>(ThrottlingSeverity::SHUTDOWN);
623 i > static_cast<size_t>(ThrottlingSeverity::NONE); --i) {
624 if (!std::isnan(hot_thresholds[i]) && hot_thresholds[i] <= value &&
625 ret_hot == ThrottlingSeverity::NONE) {
626 ret_hot = static_cast<ThrottlingSeverity>(i);
627 }
628 if (!std::isnan(hot_thresholds[i]) && (hot_thresholds[i] - hot_hysteresis[i]) < value &&
629 ret_hot_hysteresis == ThrottlingSeverity::NONE) {
630 ret_hot_hysteresis = static_cast<ThrottlingSeverity>(i);
631 }
632 if (!std::isnan(cold_thresholds[i]) && cold_thresholds[i] >= value &&
633 ret_cold == ThrottlingSeverity::NONE) {
634 ret_cold = static_cast<ThrottlingSeverity>(i);
635 }
636 if (!std::isnan(cold_thresholds[i]) && (cold_thresholds[i] + cold_hysteresis[i]) > value &&
637 ret_cold_hysteresis == ThrottlingSeverity::NONE) {
638 ret_cold_hysteresis = static_cast<ThrottlingSeverity>(i);
639 }
640 }
641 if (static_cast<size_t>(ret_hot) < static_cast<size_t>(prev_hot_severity)) {
642 ret_hot = ret_hot_hysteresis;
643 }
644 if (static_cast<size_t>(ret_cold) < static_cast<size_t>(prev_cold_severity)) {
645 ret_cold = ret_cold_hysteresis;
646 }
647
648 return std::make_pair(ret_hot, ret_cold);
649 }
650
isSubSensorValid(std::string_view sensor_data,const SensorFusionType sensor_fusion_type)651 bool ThermalHelperImpl::isSubSensorValid(std::string_view sensor_data,
652 const SensorFusionType sensor_fusion_type) {
653 switch (sensor_fusion_type) {
654 case SensorFusionType::SENSOR:
655 if (!sensor_info_map_.count(sensor_data.data())) {
656 LOG(ERROR) << "Cannot find " << sensor_data.data() << " from sensor info map";
657 return false;
658 }
659 break;
660 case SensorFusionType::ODPM:
661 if (!GetPowerStatusMap().count(sensor_data.data())) {
662 LOG(ERROR) << "Cannot find " << sensor_data.data() << " from power status map";
663 return false;
664 }
665 break;
666 default:
667 break;
668 }
669 return true;
670 }
671
clearAllThrottling(void)672 void ThermalHelperImpl::clearAllThrottling(void) {
673 // Clear the CDEV request
674 for (const auto &cdev_info_pair : cooling_device_info_map_) {
675 cooling_devices_.writeCdevFile(cdev_info_pair.first, "0");
676 }
677
678 for (auto &sensor_info_pair : sensor_info_map_) {
679 sensor_info_pair.second.is_watch = false;
680 sensor_info_pair.second.throttling_info.reset();
681 sensor_info_pair.second.hot_thresholds.fill(NAN);
682 sensor_info_pair.second.cold_thresholds.fill(NAN);
683 Temperature temp = {
684 .type = sensor_info_pair.second.type,
685 .name = sensor_info_pair.first,
686 .value = NAN,
687 .throttlingStatus = ThrottlingSeverity::NONE,
688 };
689 // Send callbacks with NONE severity
690 if (sensor_info_pair.second.send_cb && cb_) {
691 cb_(temp);
692 }
693 // Disable thermal power hints
694 if (sensor_info_pair.second.send_powerhint) {
695 for (const auto &severity : ::ndk::enum_range<ThrottlingSeverity>()) {
696 power_hal_service_.setMode(sensor_info_pair.first, severity, false);
697 }
698 }
699 }
700 }
701
initializeSensorMap(const std::unordered_map<std::string,std::string> & path_map)702 bool ThermalHelperImpl::initializeSensorMap(
703 const std::unordered_map<std::string, std::string> &path_map) {
704 for (const auto &sensor_info_pair : sensor_info_map_) {
705 std::string_view sensor_name = sensor_info_pair.first;
706 if (sensor_info_pair.second.virtual_sensor_info != nullptr) {
707 continue;
708 }
709 if (!path_map.count(sensor_name.data())) {
710 LOG(ERROR) << "Could not find " << sensor_name << " in sysfs";
711 return false;
712 }
713
714 std::string path;
715 if (sensor_info_pair.second.temp_path.empty()) {
716 path = ::android::base::StringPrintf("%s/%s", path_map.at(sensor_name.data()).c_str(),
717 kSensorTempSuffix.data());
718 } else {
719 path = sensor_info_pair.second.temp_path;
720 }
721
722 if (!thermal_sensors_.addThermalFile(sensor_name, path)) {
723 LOG(ERROR) << "Could not add " << sensor_name << "to sensors map";
724 return false;
725 }
726 }
727 return true;
728 }
729
initializeCoolingDevices(const std::unordered_map<std::string,std::string> & path_map)730 bool ThermalHelperImpl::initializeCoolingDevices(
731 const std::unordered_map<std::string, std::string> &path_map) {
732 for (auto &cooling_device_info_pair : cooling_device_info_map_) {
733 std::string cooling_device_name = cooling_device_info_pair.first;
734 if (!path_map.count(cooling_device_name)) {
735 LOG(ERROR) << "Could not find " << cooling_device_name << " in sysfs";
736 return false;
737 }
738 // Add cooling device path for thermalHAL to get current state
739 std::string_view path = path_map.at(cooling_device_name);
740 std::string read_path;
741 if (!cooling_device_info_pair.second.read_path.empty()) {
742 read_path = cooling_device_info_pair.second.read_path.data();
743 } else {
744 read_path = ::android::base::StringPrintf("%s/%s", path.data(),
745 kCoolingDeviceCurStateSuffix.data());
746 }
747 if (!cooling_devices_.addThermalFile(cooling_device_name, read_path)) {
748 LOG(ERROR) << "Could not add " << cooling_device_name
749 << " read path to cooling device map";
750 return false;
751 }
752
753 std::string state2power_path = ::android::base::StringPrintf(
754 "%s/%s", path.data(), kCoolingDeviceState2powerSuffix.data());
755 std::string state2power_str;
756 if (::android::base::ReadFileToString(state2power_path, &state2power_str)) {
757 LOG(INFO) << "Cooling device " << cooling_device_info_pair.first
758 << " use state2power read from sysfs";
759 cooling_device_info_pair.second.state2power.clear();
760
761 std::stringstream power(state2power_str);
762 unsigned int power_number;
763 int i = 0;
764 while (power >> power_number) {
765 cooling_device_info_pair.second.state2power.push_back(
766 static_cast<float>(power_number));
767 LOG(INFO) << "Cooling device " << cooling_device_info_pair.first << " state:" << i
768 << " power: " << power_number;
769 i++;
770 }
771 }
772
773 // Get max cooling device request state
774 std::string max_state;
775 std::string max_state_path = ::android::base::StringPrintf(
776 "%s/%s", path.data(), kCoolingDeviceMaxStateSuffix.data());
777 if (!::android::base::ReadFileToString(max_state_path, &max_state)) {
778 LOG(ERROR) << cooling_device_info_pair.first
779 << " could not open max state file:" << max_state_path;
780 cooling_device_info_pair.second.max_state = std::numeric_limits<int>::max();
781 } else {
782 cooling_device_info_pair.second.max_state = std::stoi(::android::base::Trim(max_state));
783 LOG(INFO) << "Cooling device " << cooling_device_info_pair.first
784 << " max state: " << cooling_device_info_pair.second.max_state
785 << " state2power number: "
786 << cooling_device_info_pair.second.state2power.size();
787 if (cooling_device_info_pair.second.state2power.size() > 0 &&
788 static_cast<int>(cooling_device_info_pair.second.state2power.size()) !=
789 (cooling_device_info_pair.second.max_state + 1)) {
790 LOG(ERROR) << "Invalid state2power number: "
791 << cooling_device_info_pair.second.state2power.size()
792 << ", number should be " << cooling_device_info_pair.second.max_state + 1
793 << " (max_state + 1)";
794 return false;
795 }
796 }
797
798 // Add cooling device path for thermalHAL to request state
799 cooling_device_name =
800 ::android::base::StringPrintf("%s_%s", cooling_device_name.c_str(), "w");
801 std::string write_path;
802 if (!cooling_device_info_pair.second.write_path.empty()) {
803 write_path = cooling_device_info_pair.second.write_path.data();
804 } else {
805 write_path = ::android::base::StringPrintf("%s/%s", path.data(),
806 kCoolingDeviceCurStateSuffix.data());
807 }
808
809 if (!cooling_devices_.addThermalFile(cooling_device_name, write_path)) {
810 LOG(ERROR) << "Could not add " << cooling_device_name
811 << " write path to cooling device map";
812 return false;
813 }
814 }
815 return true;
816 }
817
setMinTimeout(SensorInfo * sensor_info)818 void ThermalHelperImpl::setMinTimeout(SensorInfo *sensor_info) {
819 sensor_info->polling_delay = kMinPollIntervalMs;
820 sensor_info->passive_delay = kMinPollIntervalMs;
821 }
822
initializeTrip(const std::unordered_map<std::string,std::string> & path_map,std::set<std::string> * monitored_sensors,bool thermal_genl_enabled)823 void ThermalHelperImpl::initializeTrip(const std::unordered_map<std::string, std::string> &path_map,
824 std::set<std::string> *monitored_sensors,
825 bool thermal_genl_enabled) {
826 for (auto &sensor_info : sensor_info_map_) {
827 if (!sensor_info.second.is_watch || (sensor_info.second.virtual_sensor_info != nullptr)) {
828 continue;
829 }
830
831 bool trip_update = false;
832 std::string_view sensor_name = sensor_info.first;
833 std::string_view tz_path = path_map.at(sensor_name.data());
834 std::string tz_policy;
835 std::string path =
836 ::android::base::StringPrintf("%s/%s", (tz_path.data()), kSensorPolicyFile.data());
837
838 if (thermal_genl_enabled) {
839 trip_update = true;
840 } else {
841 // Check if thermal zone support uevent notify
842 if (!::android::base::ReadFileToString(path, &tz_policy)) {
843 LOG(ERROR) << sensor_name << " could not open tz policy file:" << path;
844 } else {
845 tz_policy = ::android::base::Trim(tz_policy);
846 if (tz_policy != kUserSpaceSuffix) {
847 LOG(ERROR) << sensor_name << " does not support uevent notify";
848 } else {
849 trip_update = true;
850 }
851 }
852 }
853 if (trip_update) {
854 // Update thermal zone trip point
855 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
856 if (!std::isnan(sensor_info.second.hot_thresholds[i]) &&
857 !std::isnan(sensor_info.second.hot_hysteresis[i])) {
858 // Update trip_point_0_temp threshold
859 std::string threshold = std::to_string(std::lround(
860 sensor_info.second.hot_thresholds[i] / sensor_info.second.multiplier));
861 path = ::android::base::StringPrintf("%s/%s", (tz_path.data()),
862 kSensorTripPointTempZeroFile.data());
863 if (!::android::base::WriteStringToFile(threshold, path)) {
864 LOG(ERROR) << "fail to update " << sensor_name << " trip point: " << path
865 << " to " << threshold;
866 trip_update = false;
867 break;
868 }
869 // Update trip_point_0_hyst threshold
870 threshold = std::to_string(std::lround(sensor_info.second.hot_hysteresis[i] /
871 sensor_info.second.multiplier));
872 path = ::android::base::StringPrintf("%s/%s", (tz_path.data()),
873 kSensorTripPointHystZeroFile.data());
874 if (!::android::base::WriteStringToFile(threshold, path)) {
875 LOG(ERROR) << "fail to update " << sensor_name << "trip hyst" << threshold
876 << path;
877 trip_update = false;
878 break;
879 }
880 break;
881 } else if (i == kThrottlingSeverityCount - 1) {
882 LOG(ERROR) << sensor_name << ":all thresholds are NAN";
883 trip_update = false;
884 break;
885 }
886 }
887 monitored_sensors->insert(sensor_info.first);
888 }
889
890 if (!trip_update) {
891 LOG(INFO) << "config Sensor: " << sensor_info.first
892 << " to default polling interval: " << kMinPollIntervalMs.count();
893 setMinTimeout(&sensor_info.second);
894 }
895 }
896 }
897
fillCurrentTemperatures(bool filterType,bool filterCallback,TemperatureType type,std::vector<Temperature> * temperatures)898 bool ThermalHelperImpl::fillCurrentTemperatures(bool filterType, bool filterCallback,
899 TemperatureType type,
900 std::vector<Temperature> *temperatures) {
901 std::vector<Temperature> ret;
902 for (const auto &name_info_pair : sensor_info_map_) {
903 Temperature temp;
904 if (name_info_pair.second.is_hidden) {
905 continue;
906 }
907 if (filterType && name_info_pair.second.type != type) {
908 continue;
909 }
910 if (filterCallback && !name_info_pair.second.send_cb) {
911 continue;
912 }
913 if (readTemperature(name_info_pair.first, &temp, nullptr, false)) {
914 ret.emplace_back(std::move(temp));
915 } else {
916 LOG(ERROR) << __func__
917 << ": error reading temperature for sensor: " << name_info_pair.first;
918 }
919 }
920 *temperatures = ret;
921 return ret.size() > 0;
922 }
923
fillTemperatureThresholds(bool filterType,TemperatureType type,std::vector<TemperatureThreshold> * thresholds) const924 bool ThermalHelperImpl::fillTemperatureThresholds(
925 bool filterType, TemperatureType type,
926 std::vector<TemperatureThreshold> *thresholds) const {
927 std::vector<TemperatureThreshold> ret;
928 for (const auto &name_info_pair : sensor_info_map_) {
929 TemperatureThreshold temp;
930 if (name_info_pair.second.is_hidden) {
931 continue;
932 }
933 if (filterType && name_info_pair.second.type != type) {
934 continue;
935 }
936 if (readTemperatureThreshold(name_info_pair.first, &temp)) {
937 ret.emplace_back(std::move(temp));
938 } else {
939 LOG(ERROR) << __func__ << ": error reading temperature threshold for sensor: "
940 << name_info_pair.first;
941 return false;
942 }
943 }
944 *thresholds = ret;
945 return ret.size() > 0;
946 }
947
fillCurrentCoolingDevices(bool filterType,CoolingType type,std::vector<CoolingDevice> * cooling_devices) const948 bool ThermalHelperImpl::fillCurrentCoolingDevices(
949 bool filterType, CoolingType type, std::vector<CoolingDevice> *cooling_devices) const {
950 std::vector<CoolingDevice> ret;
951 for (const auto &name_info_pair : cooling_device_info_map_) {
952 CoolingDevice value;
953 if (filterType && name_info_pair.second.type != type) {
954 continue;
955 }
956 if (readCoolingDevice(name_info_pair.first, &value)) {
957 ret.emplace_back(std::move(value));
958 } else {
959 LOG(ERROR) << __func__ << ": error reading cooling device: " << name_info_pair.first;
960 return false;
961 }
962 }
963 *cooling_devices = ret;
964 return ret.size() > 0;
965 }
966
readDataByType(std::string_view sensor_data,float * reading_value,const SensorFusionType type,const bool force_no_cache,std::map<std::string,float> * sensor_log_map)967 bool ThermalHelperImpl::readDataByType(std::string_view sensor_data, float *reading_value,
968 const SensorFusionType type, const bool force_no_cache,
969 std::map<std::string, float> *sensor_log_map) {
970 switch (type) {
971 case SensorFusionType::SENSOR:
972 if (!readThermalSensor(sensor_data.data(), reading_value, force_no_cache,
973 sensor_log_map)) {
974 LOG(ERROR) << "Failed to get " << sensor_data.data() << " data";
975 return false;
976 }
977 break;
978 case SensorFusionType::ODPM:
979 *reading_value = GetPowerStatusMap().at(sensor_data.data()).last_updated_avg_power;
980 if (std::isnan(*reading_value)) {
981 LOG(INFO) << "Power data " << sensor_data.data() << " is under collecting";
982 return true;
983 }
984 (*sensor_log_map)[sensor_data.data()] = *reading_value;
985 break;
986 case SensorFusionType::CONSTANT:
987 *reading_value = std::atof(sensor_data.data());
988 break;
989 default:
990 break;
991 }
992 return true;
993 }
994
runVirtualTempEstimator(std::string_view sensor_name,std::map<std::string,float> * sensor_log_map,const bool force_no_cache,std::vector<float> * outputs)995 bool ThermalHelperImpl::runVirtualTempEstimator(std::string_view sensor_name,
996 std::map<std::string, float> *sensor_log_map,
997 const bool force_no_cache,
998 std::vector<float> *outputs) {
999 std::vector<float> model_inputs;
1000 std::vector<float> model_outputs;
1001
1002 ATRACE_NAME(StringPrintf("ThermalHelper::runVirtualTempEstimator - %s", sensor_name.data())
1003 .c_str());
1004 if (!(sensor_info_map_.count(sensor_name.data()) &&
1005 sensor_status_map_.count(sensor_name.data()))) {
1006 LOG(ERROR) << sensor_name << " not part of sensor_info_map_ or sensor_status_map_";
1007 return false;
1008 }
1009
1010 const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
1011 if (sensor_info.virtual_sensor_info == nullptr ||
1012 sensor_info.virtual_sensor_info->vt_estimator == nullptr) {
1013 LOG(ERROR) << "vt_estimator not valid for " << sensor_name;
1014 return false;
1015 }
1016
1017 if (outputs == nullptr) {
1018 LOG(ERROR) << "vt_estimator output is nullptr";
1019 return false;
1020 }
1021
1022 model_inputs.reserve(sensor_info.virtual_sensor_info->linked_sensors.size());
1023
1024 for (size_t i = 0; i < sensor_info.virtual_sensor_info->linked_sensors.size(); i++) {
1025 std::string linked_sensor = sensor_info.virtual_sensor_info->linked_sensors[i];
1026
1027 if ((*sensor_log_map).count(linked_sensor.data())) {
1028 float value = (*sensor_log_map)[linked_sensor.data()];
1029 model_inputs.push_back(value);
1030 } else {
1031 LOG(ERROR) << "failed to read sensor: " << linked_sensor;
1032 return false;
1033 }
1034 }
1035
1036 ::thermal::vtestimator::VtEstimatorStatus ret =
1037 sensor_info.virtual_sensor_info->vt_estimator->Estimate(model_inputs, &model_outputs);
1038
1039 if (ret == ::thermal::vtestimator::kVtEstimatorOk) {
1040 *outputs = model_outputs;
1041 return true;
1042 } else if (ret == ::thermal::vtestimator::kVtEstimatorLowConfidence ||
1043 ret == ::thermal::vtestimator::kVtEstimatorUnderSampling) {
1044 std::string_view backup_sensor = sensor_info.virtual_sensor_info->backup_sensor;
1045 float backup_sensor_vt;
1046 if (backup_sensor.empty()) {
1047 LOG(ERROR) << "Failed to run estimator (ret: " << ret << ") for " << sensor_name
1048 << " with no backup.";
1049 return false;
1050 }
1051 LOG(INFO) << "VT Estimator returned (ret: " << ret << ") for " << sensor_name
1052 << ". Reading backup sensor [" << backup_sensor << "] data to use";
1053 if (!readDataByType(backup_sensor, &backup_sensor_vt, SensorFusionType::SENSOR,
1054 force_no_cache, sensor_log_map)) {
1055 LOG(ERROR) << "Failed to read " << sensor_name.data() << "'s backup sensor "
1056 << backup_sensor;
1057 return false;
1058 }
1059 model_outputs.clear();
1060 model_outputs.push_back(backup_sensor_vt);
1061 *outputs = model_outputs;
1062 return true;
1063 }
1064
1065 LOG(ERROR) << "Failed to run estimator (ret: " << ret << ") for " << sensor_name;
1066 return false;
1067 }
1068
dumpVtEstimatorStatus(std::string_view sensor_name,std::ostringstream * dump_buf) const1069 void ThermalHelperImpl::dumpVtEstimatorStatus(std::string_view sensor_name,
1070 std::ostringstream *dump_buf) const {
1071 if (!(sensor_info_map_.count(sensor_name.data()) &&
1072 sensor_status_map_.count(sensor_name.data()))) {
1073 LOG(ERROR) << sensor_name << " not part of sensor_info_map_ or sensor_status_map_";
1074 return;
1075 }
1076
1077 const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
1078 if (sensor_info.virtual_sensor_info == nullptr ||
1079 sensor_info.virtual_sensor_info->vt_estimator == nullptr) {
1080 return;
1081 }
1082
1083 sensor_info.virtual_sensor_info->vt_estimator->DumpStatus(sensor_name, dump_buf);
1084 }
1085
getPredictionMaxWindowMs(std::string_view sensor_name)1086 size_t ThermalHelperImpl::getPredictionMaxWindowMs(std::string_view sensor_name) {
1087 size_t predict_window = 0;
1088
1089 ATRACE_NAME(StringPrintf("ThermalHelper::getPredictionMaxWindowMs - %s", sensor_name.data())
1090 .c_str());
1091
1092 const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
1093 if (sensor_info.predictor_info == nullptr) {
1094 LOG(ERROR) << "No predictor info found for sensor: " << sensor_name;
1095 return 0;
1096 }
1097
1098 std::string_view predict_sensor_name = sensor_info.predictor_info->sensor;
1099 const auto &predictor_sensor_info = sensor_info_map_.at(predict_sensor_name.data());
1100 ::thermal::vtestimator::VtEstimatorStatus ret =
1101 predictor_sensor_info.virtual_sensor_info->vt_estimator->GetMaxPredictWindowMs(
1102 &predict_window);
1103
1104 if (ret != ::thermal::vtestimator::kVtEstimatorOk) {
1105 LOG(ERROR) << "Failed to read prediction (ret: " << ret << ") from " << predict_sensor_name
1106 << " for sensor " << sensor_name;
1107 return 0;
1108 }
1109
1110 return predict_window;
1111 }
1112
readPredictionAfterTimeMs(std::string_view sensor_name,const size_t time_ms)1113 float ThermalHelperImpl::readPredictionAfterTimeMs(std::string_view sensor_name,
1114 const size_t time_ms) {
1115 float predicted_vt = NAN;
1116
1117 ATRACE_NAME(
1118 StringPrintf("ThermalHelper::readPredictAfterTimeMs - %s", sensor_name.data()).c_str());
1119
1120 const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
1121 if (sensor_info.predictor_info == nullptr) {
1122 LOG(ERROR) << "No predictor info found for sensor: " << sensor_name;
1123 return NAN;
1124 }
1125
1126 std::string_view predict_sensor_name = sensor_info.predictor_info->sensor;
1127 const auto &predictor_sensor_info = sensor_info_map_.at(predict_sensor_name.data());
1128 ::thermal::vtestimator::VtEstimatorStatus ret =
1129 predictor_sensor_info.virtual_sensor_info->vt_estimator->PredictAfterTimeMs(
1130 time_ms, &predicted_vt);
1131
1132 if (ret == ::thermal::vtestimator::kVtEstimatorOk) {
1133 return predicted_vt;
1134 } else if (ret == ::thermal::vtestimator::kVtEstimatorUnderSampling) {
1135 LOG(INFO) << predict_sensor_name << " cannot provide prediction for sensor " << sensor_name
1136 << "while under sampling";
1137 } else if (ret == ::thermal::vtestimator::kVtEstimatorUnSupported) {
1138 LOG(INFO) << "PredictAfterTimeMs not supported with " << predict_sensor_name
1139 << " for sensor " << sensor_name;
1140 } else {
1141 LOG(ERROR) << "Failed to read prediction (ret: " << ret << ") from " << predict_sensor_name
1142 << " for sensor " << sensor_name;
1143 }
1144
1145 return NAN;
1146 }
1147
readTemperaturePredictions(std::string_view sensor_name,std::vector<float> * predictions)1148 bool ThermalHelperImpl::readTemperaturePredictions(std::string_view sensor_name,
1149 std::vector<float> *predictions) {
1150 ATRACE_NAME(StringPrintf("ThermalHelper::readTemperaturePredictions - %s", sensor_name.data())
1151 .c_str());
1152
1153 if (predictions == nullptr) {
1154 LOG(ERROR) << " predictions is nullptr";
1155 return false;
1156 }
1157
1158 if (!sensor_info_map_.count(sensor_name.data())) {
1159 LOG(ERROR) << sensor_name << " not part of sensor_info_map_";
1160 return false;
1161 }
1162
1163 const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
1164 if (sensor_info.predictor_info == nullptr) {
1165 LOG(ERROR) << "No predictor info found for sensor: " << sensor_name;
1166 return false;
1167 }
1168
1169 std::string predict_sensor_name = sensor_info.predictor_info->sensor;
1170 const auto &predictor_sensor_info = sensor_info_map_.at(predict_sensor_name);
1171 ::thermal::vtestimator::VtEstimatorStatus ret =
1172 predictor_sensor_info.virtual_sensor_info->vt_estimator->GetAllPredictions(predictions);
1173
1174 if (ret != ::thermal::vtestimator::kVtEstimatorOk) {
1175 LOG(ERROR) << "Failed to read predictions (ret: " << ret << ") from " << predict_sensor_name
1176 << " for sensor " << sensor_name;
1177 return false;
1178 }
1179
1180 return true;
1181 }
1182
1183 constexpr int kTranTimeoutParam = 2;
1184
readThermalSensor(std::string_view sensor_name,float * temp,const bool force_no_cache,std::map<std::string,float> * sensor_log_map)1185 bool ThermalHelperImpl::readThermalSensor(std::string_view sensor_name, float *temp,
1186 const bool force_no_cache,
1187 std::map<std::string, float> *sensor_log_map) {
1188 std::string file_reading;
1189 boot_clock::time_point now = boot_clock::now();
1190
1191 ATRACE_NAME(StringPrintf("ThermalHelper::readThermalSensor - %s", sensor_name.data()).c_str());
1192 if (!(sensor_info_map_.count(sensor_name.data()) &&
1193 sensor_status_map_.count(sensor_name.data()))) {
1194 return false;
1195 }
1196
1197 const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
1198 auto &sensor_status = sensor_status_map_.at(sensor_name.data());
1199
1200 {
1201 std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
1202 if (sensor_status.override_status.emul_temp != nullptr) {
1203 *temp = sensor_status.override_status.emul_temp->temp;
1204 (*sensor_log_map)[sensor_name.data()] = *temp;
1205 return true;
1206 }
1207 }
1208
1209 const auto since_last_update = std::chrono::duration_cast<std::chrono::milliseconds>(
1210 now - sensor_status.thermal_cached.timestamp);
1211
1212 // Check if thermal data need to be read from cache
1213 if (!force_no_cache &&
1214 (sensor_status.thermal_cached.timestamp != boot_clock::time_point::min()) &&
1215 (since_last_update < sensor_info.time_resolution) &&
1216 !isnan(sensor_status.thermal_cached.temp)) {
1217 *temp = sensor_status.thermal_cached.temp;
1218 (*sensor_log_map)[sensor_name.data()] = *temp;
1219 ATRACE_INT((sensor_name.data() + std::string("-cached")).c_str(), static_cast<int>(*temp));
1220 return true;
1221 }
1222
1223 // Reading thermal sensor according to it's composition
1224 if (sensor_info.virtual_sensor_info == nullptr) {
1225 if (!thermal_sensors_.readThermalFile(sensor_name.data(), &file_reading) ||
1226 file_reading.empty()) {
1227 LOG(ERROR) << "failed to read sensor: " << sensor_name;
1228 return false;
1229 }
1230 *temp = std::stof(::android::base::Trim(file_reading));
1231 } else {
1232 const auto &linked_sensors_size = sensor_info.virtual_sensor_info->linked_sensors.size();
1233 std::vector<float> sensor_readings(linked_sensors_size, NAN);
1234
1235 // Calculate temperature of each of the linked sensor
1236 for (size_t i = 0; i < linked_sensors_size; i++) {
1237 if (!readDataByType(sensor_info.virtual_sensor_info->linked_sensors[i],
1238 &sensor_readings[i],
1239 sensor_info.virtual_sensor_info->linked_sensors_type[i],
1240 force_no_cache, sensor_log_map)) {
1241 LOG(ERROR) << "Failed to read " << sensor_name.data() << "'s linked sensor "
1242 << sensor_info.virtual_sensor_info->linked_sensors[i];
1243 return false;
1244 }
1245 if (std::isnan(sensor_readings[i])) {
1246 LOG(INFO) << sensor_name << " data is under collecting";
1247 return true;
1248 }
1249 }
1250
1251 if ((sensor_info.virtual_sensor_info->formula == FormulaOption::USE_ML_MODEL) ||
1252 (sensor_info.virtual_sensor_info->formula == FormulaOption::USE_LINEAR_MODEL)) {
1253 std::vector<float> vt_estimator_out;
1254 if (!runVirtualTempEstimator(sensor_name, sensor_log_map, force_no_cache,
1255 &vt_estimator_out)) {
1256 LOG(ERROR) << "Failed running VirtualEstimator for " << sensor_name;
1257 return false;
1258 }
1259 *temp = vt_estimator_out[0];
1260 } else {
1261 float temp_val = 0.0;
1262 for (size_t i = 0; i < linked_sensors_size; i++) {
1263 float coefficient = NAN;
1264 if (!readDataByType(sensor_info.virtual_sensor_info->coefficients[i], &coefficient,
1265 sensor_info.virtual_sensor_info->coefficients_type[i],
1266 force_no_cache, sensor_log_map)) {
1267 LOG(ERROR) << "Failed to read " << sensor_name.data() << "'s coefficient "
1268 << sensor_info.virtual_sensor_info->coefficients[i];
1269 return false;
1270 }
1271 if (std::isnan(coefficient)) {
1272 LOG(INFO) << sensor_name << " data is under collecting";
1273 return true;
1274 }
1275 switch (sensor_info.virtual_sensor_info->formula) {
1276 case FormulaOption::COUNT_THRESHOLD:
1277 if ((coefficient < 0 && sensor_readings[i] < -coefficient) ||
1278 (coefficient >= 0 && sensor_readings[i] >= coefficient))
1279 temp_val += 1;
1280 break;
1281 case FormulaOption::WEIGHTED_AVG:
1282 temp_val += sensor_readings[i] * coefficient;
1283 break;
1284 case FormulaOption::MAXIMUM:
1285 if (i == 0)
1286 temp_val = std::numeric_limits<float>::lowest();
1287 if (sensor_readings[i] * coefficient > temp_val)
1288 temp_val = sensor_readings[i] * coefficient;
1289 break;
1290 case FormulaOption::MINIMUM:
1291 if (i == 0)
1292 temp_val = std::numeric_limits<float>::max();
1293 if (sensor_readings[i] * coefficient < temp_val)
1294 temp_val = sensor_readings[i] * coefficient;
1295 break;
1296 default:
1297 LOG(ERROR) << "Unknown formula type for sensor " << sensor_name.data();
1298 return false;
1299 }
1300 }
1301 *temp = (temp_val + sensor_info.virtual_sensor_info->offset);
1302 }
1303 }
1304
1305 if (!isnan(sensor_info.step_ratio) && !isnan(sensor_status.thermal_cached.temp) &&
1306 since_last_update < sensor_info.passive_delay * kTranTimeoutParam) {
1307 *temp = (sensor_info.step_ratio * *temp +
1308 (1 - sensor_info.step_ratio) * sensor_status.thermal_cached.temp);
1309 }
1310
1311 (*sensor_log_map)[sensor_name.data()] = *temp;
1312 ATRACE_INT(sensor_name.data(), static_cast<int>(*temp));
1313
1314 {
1315 std::unique_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
1316 sensor_status.thermal_cached.temp = *temp;
1317 sensor_status.thermal_cached.timestamp = now;
1318 }
1319 auto real_temp = (*temp) * sensor_info.multiplier;
1320 thermal_stats_helper_.updateSensorTempStatsByThreshold(sensor_name, real_temp);
1321 return true;
1322 }
1323
1324 // This is called in the different thread context and will update sensor_status
1325 // uevent_sensors is the set of sensors which trigger uevent from thermal core driver.
thermalWatcherCallbackFunc(const std::set<std::string> & uevent_sensors)1326 std::chrono::milliseconds ThermalHelperImpl::thermalWatcherCallbackFunc(
1327 const std::set<std::string> &uevent_sensors) {
1328 std::vector<Temperature> temps;
1329 std::vector<std::string> cooling_devices_to_update;
1330 boot_clock::time_point now = boot_clock::now();
1331 auto min_sleep_ms = std::chrono::milliseconds::max();
1332 bool power_data_is_updated = false;
1333
1334 ATRACE_CALL();
1335 for (auto &name_status_pair : sensor_status_map_) {
1336 bool force_update = false;
1337 bool force_no_cache = false;
1338 Temperature temp;
1339 TemperatureThreshold threshold;
1340 SensorStatus &sensor_status = name_status_pair.second;
1341 const SensorInfo &sensor_info = sensor_info_map_.at(name_status_pair.first);
1342 bool max_throttling = false;
1343
1344 // Only handle the sensors in allow list
1345 if (!sensor_info.is_watch) {
1346 continue;
1347 }
1348
1349 ATRACE_NAME(StringPrintf("ThermalHelper::thermalWatcherCallbackFunc - %s",
1350 name_status_pair.first.data())
1351 .c_str());
1352
1353 std::chrono::milliseconds time_elapsed_ms = std::chrono::milliseconds::zero();
1354 auto sleep_ms = (sensor_status.severity != ThrottlingSeverity::NONE)
1355 ? sensor_info.passive_delay
1356 : sensor_info.polling_delay;
1357
1358 if (sensor_info.virtual_sensor_info != nullptr &&
1359 !sensor_info.virtual_sensor_info->trigger_sensors.empty()) {
1360 for (size_t i = 0; i < sensor_info.virtual_sensor_info->trigger_sensors.size(); i++) {
1361 const auto &trigger_sensor_status =
1362 sensor_status_map_.at(sensor_info.virtual_sensor_info->trigger_sensors[i]);
1363 if (trigger_sensor_status.severity != ThrottlingSeverity::NONE) {
1364 sleep_ms = sensor_info.passive_delay;
1365 break;
1366 }
1367 }
1368 }
1369 // Check if the sensor need to be updated
1370 if (sensor_status.last_update_time == boot_clock::time_point::min()) {
1371 force_update = true;
1372 } else {
1373 time_elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
1374 now - sensor_status.last_update_time);
1375 if (uevent_sensors.size()) {
1376 if (sensor_info.virtual_sensor_info != nullptr) {
1377 for (size_t i = 0; i < sensor_info.virtual_sensor_info->trigger_sensors.size();
1378 i++) {
1379 if (uevent_sensors.find(
1380 sensor_info.virtual_sensor_info->trigger_sensors[i]) !=
1381 uevent_sensors.end()) {
1382 force_update = true;
1383 break;
1384 }
1385 }
1386 } else if (uevent_sensors.find(name_status_pair.first) != uevent_sensors.end()) {
1387 force_update = true;
1388 force_no_cache = true;
1389 }
1390 } else if (time_elapsed_ms > sleep_ms) {
1391 force_update = true;
1392 }
1393 }
1394 {
1395 std::lock_guard<std::shared_mutex> _lock(sensor_status_map_mutex_);
1396 max_throttling = sensor_status.override_status.max_throttling;
1397 if (sensor_status.override_status.pending_update) {
1398 force_update = sensor_status.override_status.pending_update;
1399 sensor_status.override_status.pending_update = false;
1400 }
1401 }
1402 LOG(VERBOSE) << "sensor " << name_status_pair.first
1403 << ": time_elapsed=" << time_elapsed_ms.count()
1404 << ", sleep_ms=" << sleep_ms.count() << ", force_update = " << force_update
1405 << ", force_no_cache = " << force_no_cache;
1406
1407 if (!force_update) {
1408 auto timeout_remaining = sleep_ms - time_elapsed_ms;
1409 if (min_sleep_ms > timeout_remaining) {
1410 min_sleep_ms = timeout_remaining;
1411 }
1412 LOG(VERBOSE) << "sensor " << name_status_pair.first
1413 << ": timeout_remaining=" << timeout_remaining.count();
1414 continue;
1415 }
1416
1417 std::pair<ThrottlingSeverity, ThrottlingSeverity> throttling_status;
1418 if (!readTemperature(name_status_pair.first, &temp, &throttling_status, force_no_cache)) {
1419 LOG(ERROR) << __func__
1420 << ": error reading temperature for sensor: " << name_status_pair.first;
1421 continue;
1422 }
1423 if (!readTemperatureThreshold(name_status_pair.first, &threshold)) {
1424 LOG(ERROR) << __func__ << ": error reading temperature threshold for sensor: "
1425 << name_status_pair.first;
1426 continue;
1427 }
1428
1429 {
1430 // writer lock
1431 std::unique_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
1432 if (throttling_status.first != sensor_status.prev_hot_severity) {
1433 sensor_status.prev_hot_severity = throttling_status.first;
1434 }
1435 if (throttling_status.second != sensor_status.prev_cold_severity) {
1436 sensor_status.prev_cold_severity = throttling_status.second;
1437 }
1438 if (temp.throttlingStatus != sensor_status.severity) {
1439 temps.push_back(temp);
1440 sensor_status.severity = temp.throttlingStatus;
1441 sleep_ms = (sensor_status.severity != ThrottlingSeverity::NONE)
1442 ? sensor_info.passive_delay
1443 : sensor_info.polling_delay;
1444 }
1445 }
1446
1447 if (!power_data_is_updated) {
1448 power_files_.refreshPowerStatus();
1449 power_data_is_updated = true;
1450 }
1451
1452 if (sensor_status.severity == ThrottlingSeverity::NONE) {
1453 thermal_throttling_.clearThrottlingData(name_status_pair.first);
1454 } else {
1455 // prepare for predictions for throttling compensation
1456 std::vector<float> sensor_predictions;
1457 if (sensor_info.predictor_info != nullptr &&
1458 sensor_info.predictor_info->support_pid_compensation) {
1459 if (!readTemperaturePredictions(name_status_pair.first, &sensor_predictions)) {
1460 LOG(ERROR) << "Failed to read predictions of " << name_status_pair.first
1461 << " for throttling compensation";
1462 }
1463 }
1464
1465 // update thermal throttling request
1466 thermal_throttling_.thermalThrottlingUpdate(
1467 temp, sensor_info, sensor_status.severity, time_elapsed_ms,
1468 power_files_.GetPowerStatusMap(), cooling_device_info_map_, max_throttling,
1469 sensor_predictions);
1470 }
1471
1472 thermal_throttling_.computeCoolingDevicesRequest(
1473 name_status_pair.first, sensor_info, sensor_status.severity,
1474 &cooling_devices_to_update, &thermal_stats_helper_);
1475 if (min_sleep_ms > sleep_ms) {
1476 min_sleep_ms = sleep_ms;
1477 }
1478
1479 LOG(VERBOSE) << "Sensor " << name_status_pair.first << ": sleep_ms=" << sleep_ms.count()
1480 << ", min_sleep_ms voting result=" << min_sleep_ms.count();
1481 sensor_status.last_update_time = now;
1482 }
1483
1484 if (!cooling_devices_to_update.empty()) {
1485 updateCoolingDevices(cooling_devices_to_update);
1486 }
1487
1488 if (!temps.empty()) {
1489 for (const auto &t : temps) {
1490 if (sensor_info_map_.at(t.name).send_cb && cb_) {
1491 cb_(t);
1492 }
1493
1494 if (sensor_info_map_.at(t.name).send_powerhint) {
1495 power_hal_service_.sendPowerExtHint(t);
1496 }
1497 }
1498 }
1499
1500 int count_failed_reporting = thermal_stats_helper_.reportStats();
1501 if (count_failed_reporting != 0) {
1502 LOG(ERROR) << "Failed to report " << count_failed_reporting << " thermal stats";
1503 }
1504
1505 const auto since_last_power_log_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
1506 now - power_files_.GetPrevPowerLogTime());
1507 if (since_last_power_log_ms >= kPowerLogIntervalMs) {
1508 power_files_.logPowerStatus(now);
1509 }
1510
1511 return min_sleep_ms;
1512 }
1513
1514 } // namespace implementation
1515 } // namespace thermal
1516 } // namespace hardware
1517 } // namespace android
1518 } // namespace aidl
1519