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