• 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 <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 // 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)96 void ThermalHelperImpl::maxCoolingRequestCheck(
97         std::unordered_map<std::string, BindedCdevInfo> *binded_cdev_info_map) {
98     for (auto &binded_cdev_info_pair : *binded_cdev_info_map) {
99         const auto &cdev_info = cooling_device_info_map_.at(binded_cdev_info_pair.first);
100         for (auto &cdev_ceiling : binded_cdev_info_pair.second.cdev_ceiling) {
101             if (cdev_ceiling > cdev_info.max_state) {
102                 if (cdev_ceiling != std::numeric_limits<int>::max()) {
103                     LOG(ERROR) << binded_cdev_info_pair.first << " cdev_ceiling:" << cdev_ceiling
104                                << " is higher than max state:" << cdev_info.max_state;
105                 }
106                 cdev_ceiling = cdev_info.max_state;
107             }
108         }
109     }
110 }
111 
112 /*
113  * Populate the sensor_name_to_file_map_ map by walking through the file tree,
114  * reading the type file and assigning the temp file path to the map.  If we do
115  * not succeed, abort.
116  */
ThermalHelperImpl(const NotificationCallback & cb)117 ThermalHelperImpl::ThermalHelperImpl(const NotificationCallback &cb)
118     : thermal_watcher_(new ThermalWatcher(std::bind(&ThermalHelperImpl::thermalWatcherCallbackFunc,
119                                                     this, std::placeholders::_1))),
120       cb_(cb) {
121     const std::string config_path =
122             "/vendor/etc/" +
123             ::android::base::GetProperty(kConfigProperty.data(), kConfigDefaultFileName.data());
124     bool thermal_throttling_disabled =
125             ::android::base::GetBoolProperty(kThermalDisabledProperty.data(), false);
126     bool ret = true;
127     Json::Value config;
128     if (!ParseThermalConfig(config_path, &config)) {
129         LOG(ERROR) << "Failed to read JSON config";
130         ret = false;
131     }
132 
133     if (!ParseCoolingDevice(config, &cooling_device_info_map_)) {
134         LOG(ERROR) << "Failed to parse cooling device info config";
135         ret = false;
136     }
137 
138     if (!ParseSensorInfo(config, &sensor_info_map_)) {
139         LOG(ERROR) << "Failed to parse sensor info config";
140         ret = false;
141     }
142 
143     auto tz_map = parseThermalPathMap(kSensorPrefix.data());
144     if (!initializeSensorMap(tz_map)) {
145         LOG(ERROR) << "Failed to initialize sensor map";
146         ret = false;
147     }
148 
149     auto cdev_map = parseThermalPathMap(kCoolingDevicePrefix.data());
150     if (!initializeCoolingDevices(cdev_map)) {
151         LOG(ERROR) << "Failed to initialize cooling device map";
152         ret = false;
153     }
154 
155     if (!power_files_.registerPowerRailsToWatch(config)) {
156         LOG(ERROR) << "Failed to register power rails";
157         ret = false;
158     }
159 
160     if (!thermal_stats_helper_.initializeStats(config, sensor_info_map_,
161                                                cooling_device_info_map_)) {
162         LOG(FATAL) << "Failed to initialize thermal stats";
163     }
164 
165     for (auto &name_status_pair : sensor_info_map_) {
166         sensor_status_map_[name_status_pair.first] = {
167                 .severity = ThrottlingSeverity::NONE,
168                 .prev_hot_severity = ThrottlingSeverity::NONE,
169                 .prev_cold_severity = ThrottlingSeverity::NONE,
170                 .last_update_time = boot_clock::time_point::min(),
171                 .thermal_cached = {NAN, boot_clock::time_point::min()},
172                 .emul_setting = nullptr,
173         };
174 
175         if (name_status_pair.second.throttling_info != nullptr) {
176             if (!thermal_throttling_.registerThermalThrottling(
177                         name_status_pair.first, name_status_pair.second.throttling_info,
178                         cooling_device_info_map_)) {
179                 LOG(ERROR) << name_status_pair.first << " failed to register thermal throttling";
180                 ret = false;
181                 break;
182             }
183 
184             // Update cooling device max state for default mode
185             maxCoolingRequestCheck(&name_status_pair.second.throttling_info->binded_cdev_info_map);
186 
187             // Update cooling device max state for each profile mode
188             for (auto &cdev_throttling_profile_pair :
189                  name_status_pair.second.throttling_info->profile_map) {
190                 maxCoolingRequestCheck(&cdev_throttling_profile_pair.second);
191             }
192         }
193         // Check the virtual sensor settings are valid
194         if (name_status_pair.second.virtual_sensor_info != nullptr) {
195             // Check if sub sensor setting is valid
196             for (size_t i = 0;
197                  i < name_status_pair.second.virtual_sensor_info->linked_sensors.size(); i++) {
198                 if (!isSubSensorValid(
199                             name_status_pair.second.virtual_sensor_info->linked_sensors[i],
200                             name_status_pair.second.virtual_sensor_info->linked_sensors_type[i])) {
201                     LOG(ERROR) << name_status_pair.first << "'s link sensor "
202                                << name_status_pair.second.virtual_sensor_info->linked_sensors[i]
203                                << " is invalid";
204                     ret = false;
205                     break;
206                 }
207             }
208 
209             // Check if the trigger sensor is valid
210             if (!name_status_pair.second.virtual_sensor_info->trigger_sensors.empty() &&
211                 name_status_pair.second.is_watch) {
212                 for (size_t i = 0;
213                      i < name_status_pair.second.virtual_sensor_info->trigger_sensors.size(); i++) {
214                     if (sensor_info_map_.count(
215                                 name_status_pair.second.virtual_sensor_info->trigger_sensors[i])) {
216                         sensor_info_map_[name_status_pair.second.virtual_sensor_info
217                                                  ->trigger_sensors[i]]
218                                 .is_watch = true;
219                     } else {
220                         LOG(ERROR)
221                                 << name_status_pair.first << "'s trigger sensor: "
222                                 << name_status_pair.second.virtual_sensor_info->trigger_sensors[i]
223                                 << " is invalid";
224                         ret = false;
225                         break;
226                     }
227                 }
228             }
229         }
230     }
231 
232     if (!power_hal_service_.connect()) {
233         LOG(ERROR) << "Fail to connect to Power Hal";
234     } else {
235         power_hal_service_.updateSupportedPowerHints(sensor_info_map_);
236     }
237 
238     if (thermal_throttling_disabled) {
239         if (ret) {
240             clearAllThrottling();
241             is_initialized_ = ret;
242             return;
243         } else {
244             sensor_info_map_.clear();
245             cooling_device_info_map_.clear();
246             return;
247         }
248     } else if (!ret) {
249         LOG(FATAL) << "ThermalHAL could not be initialized properly.";
250     }
251     is_initialized_ = ret;
252 
253     const bool thermal_genl_enabled =
254             ::android::base::GetBoolProperty(kThermalGenlProperty.data(), false);
255 
256     std::set<std::string> monitored_sensors;
257     initializeTrip(tz_map, &monitored_sensors, thermal_genl_enabled);
258 
259     if (thermal_genl_enabled) {
260         thermal_watcher_->registerFilesToWatchNl(monitored_sensors);
261     } else {
262         thermal_watcher_->registerFilesToWatch(monitored_sensors);
263     }
264 
265     // Need start watching after status map initialized
266     is_initialized_ = thermal_watcher_->startWatchingDeviceFiles();
267     if (!is_initialized_) {
268         LOG(FATAL) << "ThermalHAL could not start watching thread properly.";
269     }
270 }
271 
getThermalZoneTypeById(int tz_id,std::string * type)272 bool getThermalZoneTypeById(int tz_id, std::string *type) {
273     std::string tz_type;
274     std::string path =
275             ::android::base::StringPrintf("%s/%s%d/%s", kThermalSensorsRoot.data(),
276                                           kSensorPrefix.data(), tz_id, kThermalNameFile.data());
277     LOG(INFO) << "TZ Path: " << path;
278     if (!::android::base::ReadFileToString(path, &tz_type)) {
279         LOG(ERROR) << "Failed to read sensor: " << tz_type;
280         return false;
281     }
282 
283     // Strip the newline.
284     *type = ::android::base::Trim(tz_type);
285     LOG(INFO) << "TZ type: " << *type;
286     return true;
287 }
288 
emulTemp(std::string_view target_sensor,const float value)289 bool ThermalHelperImpl::emulTemp(std::string_view target_sensor, const float value) {
290     LOG(INFO) << "Set " << target_sensor.data() << " emul_temp "
291               << "to " << value;
292 
293     std::lock_guard<std::shared_mutex> _lock(sensor_status_map_mutex_);
294     // Check the target sensor is valid
295     if (!sensor_status_map_.count(target_sensor.data())) {
296         LOG(ERROR) << "Cannot find target emul sensor: " << target_sensor.data();
297         return false;
298     }
299 
300     sensor_status_map_.at(target_sensor.data())
301             .emul_setting.reset(new EmulSetting{value, -1, true});
302 
303     thermal_watcher_->wake();
304     return true;
305 }
306 
emulSeverity(std::string_view target_sensor,const int severity)307 bool ThermalHelperImpl::emulSeverity(std::string_view target_sensor, const int severity) {
308     LOG(INFO) << "Set " << target_sensor.data() << " emul_severity "
309               << "to " << severity;
310 
311     std::lock_guard<std::shared_mutex> _lock(sensor_status_map_mutex_);
312     // Check the target sensor is valid
313     if (!sensor_status_map_.count(target_sensor.data())) {
314         LOG(ERROR) << "Cannot find target emul sensor: " << target_sensor.data();
315         return false;
316     }
317     // Check the emul severity is valid
318     if (severity > static_cast<int>(kThrottlingSeverityCount)) {
319         LOG(ERROR) << "Invalid emul severity value " << severity;
320         return false;
321     }
322 
323     sensor_status_map_.at(target_sensor.data())
324             .emul_setting.reset(new EmulSetting{NAN, severity, true});
325 
326     thermal_watcher_->wake();
327     return true;
328 }
329 
emulClear(std::string_view target_sensor)330 bool ThermalHelperImpl::emulClear(std::string_view target_sensor) {
331     LOG(INFO) << "Clear " << target_sensor.data() << " emulation settings";
332 
333     std::lock_guard<std::shared_mutex> _lock(sensor_status_map_mutex_);
334     if (target_sensor == "all") {
335         for (auto &sensor_status : sensor_status_map_) {
336             if (sensor_status.second.emul_setting != nullptr) {
337                 sensor_status.second.emul_setting.reset(new EmulSetting{NAN, -1, true});
338             }
339         }
340     } else if (sensor_status_map_.count(target_sensor.data()) &&
341                sensor_status_map_.at(target_sensor.data()).emul_setting != nullptr) {
342         sensor_status_map_.at(target_sensor.data())
343                 .emul_setting.reset(new EmulSetting{NAN, -1, true});
344     } else {
345         LOG(ERROR) << "Cannot find target emul sensor: " << target_sensor.data();
346         return false;
347     }
348     return true;
349 }
350 
readCoolingDevice(std::string_view cooling_device,CoolingDevice * out) const351 bool ThermalHelperImpl::readCoolingDevice(std::string_view cooling_device,
352                                           CoolingDevice *out) const {
353     // Read the file.  If the file can't be read temp will be empty string.
354     std::string data;
355 
356     if (!cooling_devices_.readThermalFile(cooling_device, &data)) {
357         LOG(ERROR) << "readCoolingDevice: failed to read cooling_device: " << cooling_device;
358         return false;
359     }
360 
361     const CdevInfo &cdev_info = cooling_device_info_map_.at(cooling_device.data());
362     const CoolingType &type = cdev_info.type;
363 
364     out->type = type;
365     out->name = cooling_device.data();
366     out->value = std::stoi(data);
367 
368     return true;
369 }
370 
readTemperature(std::string_view sensor_name,Temperature * out,std::pair<ThrottlingSeverity,ThrottlingSeverity> * throttling_status,const bool force_no_cache)371 bool ThermalHelperImpl::readTemperature(
372         std::string_view sensor_name, Temperature *out,
373         std::pair<ThrottlingSeverity, ThrottlingSeverity> *throttling_status,
374         const bool force_no_cache) {
375     // Return fail if the thermal sensor cannot be read.
376     float temp;
377     std::map<std::string, float> sensor_log_map;
378     auto &sensor_status = sensor_status_map_.at(sensor_name.data());
379 
380     if (!readThermalSensor(sensor_name, &temp, force_no_cache, &sensor_log_map) ||
381         std::isnan(temp)) {
382         return false;
383     }
384 
385     const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
386     out->type = sensor_info.type;
387     out->name = sensor_name.data();
388     out->value = temp * sensor_info.multiplier;
389 
390     std::pair<ThrottlingSeverity, ThrottlingSeverity> status =
391             std::make_pair(ThrottlingSeverity::NONE, ThrottlingSeverity::NONE);
392     // Only update status if the thermal sensor is being monitored
393     if (sensor_info.is_watch) {
394         ThrottlingSeverity prev_hot_severity, prev_cold_severity;
395         {
396             // reader lock, readTemperature will be called in Binder call and the watcher thread.
397             std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
398             prev_hot_severity = sensor_status.prev_hot_severity;
399             prev_cold_severity = sensor_status.prev_cold_severity;
400         }
401         status = getSeverityFromThresholds(sensor_info.hot_thresholds, sensor_info.cold_thresholds,
402                                            sensor_info.hot_hysteresis, sensor_info.cold_hysteresis,
403                                            prev_hot_severity, prev_cold_severity, out->value);
404     }
405 
406     if (throttling_status) {
407         *throttling_status = status;
408     }
409 
410     if (sensor_status.emul_setting != nullptr && sensor_status.emul_setting->emul_severity >= 0) {
411         std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
412         out->throttlingStatus =
413                 static_cast<ThrottlingSeverity>(sensor_status.emul_setting->emul_severity);
414     } else {
415         out->throttlingStatus =
416                 static_cast<size_t>(status.first) > static_cast<size_t>(status.second)
417                         ? status.first
418                         : status.second;
419     }
420     if (sensor_info.is_watch) {
421         std::ostringstream sensor_log;
422         for (const auto &sensor_log_pair : sensor_log_map) {
423             sensor_log << sensor_log_pair.first << ":" << sensor_log_pair.second << " ";
424         }
425         // Update sensor temperature time in state
426         thermal_stats_helper_.updateSensorTempStatsBySeverity(sensor_name, out->throttlingStatus);
427         LOG(INFO) << sensor_name.data() << ":" << out->value << " raw data: " << sensor_log.str();
428     }
429 
430     return true;
431 }
432 
readTemperatureThreshold(std::string_view sensor_name,TemperatureThreshold * out) const433 bool ThermalHelperImpl::readTemperatureThreshold(std::string_view sensor_name,
434                                                  TemperatureThreshold *out) const {
435     // Read the file.  If the file can't be read temp will be empty string.
436     std::string temp;
437     std::string path;
438 
439     if (!sensor_info_map_.count(sensor_name.data())) {
440         LOG(ERROR) << __func__ << ": sensor not found: " << sensor_name;
441         return false;
442     }
443 
444     const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
445 
446     out->type = sensor_info.type;
447     out->name = sensor_name.data();
448     out->hotThrottlingThresholds =
449             std::vector(sensor_info.hot_thresholds.begin(), sensor_info.hot_thresholds.end());
450     out->coldThrottlingThresholds =
451             std::vector(sensor_info.cold_thresholds.begin(), sensor_info.cold_thresholds.end());
452     return true;
453 }
454 
updateCoolingDevices(const std::vector<std::string> & updated_cdev)455 void ThermalHelperImpl::updateCoolingDevices(const std::vector<std::string> &updated_cdev) {
456     int max_state;
457 
458     for (const auto &target_cdev : updated_cdev) {
459         if (thermal_throttling_.getCdevMaxRequest(target_cdev, &max_state)) {
460             if (cooling_devices_.writeCdevFile(target_cdev, std::to_string(max_state))) {
461                 ATRACE_INT(target_cdev.c_str(), max_state);
462                 LOG(INFO) << "Successfully update cdev " << target_cdev << " sysfs to "
463                           << max_state;
464             } else {
465                 LOG(ERROR) << "Failed to update cdev " << target_cdev << " sysfs to " << max_state;
466             }
467         }
468     }
469 }
470 
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) const471 std::pair<ThrottlingSeverity, ThrottlingSeverity> ThermalHelperImpl::getSeverityFromThresholds(
472         const ThrottlingArray &hot_thresholds, const ThrottlingArray &cold_thresholds,
473         const ThrottlingArray &hot_hysteresis, const ThrottlingArray &cold_hysteresis,
474         ThrottlingSeverity prev_hot_severity, ThrottlingSeverity prev_cold_severity,
475         float value) const {
476     ThrottlingSeverity ret_hot = ThrottlingSeverity::NONE;
477     ThrottlingSeverity ret_hot_hysteresis = ThrottlingSeverity::NONE;
478     ThrottlingSeverity ret_cold = ThrottlingSeverity::NONE;
479     ThrottlingSeverity ret_cold_hysteresis = ThrottlingSeverity::NONE;
480 
481     // Here we want to control the iteration from high to low, and ::ndk::enum_range doesn't support
482     // a reverse iterator yet.
483     for (size_t i = static_cast<size_t>(ThrottlingSeverity::SHUTDOWN);
484          i > static_cast<size_t>(ThrottlingSeverity::NONE); --i) {
485         if (!std::isnan(hot_thresholds[i]) && hot_thresholds[i] <= value &&
486             ret_hot == ThrottlingSeverity::NONE) {
487             ret_hot = static_cast<ThrottlingSeverity>(i);
488         }
489         if (!std::isnan(hot_thresholds[i]) && (hot_thresholds[i] - hot_hysteresis[i]) < value &&
490             ret_hot_hysteresis == ThrottlingSeverity::NONE) {
491             ret_hot_hysteresis = static_cast<ThrottlingSeverity>(i);
492         }
493         if (!std::isnan(cold_thresholds[i]) && cold_thresholds[i] >= value &&
494             ret_cold == ThrottlingSeverity::NONE) {
495             ret_cold = static_cast<ThrottlingSeverity>(i);
496         }
497         if (!std::isnan(cold_thresholds[i]) && (cold_thresholds[i] + cold_hysteresis[i]) > value &&
498             ret_cold_hysteresis == ThrottlingSeverity::NONE) {
499             ret_cold_hysteresis = static_cast<ThrottlingSeverity>(i);
500         }
501     }
502     if (static_cast<size_t>(ret_hot) < static_cast<size_t>(prev_hot_severity)) {
503         ret_hot = ret_hot_hysteresis;
504     }
505     if (static_cast<size_t>(ret_cold) < static_cast<size_t>(prev_cold_severity)) {
506         ret_cold = ret_cold_hysteresis;
507     }
508 
509     return std::make_pair(ret_hot, ret_cold);
510 }
511 
isSubSensorValid(std::string_view sensor_data,const SensorFusionType sensor_fusion_type)512 bool ThermalHelperImpl::isSubSensorValid(std::string_view sensor_data,
513                                          const SensorFusionType sensor_fusion_type) {
514     switch (sensor_fusion_type) {
515         case SensorFusionType::SENSOR:
516             if (!sensor_info_map_.count(sensor_data.data())) {
517                 LOG(ERROR) << "Cannot find " << sensor_data.data() << " from sensor info map";
518                 return false;
519             }
520             break;
521         case SensorFusionType::ODPM:
522             if (!GetPowerStatusMap().count(sensor_data.data())) {
523                 LOG(ERROR) << "Cannot find " << sensor_data.data() << " from power status map";
524                 return false;
525             }
526             break;
527         default:
528             break;
529     }
530     return true;
531 }
532 
clearAllThrottling(void)533 void ThermalHelperImpl::clearAllThrottling(void) {
534     // Clear the CDEV request
535     for (const auto &cdev_info_pair : cooling_device_info_map_) {
536         cooling_devices_.writeCdevFile(cdev_info_pair.first, "0");
537     }
538 
539     for (auto &sensor_info_pair : sensor_info_map_) {
540         sensor_info_pair.second.is_watch = false;
541         sensor_info_pair.second.throttling_info.reset();
542         sensor_info_pair.second.hot_thresholds.fill(NAN);
543         sensor_info_pair.second.cold_thresholds.fill(NAN);
544         Temperature temp = {
545                 .type = sensor_info_pair.second.type,
546                 .name = sensor_info_pair.first,
547                 .value = NAN,
548                 .throttlingStatus = ThrottlingSeverity::NONE,
549         };
550         // Send callbacks with NONE severity
551         if (sensor_info_pair.second.send_cb && cb_) {
552             cb_(temp);
553         }
554         // Disable thermal power hints
555         if (sensor_info_pair.second.send_powerhint) {
556             for (const auto &severity : ::ndk::enum_range<ThrottlingSeverity>()) {
557                 power_hal_service_.setMode(sensor_info_pair.first, severity, false);
558             }
559         }
560     }
561 }
562 
initializeSensorMap(const std::unordered_map<std::string,std::string> & path_map)563 bool ThermalHelperImpl::initializeSensorMap(
564         const std::unordered_map<std::string, std::string> &path_map) {
565     for (const auto &sensor_info_pair : sensor_info_map_) {
566         std::string_view sensor_name = sensor_info_pair.first;
567         if (sensor_info_pair.second.virtual_sensor_info != nullptr) {
568             continue;
569         }
570         if (!path_map.count(sensor_name.data())) {
571             LOG(ERROR) << "Could not find " << sensor_name << " in sysfs";
572             return false;
573         }
574 
575         std::string path;
576         if (sensor_info_pair.second.temp_path.empty()) {
577             path = ::android::base::StringPrintf("%s/%s", path_map.at(sensor_name.data()).c_str(),
578                                                  kSensorTempSuffix.data());
579         } else {
580             path = sensor_info_pair.second.temp_path;
581         }
582 
583         if (!thermal_sensors_.addThermalFile(sensor_name, path)) {
584             LOG(ERROR) << "Could not add " << sensor_name << "to sensors map";
585             return false;
586         }
587     }
588     return true;
589 }
590 
initializeCoolingDevices(const std::unordered_map<std::string,std::string> & path_map)591 bool ThermalHelperImpl::initializeCoolingDevices(
592         const std::unordered_map<std::string, std::string> &path_map) {
593     for (auto &cooling_device_info_pair : cooling_device_info_map_) {
594         std::string cooling_device_name = cooling_device_info_pair.first;
595         if (!path_map.count(cooling_device_name)) {
596             LOG(ERROR) << "Could not find " << cooling_device_name << " in sysfs";
597             return false;
598         }
599         // Add cooling device path for thermalHAL to get current state
600         std::string_view path = path_map.at(cooling_device_name);
601         std::string read_path;
602         if (!cooling_device_info_pair.second.read_path.empty()) {
603             read_path = cooling_device_info_pair.second.read_path.data();
604         } else {
605             read_path = ::android::base::StringPrintf("%s/%s", path.data(),
606                                                       kCoolingDeviceCurStateSuffix.data());
607         }
608         if (!cooling_devices_.addThermalFile(cooling_device_name, read_path)) {
609             LOG(ERROR) << "Could not add " << cooling_device_name
610                        << " read path to cooling device map";
611             return false;
612         }
613 
614         std::string state2power_path = ::android::base::StringPrintf(
615                 "%s/%s", path.data(), kCoolingDeviceState2powerSuffix.data());
616         std::string state2power_str;
617         if (::android::base::ReadFileToString(state2power_path, &state2power_str)) {
618             LOG(INFO) << "Cooling device " << cooling_device_info_pair.first
619                       << " use state2power read from sysfs";
620             cooling_device_info_pair.second.state2power.clear();
621 
622             std::stringstream power(state2power_str);
623             unsigned int power_number;
624             int i = 0;
625             while (power >> power_number) {
626                 cooling_device_info_pair.second.state2power.push_back(
627                         static_cast<float>(power_number));
628                 LOG(INFO) << "Cooling device " << cooling_device_info_pair.first << " state:" << i
629                           << " power: " << power_number;
630                 i++;
631             }
632         }
633 
634         // Get max cooling device request state
635         std::string max_state;
636         std::string max_state_path = ::android::base::StringPrintf(
637                 "%s/%s", path.data(), kCoolingDeviceMaxStateSuffix.data());
638         if (!::android::base::ReadFileToString(max_state_path, &max_state)) {
639             LOG(ERROR) << cooling_device_info_pair.first
640                        << " could not open max state file:" << max_state_path;
641             cooling_device_info_pair.second.max_state = std::numeric_limits<int>::max();
642         } else {
643             cooling_device_info_pair.second.max_state = std::stoi(::android::base::Trim(max_state));
644             LOG(INFO) << "Cooling device " << cooling_device_info_pair.first
645                       << " max state: " << cooling_device_info_pair.second.max_state
646                       << " state2power number: "
647                       << cooling_device_info_pair.second.state2power.size();
648             if (cooling_device_info_pair.second.state2power.size() > 0 &&
649                 static_cast<int>(cooling_device_info_pair.second.state2power.size()) !=
650                         (cooling_device_info_pair.second.max_state + 1)) {
651                 LOG(ERROR) << "Invalid state2power number: "
652                            << cooling_device_info_pair.second.state2power.size()
653                            << ", number should be " << cooling_device_info_pair.second.max_state + 1
654                            << " (max_state + 1)";
655                 return false;
656             }
657         }
658 
659         // Add cooling device path for thermalHAL to request state
660         cooling_device_name =
661                 ::android::base::StringPrintf("%s_%s", cooling_device_name.c_str(), "w");
662         std::string write_path;
663         if (!cooling_device_info_pair.second.write_path.empty()) {
664             write_path = cooling_device_info_pair.second.write_path.data();
665         } else {
666             write_path = ::android::base::StringPrintf("%s/%s", path.data(),
667                                                        kCoolingDeviceCurStateSuffix.data());
668         }
669 
670         if (!cooling_devices_.addThermalFile(cooling_device_name, write_path)) {
671             LOG(ERROR) << "Could not add " << cooling_device_name
672                        << " write path to cooling device map";
673             return false;
674         }
675     }
676     return true;
677 }
678 
setMinTimeout(SensorInfo * sensor_info)679 void ThermalHelperImpl::setMinTimeout(SensorInfo *sensor_info) {
680     sensor_info->polling_delay = kMinPollIntervalMs;
681     sensor_info->passive_delay = kMinPollIntervalMs;
682 }
683 
initializeTrip(const std::unordered_map<std::string,std::string> & path_map,std::set<std::string> * monitored_sensors,bool thermal_genl_enabled)684 void ThermalHelperImpl::initializeTrip(const std::unordered_map<std::string, std::string> &path_map,
685                                        std::set<std::string> *monitored_sensors,
686                                        bool thermal_genl_enabled) {
687     for (auto &sensor_info : sensor_info_map_) {
688         if (!sensor_info.second.is_watch || (sensor_info.second.virtual_sensor_info != nullptr)) {
689             continue;
690         }
691 
692         bool trip_update = false;
693         std::string_view sensor_name = sensor_info.first;
694         std::string_view tz_path = path_map.at(sensor_name.data());
695         std::string tz_policy;
696         std::string path =
697                 ::android::base::StringPrintf("%s/%s", (tz_path.data()), kSensorPolicyFile.data());
698 
699         if (thermal_genl_enabled) {
700             trip_update = true;
701         } else {
702             // Check if thermal zone support uevent notify
703             if (!::android::base::ReadFileToString(path, &tz_policy)) {
704                 LOG(ERROR) << sensor_name << " could not open tz policy file:" << path;
705             } else {
706                 tz_policy = ::android::base::Trim(tz_policy);
707                 if (tz_policy != kUserSpaceSuffix) {
708                     LOG(ERROR) << sensor_name << " does not support uevent notify";
709                 } else {
710                     trip_update = true;
711                 }
712             }
713         }
714         if (trip_update) {
715             // Update thermal zone trip point
716             for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
717                 if (!std::isnan(sensor_info.second.hot_thresholds[i]) &&
718                     !std::isnan(sensor_info.second.hot_hysteresis[i])) {
719                     // Update trip_point_0_temp threshold
720                     std::string threshold = std::to_string(static_cast<int>(
721                             sensor_info.second.hot_thresholds[i] / sensor_info.second.multiplier));
722                     path = ::android::base::StringPrintf("%s/%s", (tz_path.data()),
723                                                          kSensorTripPointTempZeroFile.data());
724                     if (!::android::base::WriteStringToFile(threshold, path)) {
725                         LOG(ERROR) << "fail to update " << sensor_name << " trip point: " << path
726                                    << " to " << threshold;
727                         trip_update = false;
728                         break;
729                     }
730                     // Update trip_point_0_hyst threshold
731                     threshold = std::to_string(static_cast<int>(
732                             sensor_info.second.hot_hysteresis[i] / sensor_info.second.multiplier));
733                     path = ::android::base::StringPrintf("%s/%s", (tz_path.data()),
734                                                          kSensorTripPointHystZeroFile.data());
735                     if (!::android::base::WriteStringToFile(threshold, path)) {
736                         LOG(ERROR) << "fail to update " << sensor_name << "trip hyst" << threshold
737                                    << path;
738                         trip_update = false;
739                         break;
740                     }
741                     break;
742                 } else if (i == kThrottlingSeverityCount - 1) {
743                     LOG(ERROR) << sensor_name << ":all thresholds are NAN";
744                     trip_update = false;
745                     break;
746                 }
747             }
748             monitored_sensors->insert(sensor_info.first);
749         }
750 
751         if (!trip_update) {
752             LOG(INFO) << "config Sensor: " << sensor_info.first
753                       << " to default polling interval: " << kMinPollIntervalMs.count();
754             setMinTimeout(&sensor_info.second);
755         }
756     }
757 }
758 
fillCurrentTemperatures(bool filterType,bool filterCallback,TemperatureType type,std::vector<Temperature> * temperatures)759 bool ThermalHelperImpl::fillCurrentTemperatures(bool filterType, bool filterCallback,
760                                                 TemperatureType type,
761                                                 std::vector<Temperature> *temperatures) {
762     std::vector<Temperature> ret;
763     for (const auto &name_info_pair : sensor_info_map_) {
764         Temperature temp;
765         if (name_info_pair.second.is_hidden) {
766             continue;
767         }
768         if (filterType && name_info_pair.second.type != type) {
769             continue;
770         }
771         if (filterCallback && !name_info_pair.second.send_cb) {
772             continue;
773         }
774         if (readTemperature(name_info_pair.first, &temp, nullptr, false)) {
775             ret.emplace_back(std::move(temp));
776         } else {
777             LOG(ERROR) << __func__
778                        << ": error reading temperature for sensor: " << name_info_pair.first;
779         }
780     }
781     *temperatures = ret;
782     return ret.size() > 0;
783 }
784 
fillTemperatureThresholds(bool filterType,TemperatureType type,std::vector<TemperatureThreshold> * thresholds) const785 bool ThermalHelperImpl::fillTemperatureThresholds(
786         bool filterType, TemperatureType type,
787         std::vector<TemperatureThreshold> *thresholds) const {
788     std::vector<TemperatureThreshold> ret;
789     for (const auto &name_info_pair : sensor_info_map_) {
790         TemperatureThreshold temp;
791         if (name_info_pair.second.is_hidden) {
792             continue;
793         }
794         if (filterType && name_info_pair.second.type != type) {
795             continue;
796         }
797         if (readTemperatureThreshold(name_info_pair.first, &temp)) {
798             ret.emplace_back(std::move(temp));
799         } else {
800             LOG(ERROR) << __func__ << ": error reading temperature threshold for sensor: "
801                        << name_info_pair.first;
802             return false;
803         }
804     }
805     *thresholds = ret;
806     return ret.size() > 0;
807 }
808 
fillCurrentCoolingDevices(bool filterType,CoolingType type,std::vector<CoolingDevice> * cooling_devices) const809 bool ThermalHelperImpl::fillCurrentCoolingDevices(
810         bool filterType, CoolingType type, std::vector<CoolingDevice> *cooling_devices) const {
811     std::vector<CoolingDevice> ret;
812     for (const auto &name_info_pair : cooling_device_info_map_) {
813         CoolingDevice value;
814         if (filterType && name_info_pair.second.type != type) {
815             continue;
816         }
817         if (readCoolingDevice(name_info_pair.first, &value)) {
818             ret.emplace_back(std::move(value));
819         } else {
820             LOG(ERROR) << __func__ << ": error reading cooling device: " << name_info_pair.first;
821             return false;
822         }
823     }
824     *cooling_devices = ret;
825     return ret.size() > 0;
826 }
827 
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)828 bool ThermalHelperImpl::readDataByType(std::string_view sensor_data, float *reading_value,
829                                        const SensorFusionType type, const bool force_no_cache,
830                                        std::map<std::string, float> *sensor_log_map) {
831     switch (type) {
832         case SensorFusionType::SENSOR:
833             if (!readThermalSensor(sensor_data.data(), reading_value, force_no_cache,
834                                    sensor_log_map)) {
835                 LOG(ERROR) << "Failed to get " << sensor_data.data() << " data";
836                 return false;
837             }
838             break;
839         case SensorFusionType::ODPM:
840             *reading_value = GetPowerStatusMap().at(sensor_data.data()).last_updated_avg_power;
841             if (std::isnan(*reading_value)) {
842                 LOG(INFO) << "Power data " << sensor_data.data() << " is under collecting";
843                 return true;
844             }
845             (*sensor_log_map)[sensor_data.data()] = *reading_value;
846             break;
847         case SensorFusionType::CONSTANT:
848             *reading_value = std::atof(sensor_data.data());
849             break;
850         default:
851             break;
852     }
853     return true;
854 }
855 
856 constexpr int kTranTimeoutParam = 2;
857 
readThermalSensor(std::string_view sensor_name,float * temp,const bool force_no_cache,std::map<std::string,float> * sensor_log_map)858 bool ThermalHelperImpl::readThermalSensor(std::string_view sensor_name, float *temp,
859                                           const bool force_no_cache,
860                                           std::map<std::string, float> *sensor_log_map) {
861     float temp_val = 0.0;
862     std::string file_reading;
863     boot_clock::time_point now = boot_clock::now();
864 
865     ATRACE_NAME(StringPrintf("ThermalHelper::readThermalSensor - %s", sensor_name.data()).c_str());
866     if (!(sensor_info_map_.count(sensor_name.data()) &&
867           sensor_status_map_.count(sensor_name.data()))) {
868         return false;
869     }
870 
871     const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
872     auto &sensor_status = sensor_status_map_.at(sensor_name.data());
873 
874     {
875         std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
876         if (sensor_status.emul_setting != nullptr &&
877             !isnan(sensor_status.emul_setting->emul_temp)) {
878             *temp = sensor_status.emul_setting->emul_temp;
879             return true;
880         }
881     }
882 
883     const auto since_last_update = std::chrono::duration_cast<std::chrono::milliseconds>(
884             now - sensor_status.thermal_cached.timestamp);
885 
886     // Check if thermal data need to be read from cache
887     if (!force_no_cache &&
888         (sensor_status.thermal_cached.timestamp != boot_clock::time_point::min()) &&
889         (since_last_update < sensor_info.time_resolution) &&
890         !isnan(sensor_status.thermal_cached.temp)) {
891         *temp = sensor_status.thermal_cached.temp;
892         (*sensor_log_map)[sensor_name.data()] = *temp;
893         ATRACE_INT((sensor_name.data() + std::string("-cached")).c_str(), static_cast<int>(*temp));
894         return true;
895     }
896 
897     // Reading thermal sensor according to it's composition
898     if (sensor_info.virtual_sensor_info == nullptr) {
899         if (!thermal_sensors_.readThermalFile(sensor_name.data(), &file_reading) ||
900             file_reading.empty()) {
901             LOG(ERROR) << "failed to read sensor: " << sensor_name;
902             return false;
903         }
904         *temp = std::stof(::android::base::Trim(file_reading));
905     } else {
906         for (size_t i = 0; i < sensor_info.virtual_sensor_info->linked_sensors.size(); i++) {
907             float sensor_reading = 0.0;
908             // Get the sensor reading data
909             if (!readDataByType(sensor_info.virtual_sensor_info->linked_sensors[i], &sensor_reading,
910                                 sensor_info.virtual_sensor_info->linked_sensors_type[i],
911                                 force_no_cache, sensor_log_map)) {
912                 LOG(ERROR) << "Failed to read " << sensor_name.data() << "'s linked sensor "
913                            << sensor_info.virtual_sensor_info->linked_sensors[i];
914                 return false;
915             }
916 
917             float coefficient = 0.0;
918             if (!readDataByType(sensor_info.virtual_sensor_info->coefficients[i], &coefficient,
919                                 sensor_info.virtual_sensor_info->coefficients_type[i],
920                                 force_no_cache, sensor_log_map)) {
921                 LOG(ERROR) << "Failed to read " << sensor_name.data() << "'s coefficient "
922                            << sensor_info.virtual_sensor_info->coefficients[i];
923                 return false;
924             }
925 
926             if (std::isnan(sensor_reading) || std::isnan(coefficient)) {
927                 LOG(INFO) << sensor_name << " data is under collecting";
928                 return true;
929             }
930 
931             switch (sensor_info.virtual_sensor_info->formula) {
932                 case FormulaOption::COUNT_THRESHOLD:
933                     if ((coefficient < 0 && sensor_reading < -coefficient) ||
934                         (coefficient >= 0 && sensor_reading >= coefficient))
935                         temp_val += 1;
936                     break;
937                 case FormulaOption::WEIGHTED_AVG:
938                     temp_val += sensor_reading * coefficient;
939                     break;
940                 case FormulaOption::MAXIMUM:
941                     if (i == 0)
942                         temp_val = std::numeric_limits<float>::lowest();
943                     if (sensor_reading * coefficient > temp_val)
944                         temp_val = sensor_reading * coefficient;
945                     break;
946                 case FormulaOption::MINIMUM:
947                     if (i == 0)
948                         temp_val = std::numeric_limits<float>::max();
949                     if (sensor_reading * coefficient < temp_val)
950                         temp_val = sensor_reading * coefficient;
951                     break;
952                 default:
953                     break;
954             }
955         }
956         *temp = (temp_val + sensor_info.virtual_sensor_info->offset);
957     }
958 
959     if (!isnan(sensor_info.step_ratio) && !isnan(sensor_status.thermal_cached.temp) &&
960         since_last_update < sensor_info.passive_delay * kTranTimeoutParam) {
961         *temp = (sensor_info.step_ratio * *temp +
962                  (1 - sensor_info.step_ratio) * sensor_status.thermal_cached.temp);
963     }
964 
965     (*sensor_log_map)[sensor_name.data()] = *temp;
966     ATRACE_INT(sensor_name.data(), static_cast<int>(*temp));
967 
968     {
969         std::unique_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
970         sensor_status.thermal_cached.temp = *temp;
971         sensor_status.thermal_cached.timestamp = now;
972     }
973     auto real_temp = (*temp) * sensor_info.multiplier;
974     thermal_stats_helper_.updateSensorTempStatsByThreshold(sensor_name, real_temp);
975     return true;
976 }
977 
978 // This is called in the different thread context and will update sensor_status
979 // uevent_sensors is the set of sensors which trigger uevent from thermal core driver.
thermalWatcherCallbackFunc(const std::set<std::string> & uevent_sensors)980 std::chrono::milliseconds ThermalHelperImpl::thermalWatcherCallbackFunc(
981         const std::set<std::string> &uevent_sensors) {
982     std::vector<Temperature> temps;
983     std::vector<std::string> cooling_devices_to_update;
984     boot_clock::time_point now = boot_clock::now();
985     auto min_sleep_ms = std::chrono::milliseconds::max();
986     bool power_data_is_updated = false;
987 
988     ATRACE_CALL();
989     for (auto &name_status_pair : sensor_status_map_) {
990         bool force_update = false;
991         bool force_no_cache = false;
992         Temperature temp;
993         TemperatureThreshold threshold;
994         SensorStatus &sensor_status = name_status_pair.second;
995         const SensorInfo &sensor_info = sensor_info_map_.at(name_status_pair.first);
996 
997         // Only handle the sensors in allow list
998         if (!sensor_info.is_watch) {
999             continue;
1000         }
1001 
1002         ATRACE_NAME(StringPrintf("ThermalHelper::thermalWatcherCallbackFunc - %s",
1003                                  name_status_pair.first.data())
1004                             .c_str());
1005 
1006         std::chrono::milliseconds time_elapsed_ms = std::chrono::milliseconds::zero();
1007         auto sleep_ms = (sensor_status.severity != ThrottlingSeverity::NONE)
1008                                 ? sensor_info.passive_delay
1009                                 : sensor_info.polling_delay;
1010 
1011         if (sensor_info.virtual_sensor_info != nullptr &&
1012             !sensor_info.virtual_sensor_info->trigger_sensors.empty()) {
1013             for (size_t i = 0; i < sensor_info.virtual_sensor_info->trigger_sensors.size(); i++) {
1014                 const auto &trigger_sensor_status =
1015                         sensor_status_map_.at(sensor_info.virtual_sensor_info->trigger_sensors[i]);
1016                 if (trigger_sensor_status.severity != ThrottlingSeverity::NONE) {
1017                     sleep_ms = sensor_info.passive_delay;
1018                     break;
1019                 }
1020             }
1021         }
1022         // Check if the sensor need to be updated
1023         if (sensor_status.last_update_time == boot_clock::time_point::min()) {
1024             force_update = true;
1025         } else {
1026             time_elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
1027                     now - sensor_status.last_update_time);
1028             if (uevent_sensors.size()) {
1029                 if (sensor_info.virtual_sensor_info != nullptr) {
1030                     for (size_t i = 0; i < sensor_info.virtual_sensor_info->trigger_sensors.size();
1031                          i++) {
1032                         if (uevent_sensors.find(
1033                                     sensor_info.virtual_sensor_info->trigger_sensors[i]) !=
1034                             uevent_sensors.end()) {
1035                             force_update = true;
1036                             break;
1037                         }
1038                     }
1039                 } else if (uevent_sensors.find(name_status_pair.first) != uevent_sensors.end()) {
1040                     force_update = true;
1041                     force_no_cache = true;
1042                 }
1043             } else if (time_elapsed_ms > sleep_ms) {
1044                 force_update = true;
1045             }
1046         }
1047         {
1048             std::lock_guard<std::shared_mutex> _lock(sensor_status_map_mutex_);
1049             if (sensor_status.emul_setting != nullptr &&
1050                 sensor_status.emul_setting->pending_update) {
1051                 force_update = true;
1052                 sensor_status.emul_setting->pending_update = false;
1053                 LOG(INFO) << "Update " << name_status_pair.first.data()
1054                           << " right away with emul setting";
1055             }
1056         }
1057         LOG(VERBOSE) << "sensor " << name_status_pair.first
1058                      << ": time_elapsed=" << time_elapsed_ms.count()
1059                      << ", sleep_ms=" << sleep_ms.count() << ", force_update = " << force_update
1060                      << ", force_no_cache = " << force_no_cache;
1061 
1062         if (!force_update) {
1063             auto timeout_remaining = sleep_ms - time_elapsed_ms;
1064             if (min_sleep_ms > timeout_remaining) {
1065                 min_sleep_ms = timeout_remaining;
1066             }
1067             LOG(VERBOSE) << "sensor " << name_status_pair.first
1068                          << ": timeout_remaining=" << timeout_remaining.count();
1069             continue;
1070         }
1071 
1072         std::pair<ThrottlingSeverity, ThrottlingSeverity> throttling_status;
1073         if (!readTemperature(name_status_pair.first, &temp, &throttling_status, force_no_cache)) {
1074             LOG(ERROR) << __func__
1075                        << ": error reading temperature for sensor: " << name_status_pair.first;
1076             continue;
1077         }
1078         if (!readTemperatureThreshold(name_status_pair.first, &threshold)) {
1079             LOG(ERROR) << __func__ << ": error reading temperature threshold for sensor: "
1080                        << name_status_pair.first;
1081             continue;
1082         }
1083 
1084         {
1085             // writer lock
1086             std::unique_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
1087             if (throttling_status.first != sensor_status.prev_hot_severity) {
1088                 sensor_status.prev_hot_severity = throttling_status.first;
1089             }
1090             if (throttling_status.second != sensor_status.prev_cold_severity) {
1091                 sensor_status.prev_cold_severity = throttling_status.second;
1092             }
1093             if (temp.throttlingStatus != sensor_status.severity) {
1094                 temps.push_back(temp);
1095                 sensor_status.severity = temp.throttlingStatus;
1096                 sleep_ms = (sensor_status.severity != ThrottlingSeverity::NONE)
1097                                    ? sensor_info.passive_delay
1098                                    : sensor_info.polling_delay;
1099             }
1100         }
1101 
1102         if (!power_data_is_updated) {
1103             power_files_.refreshPowerStatus();
1104             power_data_is_updated = true;
1105         }
1106 
1107         if (sensor_status.severity == ThrottlingSeverity::NONE) {
1108             thermal_throttling_.clearThrottlingData(name_status_pair.first, sensor_info);
1109         } else {
1110             // update thermal throttling request
1111             thermal_throttling_.thermalThrottlingUpdate(
1112                     temp, sensor_info, sensor_status.severity, time_elapsed_ms,
1113                     power_files_.GetPowerStatusMap(), cooling_device_info_map_);
1114         }
1115 
1116         thermal_throttling_.computeCoolingDevicesRequest(
1117                 name_status_pair.first, sensor_info, sensor_status.severity,
1118                 &cooling_devices_to_update, &thermal_stats_helper_);
1119         if (min_sleep_ms > sleep_ms) {
1120             min_sleep_ms = sleep_ms;
1121         }
1122 
1123         LOG(VERBOSE) << "Sensor " << name_status_pair.first << ": sleep_ms=" << sleep_ms.count()
1124                      << ", min_sleep_ms voting result=" << min_sleep_ms.count();
1125         sensor_status.last_update_time = now;
1126     }
1127 
1128     if (!cooling_devices_to_update.empty()) {
1129         updateCoolingDevices(cooling_devices_to_update);
1130     }
1131 
1132     if (!temps.empty()) {
1133         for (const auto &t : temps) {
1134             if (sensor_info_map_.at(t.name).send_cb && cb_) {
1135                 cb_(t);
1136             }
1137 
1138             if (sensor_info_map_.at(t.name).send_powerhint) {
1139                 power_hal_service_.sendPowerExtHint(t);
1140             }
1141         }
1142     }
1143 
1144     int count_failed_reporting = thermal_stats_helper_.reportStats();
1145     if (count_failed_reporting != 0) {
1146         LOG(ERROR) << "Failed to report " << count_failed_reporting << " thermal stats";
1147     }
1148 
1149     const auto since_last_power_log_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
1150             now - power_files_.GetPrevPowerLogTime());
1151     if (since_last_power_log_ms >= kPowerLogIntervalMs) {
1152         power_files_.logPowerStatus(now);
1153     }
1154 
1155     return min_sleep_ms;
1156 }
1157 
1158 }  // namespace implementation
1159 }  // namespace thermal
1160 }  // namespace hardware
1161 }  // namespace android
1162 }  // namespace aidl
1163