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