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