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