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