1 /*
2  * Copyright (C) 2018 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 
17 #include <iterator>
18 #include <set>
19 #include <sstream>
20 #include <thread>
21 #include <vector>
22 
23 #include <android-base/file.h>
24 #include <android-base/logging.h>
25 #include <android-base/properties.h>
26 #include <android-base/stringprintf.h>
27 #include <android-base/strings.h>
28 #include <android/binder_manager.h>
29 #include <hidl/HidlTransportSupport.h>
30 
31 #include "thermal-helper.h"
32 
33 namespace android {
34 namespace hardware {
35 namespace thermal {
36 namespace V2_0 {
37 namespace implementation {
38 
39 constexpr std::string_view kCpuOnlineRoot("/sys/devices/system/cpu");
40 constexpr std::string_view kThermalSensorsRoot("/sys/devices/virtual/thermal");
41 constexpr std::string_view kCpuUsageFile("/proc/stat");
42 constexpr std::string_view kCpuOnlineFileSuffix("online");
43 constexpr std::string_view kCpuPresentFile("/sys/devices/system/cpu/present");
44 constexpr std::string_view kSensorPrefix("thermal_zone");
45 constexpr std::string_view kCoolingDevicePrefix("cooling_device");
46 constexpr std::string_view kThermalNameFile("type");
47 constexpr std::string_view kSensorPolicyFile("policy");
48 constexpr std::string_view kSensorTempSuffix("temp");
49 constexpr std::string_view kSensorTripPointTempZeroFile("trip_point_0_temp");
50 constexpr std::string_view kSensorTripPointHystZeroFile("trip_point_0_hyst");
51 constexpr std::string_view kUserSpaceSuffix("user_space");
52 constexpr std::string_view kCoolingDeviceCurStateSuffix("cur_state");
53 constexpr std::string_view kCoolingDeviceMaxStateSuffix("max_state");
54 constexpr std::string_view kCoolingDeviceState2powerSuffix("state2power_table");
55 constexpr std::string_view kConfigProperty("vendor.thermal.config");
56 constexpr std::string_view kConfigDefaultFileName("thermal_info_config.json");
57 constexpr std::string_view kThermalGenlProperty("persist.vendor.enable.thermal.genl");
58 constexpr std::string_view kThermalDisabledProperty("vendor.disable.thermal.control");
59 
60 namespace {
61 using android::base::StringPrintf;
62 using android::hardware::thermal::V2_0::toString;
63 
64 /*
65  * Pixel don't offline CPU, so std::thread::hardware_concurrency(); should work.
66  * However /sys/devices/system/cpu/present is preferred.
67  * The file is expected to contain single text line with two numbers %d-%d,
68  * which is a range of available cpu numbers, e.g. 0-7 would mean there
69  * are 8 cores number from 0 to 7.
70  * For Android systems this approach is safer than using cpufeatures, see bug
71  * b/36941727.
72  */
getNumberOfCores()73 static int getNumberOfCores() {
74     std::string file;
75     if (!android::base::ReadFileToString(kCpuPresentFile.data(), &file)) {
76         LOG(ERROR) << "Error reading Cpu present file: " << kCpuPresentFile;
77         return 0;
78     }
79     std::vector<std::string> pieces = android::base::Split(file, "-");
80     if (pieces.size() != 2) {
81         LOG(ERROR) << "Error parsing Cpu present file content: " << file;
82         return 0;
83     }
84     auto min_core = std::stoul(pieces[0]);
85     auto max_core = std::stoul(pieces[1]);
86     if (max_core < min_core) {
87         LOG(ERROR) << "Error parsing Cpu present min and max: " << min_core << " - " << max_core;
88         return 0;
89     }
90     return static_cast<std::size_t>(max_core - min_core + 1);
91 }
92 const int kMaxCpus = getNumberOfCores();
93 
parseCpuUsagesFileAndAssignUsages(hidl_vec<CpuUsage> * cpu_usages)94 void parseCpuUsagesFileAndAssignUsages(hidl_vec<CpuUsage> *cpu_usages) {
95     std::string data;
96     if (!android::base::ReadFileToString(kCpuUsageFile.data(), &data)) {
97         LOG(ERROR) << "Error reading cpu usage file: " << kCpuUsageFile;
98         return;
99     }
100 
101     std::istringstream stat_data(data);
102     std::string line;
103     while (std::getline(stat_data, line)) {
104         if (!line.find("cpu") && isdigit(line[3])) {
105             // Split the string using spaces.
106             std::vector<std::string> words = android::base::Split(line, " ");
107             std::string cpu_name = words[0];
108             int cpu_num = std::stoi(cpu_name.substr(3));
109 
110             if (cpu_num < kMaxCpus) {
111                 uint64_t user = std::stoull(words[1]);
112                 uint64_t nice = std::stoull(words[2]);
113                 uint64_t system = std::stoull(words[3]);
114                 uint64_t idle = std::stoull(words[4]);
115 
116                 // Check if the CPU is online by reading the online file.
117                 std::string cpu_online_path =
118                         StringPrintf("%s/%s/%s", kCpuOnlineRoot.data(), cpu_name.c_str(),
119                                      kCpuOnlineFileSuffix.data());
120                 std::string is_online;
121                 if (!android::base::ReadFileToString(cpu_online_path, &is_online)) {
122                     LOG(ERROR) << "Could not open Cpu online file: " << cpu_online_path;
123                     if (cpu_num != 0) {
124                         return;
125                     }
126                     // Some architecture cannot offline cpu0, so assuming it is online
127                     is_online = "1";
128                 }
129                 is_online = android::base::Trim(is_online);
130 
131                 (*cpu_usages)[cpu_num].active = user + nice + system;
132                 (*cpu_usages)[cpu_num].total = user + nice + system + idle;
133                 (*cpu_usages)[cpu_num].isOnline = (is_online == "1") ? true : false;
134             } else {
135                 LOG(ERROR) << "Unexpected cpu number: " << words[0];
136                 return;
137             }
138         }
139     }
140 }
141 
parseThermalPathMap(std::string_view prefix)142 std::unordered_map<std::string, std::string> parseThermalPathMap(std::string_view prefix) {
143     std::unordered_map<std::string, std::string> path_map;
144     std::unique_ptr<DIR, int (*)(DIR *)> dir(opendir(kThermalSensorsRoot.data()), closedir);
145     if (!dir) {
146         return path_map;
147     }
148 
149     // std::filesystem is not available for vendor yet
150     // see discussion: aosp/894015
151     while (struct dirent *dp = readdir(dir.get())) {
152         if (dp->d_type != DT_DIR) {
153             continue;
154         }
155 
156         if (!android::base::StartsWith(dp->d_name, prefix.data())) {
157             continue;
158         }
159 
160         std::string path = android::base::StringPrintf("%s/%s/%s", kThermalSensorsRoot.data(),
161                                                        dp->d_name, kThermalNameFile.data());
162         std::string name;
163         if (!android::base::ReadFileToString(path, &name)) {
164             PLOG(ERROR) << "Failed to read from " << path;
165             continue;
166         }
167 
168         path_map.emplace(
169                 android::base::Trim(name),
170                 android::base::StringPrintf("%s/%s", kThermalSensorsRoot.data(), dp->d_name));
171     }
172 
173     return path_map;
174 }
175 
176 }  // namespace
PowerHalService()177 PowerHalService::PowerHalService()
178     : power_hal_aidl_exist_(true), power_hal_aidl_(nullptr), power_hal_ext_aidl_(nullptr) {
179     connect();
180 }
181 
connect()182 bool PowerHalService::connect() {
183     std::lock_guard<std::mutex> lock(lock_);
184     if (!power_hal_aidl_exist_)
185         return false;
186 
187     if (power_hal_aidl_ != nullptr)
188         return true;
189 
190     const std::string kInstance = std::string(IPower::descriptor) + "/default";
191     ndk::SpAIBinder power_binder = ndk::SpAIBinder(AServiceManager_getService(kInstance.c_str()));
192     ndk::SpAIBinder ext_power_binder;
193 
194     if (power_binder.get() == nullptr) {
195         LOG(ERROR) << "Cannot get Power Hal Binder";
196         power_hal_aidl_exist_ = false;
197         return false;
198     }
199 
200     power_hal_aidl_ = IPower::fromBinder(power_binder);
201 
202     if (power_hal_aidl_ == nullptr) {
203         power_hal_aidl_exist_ = false;
204         LOG(ERROR) << "Cannot get Power Hal AIDL" << kInstance.c_str();
205         return false;
206     }
207 
208     if (STATUS_OK != AIBinder_getExtension(power_binder.get(), ext_power_binder.getR()) ||
209         ext_power_binder.get() == nullptr) {
210         LOG(ERROR) << "Cannot get Power Hal Extension Binder";
211         power_hal_aidl_exist_ = false;
212         return false;
213     }
214 
215     power_hal_ext_aidl_ = IPowerExt::fromBinder(ext_power_binder);
216     if (power_hal_ext_aidl_ == nullptr) {
217         LOG(ERROR) << "Cannot get Power Hal Extension AIDL";
218         power_hal_aidl_exist_ = false;
219     }
220 
221     return true;
222 }
223 
isModeSupported(const std::string & type,const ThrottlingSeverity & t)224 bool PowerHalService::isModeSupported(const std::string &type, const ThrottlingSeverity &t) {
225     bool isSupported = false;
226     if (!isPowerHalConnected()) {
227         return false;
228     }
229     std::string power_hint = StringPrintf("THERMAL_%s_%s", type.c_str(), toString(t).c_str());
230     lock_.lock();
231     if (!power_hal_ext_aidl_->isModeSupported(power_hint, &isSupported).isOk()) {
232         LOG(ERROR) << "Fail to check supported mode, Hint: " << power_hint;
233         power_hal_aidl_exist_ = false;
234         power_hal_ext_aidl_ = nullptr;
235         power_hal_aidl_ = nullptr;
236         lock_.unlock();
237         return false;
238     }
239     lock_.unlock();
240     return isSupported;
241 }
242 
setMode(const std::string & type,const ThrottlingSeverity & t,const bool & enable)243 void PowerHalService::setMode(const std::string &type, const ThrottlingSeverity &t,
244                               const bool &enable) {
245     if (!isPowerHalConnected()) {
246         return;
247     }
248 
249     std::string power_hint = StringPrintf("THERMAL_%s_%s", type.c_str(), toString(t).c_str());
250     LOG(INFO) << "Send Hint " << power_hint << " Enable: " << std::boolalpha << enable;
251     lock_.lock();
252     if (!power_hal_ext_aidl_->setMode(power_hint, enable).isOk()) {
253         LOG(ERROR) << "Fail to set mode, Hint: " << power_hint;
254         power_hal_aidl_exist_ = false;
255         power_hal_ext_aidl_ = nullptr;
256         power_hal_aidl_ = nullptr;
257         lock_.unlock();
258         return;
259     }
260     lock_.unlock();
261 }
262 
263 /*
264  * Populate the sensor_name_to_file_map_ map by walking through the file tree,
265  * reading the type file and assigning the temp file path to the map.  If we do
266  * not succeed, abort.
267  */
ThermalHelper(const NotificationCallback & cb)268 ThermalHelper::ThermalHelper(const NotificationCallback &cb)
269     : thermal_watcher_(new ThermalWatcher(
270               std::bind(&ThermalHelper::thermalWatcherCallbackFunc, this, std::placeholders::_1))),
271       cb_(cb) {
272     const std::string config_path =
273             "/vendor/etc/" +
274             android::base::GetProperty(kConfigProperty.data(), kConfigDefaultFileName.data());
275     cooling_device_info_map_ = ParseCoolingDevice(config_path);
276     sensor_info_map_ = ParseSensorInfo(config_path);
277     power_rail_info_map_ = ParsePowerRailInfo(config_path);
278     auto tz_map = parseThermalPathMap(kSensorPrefix.data());
279     auto cdev_map = parseThermalPathMap(kCoolingDevicePrefix.data());
280 
281     is_initialized_ = initializeSensorMap(tz_map) && initializeCoolingDevices(cdev_map);
282     if (!is_initialized_) {
283         LOG(FATAL) << "ThermalHAL could not be initialized properly.";
284     }
285 
286     for (auto const &name_status_pair : sensor_info_map_) {
287         sensor_status_map_[name_status_pair.first] = {
288                 .severity = ThrottlingSeverity::NONE,
289                 .prev_hot_severity = ThrottlingSeverity::NONE,
290                 .prev_cold_severity = ThrottlingSeverity::NONE,
291                 .prev_hint_severity = ThrottlingSeverity::NONE,
292                 .last_update_time = boot_clock::time_point::min(),
293                 .err_integral = 0.0,
294                 .prev_err = NAN,
295         };
296 
297         bool invalid_binded_cdev = false;
298         for (auto &binded_cdev_pair :
299              name_status_pair.second.throttling_info->binded_cdev_info_map) {
300             if (!cooling_device_info_map_.count(binded_cdev_pair.first)) {
301                 invalid_binded_cdev = true;
302                 LOG(ERROR) << "Could not find " << binded_cdev_pair.first
303                            << " in cooling device info map";
304             }
305 
306             for (const auto &cdev_weight : binded_cdev_pair.second.cdev_weight_for_pid) {
307                 if (!std::isnan(cdev_weight)) {
308                     sensor_status_map_[name_status_pair.first]
309                             .pid_request_map[binded_cdev_pair.first] = 0;
310                     cdev_status_map_[binded_cdev_pair.first][name_status_pair.first] = 0;
311                     break;
312                 }
313             }
314 
315             for (const auto &limit_info : binded_cdev_pair.second.limit_info) {
316                 if (limit_info > 0) {
317                     sensor_status_map_[name_status_pair.first]
318                             .hard_limit_request_map[binded_cdev_pair.first] = 0;
319                     cdev_status_map_[binded_cdev_pair.first][name_status_pair.first] = 0;
320                 }
321             }
322             const auto &cdev_info = cooling_device_info_map_.at(binded_cdev_pair.first);
323 
324             for (auto &cdev_ceiling : binded_cdev_pair.second.cdev_ceiling) {
325                 if (cdev_ceiling > cdev_info.max_state) {
326                     if (cdev_ceiling != std::numeric_limits<int>::max()) {
327                         LOG(ERROR) << "Sensor " << name_status_pair.first << "'s "
328                                    << binded_cdev_pair.first << " cdev_ceiling:" << cdev_ceiling
329                                    << " is higher than max state:" << cdev_info.max_state;
330                     }
331                     cdev_ceiling = cdev_info.max_state;
332                 }
333             }
334 
335             if (power_rail_info_map_.count(binded_cdev_pair.second.power_rail) &&
336                 power_rail_info_map_.at(binded_cdev_pair.second.power_rail).power_sample_count &&
337                 power_files_.findEnergySourceToWatch()) {
338                 const auto &power_rail_info =
339                         power_rail_info_map_.at(binded_cdev_pair.second.power_rail);
340                 if (!power_files_.registerPowerRailsToWatch(
341                             name_status_pair.first, binded_cdev_pair.first, binded_cdev_pair.second,
342                             cdev_info, power_rail_info)) {
343                     invalid_binded_cdev = true;
344                     LOG(ERROR) << "Could not find " << binded_cdev_pair.first
345                                << "'s power energy source: " << binded_cdev_pair.second.power_rail;
346                 }
347             }
348         }
349 
350         if (invalid_binded_cdev) {
351             name_status_pair.second.throttling_info->binded_cdev_info_map.clear();
352             sensor_status_map_[name_status_pair.first].hard_limit_request_map.clear();
353             sensor_status_map_[name_status_pair.first].pid_request_map.clear();
354         }
355 
356         if (name_status_pair.second.virtual_sensor_info != nullptr &&
357             name_status_pair.second.is_monitor) {
358             if (sensor_info_map_.count(
359                         name_status_pair.second.virtual_sensor_info->trigger_sensor)) {
360                 sensor_info_map_[name_status_pair.second.virtual_sensor_info->trigger_sensor]
361                         .is_monitor = true;
362             } else {
363                 LOG(FATAL) << name_status_pair.first << " does not have trigger sensor: "
364                            << name_status_pair.second.virtual_sensor_info->trigger_sensor;
365             }
366         }
367     }
368 
369     const bool thermal_throttling_disabled =
370             android::base::GetBoolProperty(kThermalDisabledProperty.data(), false);
371 
372     if (thermal_throttling_disabled) {
373         LOG(INFO) << kThermalDisabledProperty.data() << " is true";
374         for (const auto &cdev_pair : cooling_device_info_map_) {
375             if (cooling_devices_.writeCdevFile(cdev_pair.first, std::to_string(0))) {
376                 LOG(INFO) << "Successfully clear cdev " << cdev_pair.first << " to 0";
377             }
378         }
379         return;
380     }
381 
382     const bool thermal_genl_enabled =
383             android::base::GetBoolProperty(kThermalGenlProperty.data(), false);
384 
385     std::set<std::string> monitored_sensors;
386     initializeTrip(tz_map, &monitored_sensors, thermal_genl_enabled);
387 
388     if (thermal_genl_enabled) {
389         thermal_watcher_->registerFilesToWatchNl(monitored_sensors);
390     } else {
391         thermal_watcher_->registerFilesToWatch(monitored_sensors);
392     }
393 
394     // Need start watching after status map initialized
395     is_initialized_ = thermal_watcher_->startWatchingDeviceFiles();
396     if (!is_initialized_) {
397         LOG(FATAL) << "ThermalHAL could not start watching thread properly.";
398     }
399 
400     if (!connectToPowerHal()) {
401         LOG(ERROR) << "Fail to connect to Power Hal";
402     } else {
403         updateSupportedPowerHints();
404     }
405 }
406 
getThermalZoneTypeById(int tz_id,std::string * type)407 bool getThermalZoneTypeById(int tz_id, std::string *type) {
408     std::string tz_type;
409     std::string path =
410             android::base::StringPrintf("%s/%s%d/%s", kThermalSensorsRoot.data(),
411                                         kSensorPrefix.data(), tz_id, kThermalNameFile.data());
412     LOG(INFO) << "TZ Path: " << path;
413     if (!::android::base::ReadFileToString(path, &tz_type)) {
414         LOG(ERROR) << "Failed to read sensor: " << tz_type;
415         return false;
416     }
417 
418     // Strip the newline.
419     *type = ::android::base::Trim(tz_type);
420     LOG(INFO) << "TZ type: " << *type;
421     return true;
422 }
423 
readCoolingDevice(std::string_view cooling_device,CoolingDevice_2_0 * out) const424 bool ThermalHelper::readCoolingDevice(std::string_view cooling_device,
425                                       CoolingDevice_2_0 *out) const {
426     // Read the file.  If the file can't be read temp will be empty string.
427     std::string data;
428 
429     if (!cooling_devices_.readThermalFile(cooling_device, &data)) {
430         LOG(ERROR) << "readCoolingDevice: failed to read cooling_device: " << cooling_device;
431         return false;
432     }
433 
434     const CdevInfo &cdev_info = cooling_device_info_map_.at(cooling_device.data());
435     const CoolingType &type = cdev_info.type;
436 
437     out->type = type;
438     out->name = cooling_device.data();
439     out->value = std::stoi(data);
440 
441     return true;
442 }
443 
readTemperature(std::string_view sensor_name,Temperature_1_0 * out,bool is_virtual_sensor) const444 bool ThermalHelper::readTemperature(std::string_view sensor_name, Temperature_1_0 *out,
445                                     bool is_virtual_sensor) const {
446     // Read the file.  If the file can't be read temp will be empty string.
447     std::string temp;
448 
449     if (!is_virtual_sensor) {
450         if (!thermal_sensors_.readThermalFile(sensor_name, &temp)) {
451             LOG(ERROR) << "readTemperature: sensor not found: " << sensor_name;
452             return false;
453         }
454 
455         if (temp.empty()) {
456             LOG(ERROR) << "readTemperature: failed to read sensor: " << sensor_name;
457             return false;
458         }
459     } else {
460         if (!checkVirtualSensor(sensor_name.data(), &temp)) {
461             LOG(ERROR) << "readTemperature: failed to read virtual sensor: " << sensor_name;
462             return false;
463         }
464     }
465 
466     const SensorInfo &sensor_info = sensor_info_map_.at(sensor_name.data());
467     TemperatureType_1_0 type =
468         (static_cast<int>(sensor_info.type) > static_cast<int>(TemperatureType_1_0::SKIN))
469             ? TemperatureType_1_0::UNKNOWN
470             : static_cast<TemperatureType_1_0>(sensor_info.type);
471     out->type = type;
472     out->name = sensor_name.data();
473     out->currentValue = std::stof(temp) * sensor_info.multiplier;
474     out->throttlingThreshold =
475         sensor_info.hot_thresholds[static_cast<size_t>(ThrottlingSeverity::SEVERE)];
476     out->shutdownThreshold =
477         sensor_info.hot_thresholds[static_cast<size_t>(ThrottlingSeverity::SHUTDOWN)];
478     out->vrThrottlingThreshold = sensor_info.vr_threshold;
479 
480     return true;
481 }
482 
readTemperature(std::string_view sensor_name,Temperature_2_0 * out,std::pair<ThrottlingSeverity,ThrottlingSeverity> * throtting_status,bool is_virtual_sensor) const483 bool ThermalHelper::readTemperature(
484         std::string_view sensor_name, Temperature_2_0 *out,
485         std::pair<ThrottlingSeverity, ThrottlingSeverity> *throtting_status,
486         bool is_virtual_sensor) const {
487     // Read the file.  If the file can't be read temp will be empty string.
488     std::string temp;
489 
490     if (!is_virtual_sensor) {
491         if (!thermal_sensors_.readThermalFile(sensor_name, &temp)) {
492             LOG(ERROR) << "readTemperature: sensor not found: " << sensor_name;
493             return false;
494         }
495 
496         if (temp.empty()) {
497             LOG(ERROR) << "readTemperature: failed to read sensor: " << sensor_name;
498             return false;
499         }
500     } else {
501         if (!checkVirtualSensor(sensor_name.data(), &temp)) {
502             LOG(ERROR) << "readTemperature: failed to read virtual sensor: " << sensor_name;
503             return false;
504         }
505     }
506 
507     const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
508     out->type = sensor_info.type;
509     out->name = sensor_name.data();
510     out->value = std::stof(temp) * sensor_info.multiplier;
511 
512     std::pair<ThrottlingSeverity, ThrottlingSeverity> status =
513         std::make_pair(ThrottlingSeverity::NONE, ThrottlingSeverity::NONE);
514     // Only update status if the thermal sensor is being monitored
515     if (sensor_info.is_monitor) {
516         ThrottlingSeverity prev_hot_severity, prev_cold_severity;
517         {
518             // reader lock, readTemperature will be called in Binder call and the watcher thread.
519             std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
520             prev_hot_severity = sensor_status_map_.at(sensor_name.data()).prev_hot_severity;
521             prev_cold_severity = sensor_status_map_.at(sensor_name.data()).prev_cold_severity;
522         }
523         status = getSeverityFromThresholds(sensor_info.hot_thresholds, sensor_info.cold_thresholds,
524                                            sensor_info.hot_hysteresis, sensor_info.cold_hysteresis,
525                                            prev_hot_severity, prev_cold_severity, out->value);
526     }
527     if (throtting_status) {
528         *throtting_status = status;
529     }
530 
531     out->throttlingStatus = static_cast<size_t>(status.first) > static_cast<size_t>(status.second)
532                                 ? status.first
533                                 : status.second;
534 
535     return true;
536 }
537 
readTemperatureThreshold(std::string_view sensor_name,TemperatureThreshold * out) const538 bool ThermalHelper::readTemperatureThreshold(std::string_view sensor_name,
539                                              TemperatureThreshold *out) const {
540     // Read the file.  If the file can't be read temp will be empty string.
541     std::string temp;
542     std::string path;
543 
544     if (!sensor_info_map_.count(sensor_name.data())) {
545         LOG(ERROR) << __func__ << ": sensor not found: " << sensor_name;
546         return false;
547     }
548 
549     const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
550 
551     out->type = sensor_info.type;
552     out->name = sensor_name.data();
553     out->hotThrottlingThresholds = sensor_info.hot_thresholds;
554     out->coldThrottlingThresholds = sensor_info.cold_thresholds;
555     out->vrThrottlingThreshold = sensor_info.vr_threshold;
556     return true;
557 }
558 
559 // To find the next PID target state according to the current thermal severity
getTargetStateOfPID(const SensorInfo & sensor_info,const SensorStatus & sensor_status)560 size_t ThermalHelper::getTargetStateOfPID(const SensorInfo &sensor_info,
561                                           const SensorStatus &sensor_status) {
562     size_t target_state = 0;
563 
564     for (const auto &severity : hidl_enum_range<ThrottlingSeverity>()) {
565         size_t state = static_cast<size_t>(severity);
566         if (std::isnan(sensor_info.throttling_info->s_power[state])) {
567             continue;
568         }
569         target_state = state;
570         if (severity > sensor_status.severity) {
571             break;
572         }
573     }
574     return target_state;
575 }
576 
577 // Return the power budget which is computed by PID algorithm
pidPowerCalculator(const Temperature_2_0 & temp,const SensorInfo & sensor_info,SensorStatus * sensor_status,std::chrono::milliseconds time_elapsed_ms,size_t target_state)578 float ThermalHelper::pidPowerCalculator(const Temperature_2_0 &temp, const SensorInfo &sensor_info,
579                                         SensorStatus *sensor_status,
580                                         std::chrono::milliseconds time_elapsed_ms,
581                                         size_t target_state) {
582     float p = 0, i = 0, d = 0;
583     float power_budget = std::numeric_limits<float>::max();
584 
585     LOG(VERBOSE) << "PID target state=" << target_state;
586     if (!target_state || (sensor_status->severity == ThrottlingSeverity::NONE)) {
587         sensor_status->err_integral = 0;
588         sensor_status->prev_err = NAN;
589         return power_budget;
590     }
591 
592     // Compute PID
593     float err = sensor_info.hot_thresholds[target_state] - temp.value;
594     p = err * (err < 0 ? sensor_info.throttling_info->k_po[target_state]
595                        : sensor_info.throttling_info->k_pu[target_state]);
596     i = sensor_status->err_integral * sensor_info.throttling_info->k_i[target_state];
597     if (err < sensor_info.throttling_info->i_cutoff[target_state]) {
598         float i_next = i + err * sensor_info.throttling_info->k_i[target_state];
599         if (abs(i_next) < sensor_info.throttling_info->i_max[target_state]) {
600             i = i_next;
601             sensor_status->err_integral += err;
602         }
603     }
604 
605     if (!std::isnan(sensor_status->prev_err) &&
606         time_elapsed_ms != std::chrono::milliseconds::zero()) {
607         d = sensor_info.throttling_info->k_d[target_state] * (err - sensor_status->prev_err) /
608             time_elapsed_ms.count();
609     }
610 
611     sensor_status->prev_err = err;
612     // Calculate power budget
613     power_budget = sensor_info.throttling_info->s_power[target_state] + p + i + d;
614     if (power_budget < sensor_info.throttling_info->min_alloc_power[target_state]) {
615         power_budget = sensor_info.throttling_info->min_alloc_power[target_state];
616     }
617     if (power_budget > sensor_info.throttling_info->max_alloc_power[target_state]) {
618         power_budget = sensor_info.throttling_info->max_alloc_power[target_state];
619     }
620 
621     LOG(VERBOSE) << "power_budget=" << power_budget << " err=" << err
622                  << " err_integral=" << sensor_status->err_integral
623                  << " s_power=" << sensor_info.throttling_info->s_power[target_state]
624                  << " time_elpased_ms=" << time_elapsed_ms.count() << " p=" << p << " i=" << i
625                  << " d=" << d;
626 
627     return power_budget;
628 }
629 
requestCdevByPower(std::string_view sensor_name,SensorStatus * sensor_status,const SensorInfo & sensor_info,float total_power_budget,size_t target_state)630 bool ThermalHelper::requestCdevByPower(std::string_view sensor_name, SensorStatus *sensor_status,
631                                        const SensorInfo &sensor_info, float total_power_budget,
632                                        size_t target_state) {
633     float total_weight = 0, cdev_power_budget;
634     size_t j;
635 
636     for (const auto &binded_cdev_info_pair : sensor_info.throttling_info->binded_cdev_info_map) {
637         if (!std::isnan(binded_cdev_info_pair.second.cdev_weight_for_pid[target_state])) {
638             total_weight += binded_cdev_info_pair.second.cdev_weight_for_pid[target_state];
639         }
640     }
641 
642     if (!total_weight) {
643         LOG(ERROR) << "Sensor: " << sensor_name.data() << " total weight value is zero";
644         return false;
645     }
646 
647     // Map cdev state by power
648     for (const auto &binded_cdev_info_pair : sensor_info.throttling_info->binded_cdev_info_map) {
649         const auto cdev_weight = binded_cdev_info_pair.second.cdev_weight_for_pid[target_state];
650         if (!std::isnan(cdev_weight)) {
651             cdev_power_budget = total_power_budget * (cdev_weight / total_weight);
652 
653             const CdevInfo &cdev_info_pair =
654                     cooling_device_info_map_.at(binded_cdev_info_pair.first);
655             for (j = 0; j < cdev_info_pair.state2power.size() - 1; ++j) {
656                 if (cdev_power_budget > cdev_info_pair.state2power[j]) {
657                     break;
658                 }
659             }
660             sensor_status->pid_request_map.at(binded_cdev_info_pair.first) = static_cast<int>(j);
661             LOG(VERBOSE) << "Power allocator: Sensor " << sensor_name.data() << " allocate "
662                          << cdev_power_budget << "mW to " << binded_cdev_info_pair.first
663                          << "(cdev_weight=" << cdev_weight << ") update state to " << j;
664         }
665     }
666     return true;
667 }
668 
requestCdevBySeverity(std::string_view sensor_name,SensorStatus * sensor_status,const SensorInfo & sensor_info)669 void ThermalHelper::requestCdevBySeverity(std::string_view sensor_name, SensorStatus *sensor_status,
670                                           const SensorInfo &sensor_info) {
671     for (auto const &binded_cdev_info_pair : sensor_info.throttling_info->binded_cdev_info_map) {
672         sensor_status->hard_limit_request_map.at(binded_cdev_info_pair.first) =
673                 binded_cdev_info_pair.second
674                         .limit_info[static_cast<size_t>(sensor_status->severity)];
675         LOG(VERBOSE) << "Hard Limit: Sensor " << sensor_name.data() << " update cdev "
676                      << binded_cdev_info_pair.first << " to "
677                      << sensor_status->hard_limit_request_map.at(binded_cdev_info_pair.first);
678     }
679 }
680 
computeCoolingDevicesRequest(std::string_view sensor_name,const SensorInfo & sensor_info,const SensorStatus & sensor_status,std::vector<std::string> * cooling_devices_to_update)681 void ThermalHelper::computeCoolingDevicesRequest(
682         std::string_view sensor_name, const SensorInfo &sensor_info,
683         const SensorStatus &sensor_status, std::vector<std::string> *cooling_devices_to_update) {
684     int release_step = 0;
685 
686     std::unique_lock<std::shared_mutex> _lock(cdev_status_map_mutex_);
687     for (auto &cdev_request_pair : cdev_status_map_) {
688         if (!cdev_request_pair.second.count(sensor_name.data())) {
689             continue;
690         }
691         int pid_request = 0;
692         int hard_limit_request = 0;
693         const auto &binded_cdev_info =
694                 sensor_info.throttling_info->binded_cdev_info_map.at(cdev_request_pair.first);
695         const auto cdev_ceiling =
696                 binded_cdev_info.cdev_ceiling[static_cast<size_t>(sensor_status.severity)];
697         const auto cdev_floor =
698                 binded_cdev_info
699                         .cdev_floor_with_power_link[static_cast<size_t>(sensor_status.severity)];
700         release_step = 0;
701 
702         if (sensor_status.pid_request_map.count(cdev_request_pair.first)) {
703             pid_request = sensor_status.pid_request_map.at(cdev_request_pair.first);
704         }
705 
706         if (sensor_status.hard_limit_request_map.count(cdev_request_pair.first)) {
707             hard_limit_request = sensor_status.hard_limit_request_map.at(cdev_request_pair.first);
708         }
709 
710         release_step = power_files_.getReleaseStep(sensor_name, cdev_request_pair.first);
711         LOG(VERBOSE) << "Sensor: " << sensor_name.data() << " binded cooling device "
712                      << cdev_request_pair.first << "'s pid_request=" << pid_request
713                      << " hard_limit_request=" << hard_limit_request
714                      << " release_step=" << release_step
715                      << " cdev_floor_with_power_link=" << cdev_floor
716                      << " cdev_ceiling=" << cdev_ceiling;
717 
718         auto request_state = std::max(pid_request, hard_limit_request);
719         if (release_step) {
720             if (release_step >= request_state) {
721                 request_state = 0;
722             } else {
723                 request_state = request_state - release_step;
724             }
725             // Only check the cdev_floor when release step is non zero
726             if (request_state < cdev_floor) {
727                 request_state = cdev_floor;
728             }
729         }
730 
731         if (request_state > cdev_ceiling) {
732             request_state = cdev_ceiling;
733         }
734         if (cdev_request_pair.second.at(sensor_name.data()) != request_state) {
735             cdev_request_pair.second.at(sensor_name.data()) = request_state;
736             cooling_devices_to_update->emplace_back(cdev_request_pair.first);
737             LOG(INFO) << "Sensor: " << sensor_name.data() << " request " << cdev_request_pair.first
738                       << " to " << request_state;
739         }
740     }
741 }
742 
updateCoolingDevices(const std::vector<std::string> & updated_cdev)743 void ThermalHelper::updateCoolingDevices(const std::vector<std::string> &updated_cdev) {
744     int max_state;
745 
746     for (const auto &target_cdev : updated_cdev) {
747         max_state = 0;
748         const CdevRequestStatus &cdev_status = cdev_status_map_.at(target_cdev);
749         for (auto &sensor_request_pair : cdev_status) {
750             if (sensor_request_pair.second > max_state) {
751                 max_state = sensor_request_pair.second;
752             }
753         }
754         if (cooling_devices_.writeCdevFile(target_cdev, std::to_string(max_state))) {
755             LOG(VERBOSE) << "Successfully update cdev " << target_cdev << " sysfs to " << max_state;
756         }
757     }
758 }
759 
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) const760 std::pair<ThrottlingSeverity, ThrottlingSeverity> ThermalHelper::getSeverityFromThresholds(
761     const ThrottlingArray &hot_thresholds, const ThrottlingArray &cold_thresholds,
762     const ThrottlingArray &hot_hysteresis, const ThrottlingArray &cold_hysteresis,
763     ThrottlingSeverity prev_hot_severity, ThrottlingSeverity prev_cold_severity,
764     float value) const {
765     ThrottlingSeverity ret_hot = ThrottlingSeverity::NONE;
766     ThrottlingSeverity ret_hot_hysteresis = ThrottlingSeverity::NONE;
767     ThrottlingSeverity ret_cold = ThrottlingSeverity::NONE;
768     ThrottlingSeverity ret_cold_hysteresis = ThrottlingSeverity::NONE;
769 
770     // Here we want to control the iteration from high to low, and hidl_enum_range doesn't support
771     // a reverse iterator yet.
772     for (size_t i = static_cast<size_t>(ThrottlingSeverity::SHUTDOWN);
773          i > static_cast<size_t>(ThrottlingSeverity::NONE); --i) {
774         if (!std::isnan(hot_thresholds[i]) && hot_thresholds[i] <= value &&
775             ret_hot == ThrottlingSeverity::NONE) {
776             ret_hot = static_cast<ThrottlingSeverity>(i);
777         }
778         if (!std::isnan(hot_thresholds[i]) && (hot_thresholds[i] - hot_hysteresis[i]) < value &&
779             ret_hot_hysteresis == ThrottlingSeverity::NONE) {
780             ret_hot_hysteresis = static_cast<ThrottlingSeverity>(i);
781         }
782         if (!std::isnan(cold_thresholds[i]) && cold_thresholds[i] >= value &&
783             ret_cold == ThrottlingSeverity::NONE) {
784             ret_cold = static_cast<ThrottlingSeverity>(i);
785         }
786         if (!std::isnan(cold_thresholds[i]) && (cold_thresholds[i] + cold_hysteresis[i]) > value &&
787             ret_cold_hysteresis == ThrottlingSeverity::NONE) {
788             ret_cold_hysteresis = static_cast<ThrottlingSeverity>(i);
789         }
790     }
791     if (static_cast<size_t>(ret_hot) < static_cast<size_t>(prev_hot_severity)) {
792         ret_hot = ret_hot_hysteresis;
793     }
794     if (static_cast<size_t>(ret_cold) < static_cast<size_t>(prev_cold_severity)) {
795         ret_cold = ret_cold_hysteresis;
796     }
797 
798     return std::make_pair(ret_hot, ret_cold);
799 }
800 
initializeSensorMap(const std::unordered_map<std::string,std::string> & path_map)801 bool ThermalHelper::initializeSensorMap(
802         const std::unordered_map<std::string, std::string> &path_map) {
803     for (const auto &sensor_info_pair : sensor_info_map_) {
804         std::string_view sensor_name = sensor_info_pair.first;
805         if (sensor_info_pair.second.virtual_sensor_info != nullptr) {
806             continue;
807         }
808         if (!path_map.count(sensor_name.data())) {
809             LOG(ERROR) << "Could not find " << sensor_name << " in sysfs";
810             return false;
811         }
812 
813         std::string path;
814         if (sensor_info_pair.second.temp_path.empty()) {
815             path = android::base::StringPrintf("%s/%s", path_map.at(sensor_name.data()).c_str(),
816                                                kSensorTempSuffix.data());
817         } else {
818             path = sensor_info_pair.second.temp_path;
819         }
820 
821         if (!thermal_sensors_.addThermalFile(sensor_name, path)) {
822             LOG(ERROR) << "Could not add " << sensor_name << "to sensors map";
823             return false;
824         }
825     }
826     return true;
827 }
828 
initializeCoolingDevices(const std::unordered_map<std::string,std::string> & path_map)829 bool ThermalHelper::initializeCoolingDevices(
830         const std::unordered_map<std::string, std::string> &path_map) {
831     for (auto &cooling_device_info_pair : cooling_device_info_map_) {
832         std::string cooling_device_name = cooling_device_info_pair.first;
833         if (!path_map.count(cooling_device_name)) {
834             LOG(ERROR) << "Could not find " << cooling_device_name << " in sysfs";
835             continue;
836         }
837         // Add cooling device path for thermalHAL to get current state
838         std::string_view path = path_map.at(cooling_device_name);
839         std::string read_path;
840         if (!cooling_device_info_pair.second.read_path.empty()) {
841             read_path = cooling_device_info_pair.second.read_path.data();
842         } else {
843             read_path = android::base::StringPrintf("%s/%s", path.data(),
844                                                     kCoolingDeviceCurStateSuffix.data());
845         }
846         if (!cooling_devices_.addThermalFile(cooling_device_name, read_path)) {
847             LOG(ERROR) << "Could not add " << cooling_device_name
848                        << " read path to cooling device map";
849             continue;
850         }
851 
852         std::string state2power_path = android::base::StringPrintf(
853                 "%s/%s", path.data(), kCoolingDeviceState2powerSuffix.data());
854         std::string state2power_str;
855         if (android::base::ReadFileToString(state2power_path, &state2power_str)) {
856             LOG(INFO) << "Cooling device " << cooling_device_info_pair.first
857                       << " use state2power read from sysfs";
858             cooling_device_info_pair.second.state2power.clear();
859 
860             std::stringstream power(state2power_str);
861             unsigned int power_number;
862             int i = 0;
863             while (power >> power_number) {
864                 cooling_device_info_pair.second.state2power.push_back(
865                         static_cast<float>(power_number));
866                 LOG(INFO) << "Cooling device " << cooling_device_info_pair.first << " state:" << i
867                           << " power: " << power_number;
868                 i++;
869             }
870         }
871 
872         // Get max cooling device request state
873         std::string max_state;
874         std::string max_state_path = android::base::StringPrintf(
875                 "%s/%s", path.data(), kCoolingDeviceMaxStateSuffix.data());
876         if (!android::base::ReadFileToString(max_state_path, &max_state)) {
877             LOG(ERROR) << cooling_device_info_pair.first
878                        << " could not open max state file:" << max_state_path;
879             cooling_device_info_pair.second.max_state = std::numeric_limits<int>::max();
880         } else {
881             cooling_device_info_pair.second.max_state = std::stoi(android::base::Trim(max_state));
882             LOG(INFO) << "Cooling device " << cooling_device_info_pair.first
883                       << " max state: " << cooling_device_info_pair.second.max_state
884                       << " state2power number: "
885                       << cooling_device_info_pair.second.state2power.size();
886             if (cooling_device_info_pair.second.state2power.size() > 0 &&
887                 cooling_device_info_pair.second.state2power.size() !=
888                         (size_t)cooling_device_info_pair.second.max_state + 1) {
889                 LOG(ERROR) << "Invalid state2power number: "
890                            << cooling_device_info_pair.second.state2power.size()
891                            << ", number should be " << cooling_device_info_pair.second.max_state + 1
892                            << " (max_state + 1)";
893             }
894         }
895 
896         // Add cooling device path for thermalHAL to request state
897         cooling_device_name =
898                 android::base::StringPrintf("%s_%s", cooling_device_name.c_str(), "w");
899         std::string write_path;
900         if (!cooling_device_info_pair.second.write_path.empty()) {
901             write_path = cooling_device_info_pair.second.write_path.data();
902         } else {
903             write_path = android::base::StringPrintf("%s/%s", path.data(),
904                                                      kCoolingDeviceCurStateSuffix.data());
905         }
906 
907         if (!cooling_devices_.addThermalFile(cooling_device_name, write_path)) {
908             LOG(ERROR) << "Could not add " << cooling_device_name
909                        << " write path to cooling device map";
910             continue;
911         }
912     }
913 
914     if (cooling_device_info_map_.size() * 2 != cooling_devices_.getNumThermalFiles()) {
915         LOG(ERROR) << "Some cooling device can not be initialized";
916     }
917     return true;
918 }
919 
setMinTimeout(SensorInfo * sensor_info)920 void ThermalHelper::setMinTimeout(SensorInfo *sensor_info) {
921     sensor_info->polling_delay = kMinPollIntervalMs;
922     sensor_info->passive_delay = kMinPollIntervalMs;
923 }
924 
initializeTrip(const std::unordered_map<std::string,std::string> & path_map,std::set<std::string> * monitored_sensors,bool thermal_genl_enabled)925 void ThermalHelper::initializeTrip(const std::unordered_map<std::string, std::string> &path_map,
926                                    std::set<std::string> *monitored_sensors,
927                                    bool thermal_genl_enabled) {
928     for (auto &sensor_info : sensor_info_map_) {
929         if (!sensor_info.second.is_monitor || (sensor_info.second.virtual_sensor_info != nullptr)) {
930             continue;
931         }
932 
933         bool trip_update = false;
934         std::string_view sensor_name = sensor_info.first;
935         std::string_view tz_path = path_map.at(sensor_name.data());
936         std::string tz_policy;
937         std::string path =
938                 android::base::StringPrintf("%s/%s", (tz_path.data()), kSensorPolicyFile.data());
939 
940         if (thermal_genl_enabled) {
941             trip_update = true;
942         } else {
943             // Check if thermal zone support uevent notify
944             if (!android::base::ReadFileToString(path, &tz_policy)) {
945                 LOG(ERROR) << sensor_name << " could not open tz policy file:" << path;
946             } else {
947                 tz_policy = android::base::Trim(tz_policy);
948                 if (tz_policy != kUserSpaceSuffix) {
949                     LOG(ERROR) << sensor_name << " does not support uevent notify";
950                 } else {
951                     trip_update = true;
952                 }
953             }
954         }
955         if (trip_update) {
956             // Update thermal zone trip point
957             for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
958                 if (!std::isnan(sensor_info.second.hot_thresholds[i]) &&
959                     !std::isnan(sensor_info.second.hot_hysteresis[i])) {
960                     // Update trip_point_0_temp threshold
961                     std::string threshold = std::to_string(static_cast<int>(
962                             sensor_info.second.hot_thresholds[i] / sensor_info.second.multiplier));
963                     path = android::base::StringPrintf("%s/%s", (tz_path.data()),
964                                                        kSensorTripPointTempZeroFile.data());
965                     if (!android::base::WriteStringToFile(threshold, path)) {
966                         LOG(ERROR) << "fail to update " << sensor_name << " trip point: " << path
967                                    << " to " << threshold;
968                         trip_update = false;
969                         break;
970                     }
971                     // Update trip_point_0_hyst threshold
972                     threshold = std::to_string(static_cast<int>(
973                             sensor_info.second.hot_hysteresis[i] / sensor_info.second.multiplier));
974                     path = android::base::StringPrintf("%s/%s", (tz_path.data()),
975                                                        kSensorTripPointHystZeroFile.data());
976                     if (!android::base::WriteStringToFile(threshold, path)) {
977                         LOG(ERROR) << "fail to update " << sensor_name << "trip hyst" << threshold
978                                    << path;
979                         trip_update = false;
980                         break;
981                     }
982                     break;
983                 } else if (i == kThrottlingSeverityCount - 1) {
984                     LOG(ERROR) << sensor_name << ":all thresholds are NAN";
985                     trip_update = false;
986                     break;
987                 }
988             }
989             monitored_sensors->insert(sensor_info.first);
990         }
991 
992         if (!trip_update) {
993             LOG(INFO) << "config Sensor: " << sensor_info.first
994                       << " to default polling interval: " << kMinPollIntervalMs.count();
995             setMinTimeout(&sensor_info.second);
996         }
997     }
998 }
999 
fillTemperatures(hidl_vec<Temperature_1_0> * temperatures) const1000 bool ThermalHelper::fillTemperatures(hidl_vec<Temperature_1_0> *temperatures) const {
1001     temperatures->resize(sensor_info_map_.size());
1002     int current_index = 0;
1003     for (const auto &name_info_pair : sensor_info_map_) {
1004         Temperature_1_0 temp;
1005 
1006         if (readTemperature(name_info_pair.first, &temp,
1007                             name_info_pair.second.virtual_sensor_info != nullptr)) {
1008             (*temperatures)[current_index] = temp;
1009         } else {
1010             LOG(ERROR) << __func__
1011                        << ": error reading temperature for sensor: " << name_info_pair.first;
1012             return false;
1013         }
1014         ++current_index;
1015     }
1016     return current_index > 0;
1017 }
1018 
fillCurrentTemperatures(bool filterType,bool filterCallback,TemperatureType_2_0 type,hidl_vec<Temperature_2_0> * temperatures) const1019 bool ThermalHelper::fillCurrentTemperatures(bool filterType, bool filterCallback,
1020                                             TemperatureType_2_0 type,
1021                                             hidl_vec<Temperature_2_0> *temperatures) const {
1022     std::vector<Temperature_2_0> ret;
1023     for (const auto &name_info_pair : sensor_info_map_) {
1024         Temperature_2_0 temp;
1025         if (filterType && name_info_pair.second.type != type) {
1026             continue;
1027         }
1028         if (filterCallback && !name_info_pair.second.send_cb) {
1029             continue;
1030         }
1031         if (readTemperature(name_info_pair.first, &temp, nullptr,
1032                             name_info_pair.second.virtual_sensor_info != nullptr)) {
1033             ret.emplace_back(std::move(temp));
1034         } else {
1035             LOG(ERROR) << __func__
1036                        << ": error reading temperature for sensor: " << name_info_pair.first;
1037         }
1038     }
1039     *temperatures = ret;
1040     return ret.size() > 0;
1041 }
1042 
fillTemperatureThresholds(bool filterType,TemperatureType_2_0 type,hidl_vec<TemperatureThreshold> * thresholds) const1043 bool ThermalHelper::fillTemperatureThresholds(bool filterType, TemperatureType_2_0 type,
1044                                               hidl_vec<TemperatureThreshold> *thresholds) const {
1045     std::vector<TemperatureThreshold> ret;
1046     for (const auto &name_info_pair : sensor_info_map_) {
1047         TemperatureThreshold temp;
1048         if (filterType && name_info_pair.second.type != type) {
1049             continue;
1050         }
1051         if (readTemperatureThreshold(name_info_pair.first, &temp)) {
1052             ret.emplace_back(std::move(temp));
1053         } else {
1054             LOG(ERROR) << __func__ << ": error reading temperature threshold for sensor: "
1055                        << name_info_pair.first;
1056             return false;
1057         }
1058     }
1059     *thresholds = ret;
1060     return ret.size() > 0;
1061 }
1062 
fillCurrentCoolingDevices(bool filterType,CoolingType type,hidl_vec<CoolingDevice_2_0> * cooling_devices) const1063 bool ThermalHelper::fillCurrentCoolingDevices(bool filterType, CoolingType type,
1064                                               hidl_vec<CoolingDevice_2_0> *cooling_devices) const {
1065     std::vector<CoolingDevice_2_0> ret;
1066     for (const auto &name_info_pair : cooling_device_info_map_) {
1067         CoolingDevice_2_0 value;
1068         if (filterType && name_info_pair.second.type != type) {
1069             continue;
1070         }
1071         if (readCoolingDevice(name_info_pair.first, &value)) {
1072             ret.emplace_back(std::move(value));
1073         } else {
1074             LOG(ERROR) << __func__ << ": error reading cooling device: " << name_info_pair.first;
1075             return false;
1076         }
1077     }
1078     *cooling_devices = ret;
1079     return ret.size() > 0;
1080 }
1081 
fillCpuUsages(hidl_vec<CpuUsage> * cpu_usages) const1082 bool ThermalHelper::fillCpuUsages(hidl_vec<CpuUsage> *cpu_usages) const {
1083     cpu_usages->resize(kMaxCpus);
1084     for (int i = 0; i < kMaxCpus; i++) {
1085         (*cpu_usages)[i].name = StringPrintf("cpu%d", i);
1086         (*cpu_usages)[i].active = 0;
1087         (*cpu_usages)[i].total = 0;
1088         (*cpu_usages)[i].isOnline = false;
1089     }
1090     parseCpuUsagesFileAndAssignUsages(cpu_usages);
1091     return true;
1092 }
1093 
checkVirtualSensor(std::string_view sensor_name,std::string * temp) const1094 bool ThermalHelper::checkVirtualSensor(std::string_view sensor_name, std::string *temp) const {
1095     float temp_val = 0.0;
1096 
1097     const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
1098     float offset = sensor_info.virtual_sensor_info->offset;
1099     for (size_t i = 0; i < sensor_info.virtual_sensor_info->linked_sensors.size(); i++) {
1100         std::string data;
1101         const auto &linked_sensor_info =
1102                 sensor_info_map_.at(sensor_info.virtual_sensor_info->linked_sensors[i].data());
1103         if (linked_sensor_info.virtual_sensor_info == nullptr) {
1104             if (!thermal_sensors_.readThermalFile(
1105                         sensor_info.virtual_sensor_info->linked_sensors[i], &data)) {
1106                 continue;
1107             }
1108         } else if (!checkVirtualSensor(sensor_info.virtual_sensor_info->linked_sensors[i], &data)) {
1109             return false;
1110         }
1111 
1112         LOG(VERBOSE) << sensor_name.data() << "'s linked sensor "
1113                      << sensor_info.virtual_sensor_info->linked_sensors[i] << ": temp = " << data;
1114         data = ::android::base::Trim(data);
1115         float sensor_reading = std::stof(data);
1116         if (std::isnan(sensor_info.virtual_sensor_info->coefficients[i])) {
1117             return false;
1118         }
1119         float coefficient = sensor_info.virtual_sensor_info->coefficients[i];
1120         switch (sensor_info.virtual_sensor_info->formula) {
1121             case FormulaOption::COUNT_THRESHOLD:
1122                 if ((coefficient < 0 && sensor_reading < -coefficient) ||
1123                     (coefficient >= 0 && sensor_reading >= coefficient))
1124                     temp_val += 1;
1125                 break;
1126             case FormulaOption::WEIGHTED_AVG:
1127                 temp_val += sensor_reading * coefficient;
1128                 break;
1129             case FormulaOption::MAXIMUM:
1130                 if (i == 0)
1131                     temp_val = std::numeric_limits<float>::lowest();
1132                 if (sensor_reading * coefficient > temp_val)
1133                     temp_val = sensor_reading * coefficient;
1134                 break;
1135             case FormulaOption::MINIMUM:
1136                 if (i == 0)
1137                     temp_val = std::numeric_limits<float>::max();
1138                 if (sensor_reading * coefficient < temp_val)
1139                     temp_val = sensor_reading * coefficient;
1140                 break;
1141             default:
1142                 break;
1143         }
1144     }
1145     *temp = std::to_string(temp_val + offset);
1146     return true;
1147 }
1148 
1149 // This is called in the different thread context and will update sensor_status
1150 // uevent_sensors is the set of sensors which trigger uevent from thermal core driver.
thermalWatcherCallbackFunc(const std::set<std::string> & uevent_sensors)1151 std::chrono::milliseconds ThermalHelper::thermalWatcherCallbackFunc(
1152         const std::set<std::string> &uevent_sensors) {
1153     std::vector<Temperature_2_0> temps;
1154     std::vector<std::string> cooling_devices_to_update;
1155     std::set<std::string> updated_power_rails;
1156     boot_clock::time_point now = boot_clock::now();
1157     auto min_sleep_ms = std::chrono::milliseconds::max();
1158 
1159     for (auto &name_status_pair : sensor_status_map_) {
1160         bool force_update = false;
1161         bool severity_changed = false;
1162         Temperature_2_0 temp;
1163         TemperatureThreshold threshold;
1164         SensorStatus &sensor_status = name_status_pair.second;
1165         const SensorInfo &sensor_info = sensor_info_map_.at(name_status_pair.first);
1166 
1167         // Only handle the sensors in allow list
1168         if (!sensor_info.is_monitor) {
1169             continue;
1170         }
1171 
1172         std::chrono::milliseconds time_elapsed_ms = std::chrono::milliseconds::zero();
1173         auto sleep_ms = (sensor_status.severity != ThrottlingSeverity::NONE)
1174                                 ? sensor_info.passive_delay
1175                                 : sensor_info.polling_delay;
1176         // Check if the sensor need to be updated
1177         if (sensor_status.last_update_time == boot_clock::time_point::min()) {
1178             force_update = true;
1179             LOG(VERBOSE) << "Force update " << name_status_pair.first
1180                          << "'s temperature after booting";
1181         } else {
1182             time_elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
1183                     now - sensor_status.last_update_time);
1184 
1185             if (time_elapsed_ms > sleep_ms) {
1186                 // Update the sensor because sleep timeout
1187                 force_update = true;
1188             } else if (uevent_sensors.size() &&
1189                        uevent_sensors.find((sensor_info.virtual_sensor_info != nullptr)
1190                                                    ? sensor_info.virtual_sensor_info->trigger_sensor
1191                                                    : name_status_pair.first) !=
1192                                uevent_sensors.end()) {
1193                 // Update the sensor from uevent
1194                 force_update = true;
1195             } else if (sensor_info.virtual_sensor_info != nullptr) {
1196                 // Update the virtual sensor if it's trigger sensor over the threshold
1197                 const auto trigger_sensor_status =
1198                         sensor_status_map_.at(sensor_info.virtual_sensor_info->trigger_sensor);
1199                 if (trigger_sensor_status.severity != ThrottlingSeverity::NONE) {
1200                     force_update = true;
1201                 }
1202             }
1203         }
1204 
1205         LOG(VERBOSE) << "sensor " << name_status_pair.first
1206                      << ": time_elpased=" << time_elapsed_ms.count()
1207                      << ", sleep_ms=" << sleep_ms.count() << ", force_update = " << force_update;
1208 
1209         if (!force_update) {
1210             auto timeout_remaining = sleep_ms - time_elapsed_ms;
1211             if (min_sleep_ms > timeout_remaining) {
1212                 min_sleep_ms = timeout_remaining;
1213             }
1214             LOG(VERBOSE) << "sensor " << name_status_pair.first
1215                          << ": timeout_remaining=" << timeout_remaining.count();
1216             continue;
1217         }
1218 
1219         std::pair<ThrottlingSeverity, ThrottlingSeverity> throtting_status;
1220         if (!readTemperature(name_status_pair.first, &temp, &throtting_status,
1221                              (sensor_info.virtual_sensor_info != nullptr))) {
1222             LOG(ERROR) << __func__
1223                        << ": error reading temperature for sensor: " << name_status_pair.first;
1224             continue;
1225         }
1226         if (!readTemperatureThreshold(name_status_pair.first, &threshold)) {
1227             LOG(ERROR) << __func__ << ": error reading temperature threshold for sensor: "
1228                        << name_status_pair.first;
1229             continue;
1230         }
1231 
1232         {
1233             // writer lock
1234             std::unique_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
1235             if (throtting_status.first != sensor_status.prev_hot_severity) {
1236                 sensor_status.prev_hot_severity = throtting_status.first;
1237             }
1238             if (throtting_status.second != sensor_status.prev_cold_severity) {
1239                 sensor_status.prev_cold_severity = throtting_status.second;
1240             }
1241             if (temp.throttlingStatus != sensor_status.severity) {
1242                 temps.push_back(temp);
1243                 severity_changed = true;
1244                 sensor_status.severity = temp.throttlingStatus;
1245                 sleep_ms = (sensor_status.severity != ThrottlingSeverity::NONE)
1246                                    ? sensor_info.passive_delay
1247                                    : sensor_info.polling_delay;
1248             }
1249         }
1250 
1251         if (sensor_status.severity != ThrottlingSeverity::NONE) {
1252             LOG(INFO) << temp.name << ": " << temp.value << " degC";
1253         } else {
1254             LOG(VERBOSE) << temp.name << ": " << temp.value << " degC";
1255         }
1256 
1257         // Start PID computation
1258         if (sensor_status.pid_request_map.size()) {
1259             size_t target_state = getTargetStateOfPID(sensor_info, sensor_status);
1260             float power_budget = pidPowerCalculator(temp, sensor_info, &sensor_status,
1261                                                     time_elapsed_ms, target_state);
1262             if (!requestCdevByPower(name_status_pair.first, &sensor_status, sensor_info,
1263                                     power_budget, target_state)) {
1264                 LOG(ERROR) << "Sensor " << temp.name << " PID request cdev failed";
1265             }
1266         }
1267 
1268         if (sensor_status.hard_limit_request_map.size()) {
1269             // Start hard limit computation
1270             requestCdevBySeverity(name_status_pair.first, &sensor_status, sensor_info);
1271         }
1272 
1273         // Aggregate cooling device request
1274         if (sensor_status.pid_request_map.size() || sensor_status.hard_limit_request_map.size()) {
1275             if (sensor_status.severity == ThrottlingSeverity::NONE) {
1276                 power_files_.setPowerDataToDefault(name_status_pair.first);
1277             } else {
1278                 for (const auto &binded_cdev_info_pair :
1279                      sensor_info.throttling_info->binded_cdev_info_map) {
1280                     if (binded_cdev_info_pair.second.power_rail != "") {
1281                         const auto &power_rail_info =
1282                                 power_rail_info_map_.at(binded_cdev_info_pair.second.power_rail);
1283 
1284                         if (power_files_.throttlingReleaseUpdate(
1285                                     name_status_pair.first, binded_cdev_info_pair.first,
1286                                     sensor_status.severity, time_elapsed_ms,
1287                                     binded_cdev_info_pair.second, power_rail_info,
1288                                     !updated_power_rails.count(
1289                                             binded_cdev_info_pair.second.power_rail),
1290                                     severity_changed)) {
1291                             updated_power_rails.insert(binded_cdev_info_pair.second.power_rail);
1292                         }
1293                     }
1294                 }
1295             }
1296             computeCoolingDevicesRequest(name_status_pair.first, sensor_info, sensor_status,
1297                                          &cooling_devices_to_update);
1298         }
1299 
1300         if (min_sleep_ms > sleep_ms) {
1301             min_sleep_ms = sleep_ms;
1302         }
1303         LOG(VERBOSE) << "Sensor " << name_status_pair.first << ": sleep_ms=" << sleep_ms.count()
1304                      << ", min_sleep_ms voting result=" << min_sleep_ms.count();
1305         sensor_status.last_update_time = now;
1306     }
1307 
1308     if (!cooling_devices_to_update.empty()) {
1309         updateCoolingDevices(cooling_devices_to_update);
1310     }
1311 
1312     if (!temps.empty()) {
1313         for (const auto &t : temps) {
1314             if (sensor_info_map_.at(t.name).send_cb && cb_) {
1315                 cb_(t);
1316             }
1317 
1318             if (sensor_info_map_.at(t.name).send_powerhint && isAidlPowerHalExist()) {
1319                 sendPowerExtHint(t);
1320             }
1321         }
1322     }
1323 
1324     power_files_.clearEnergyInfoMap();
1325     return min_sleep_ms < kMinPollIntervalMs ? kMinPollIntervalMs : min_sleep_ms;
1326 }
1327 
connectToPowerHal()1328 bool ThermalHelper::connectToPowerHal() {
1329     return power_hal_service_.connect();
1330 }
1331 
updateSupportedPowerHints()1332 void ThermalHelper::updateSupportedPowerHints() {
1333     for (auto const &name_status_pair : sensor_info_map_) {
1334         if (!(name_status_pair.second.send_powerhint)) {
1335             continue;
1336         }
1337         ThrottlingSeverity current_severity = ThrottlingSeverity::NONE;
1338         for (const auto &severity : hidl_enum_range<ThrottlingSeverity>()) {
1339             if (severity == ThrottlingSeverity::NONE) {
1340                 supported_powerhint_map_[name_status_pair.first][ThrottlingSeverity::NONE] =
1341                         ThrottlingSeverity::NONE;
1342                 continue;
1343             }
1344 
1345             bool isSupported = false;
1346             ndk::ScopedAStatus isSupportedResult;
1347 
1348             if (power_hal_service_.isPowerHalExtConnected()) {
1349                 isSupported = power_hal_service_.isModeSupported(name_status_pair.first, severity);
1350             }
1351             if (isSupported)
1352                 current_severity = severity;
1353             supported_powerhint_map_[name_status_pair.first][severity] = current_severity;
1354         }
1355     }
1356 }
1357 
sendPowerExtHint(const Temperature_2_0 & t)1358 void ThermalHelper::sendPowerExtHint(const Temperature_2_0 &t) {
1359     std::lock_guard<std::shared_mutex> lock(sensor_status_map_mutex_);
1360 
1361     ThrottlingSeverity prev_hint_severity;
1362     prev_hint_severity = sensor_status_map_.at(t.name).prev_hint_severity;
1363     ThrottlingSeverity current_hint_severity = supported_powerhint_map_[t.name][t.throttlingStatus];
1364 
1365     if (prev_hint_severity == current_hint_severity)
1366         return;
1367 
1368     if (prev_hint_severity != ThrottlingSeverity::NONE) {
1369         power_hal_service_.setMode(t.name, prev_hint_severity, false);
1370     }
1371 
1372     if (current_hint_severity != ThrottlingSeverity::NONE) {
1373         power_hal_service_.setMode(t.name, current_hint_severity, true);
1374     }
1375 
1376     sensor_status_map_[t.name].prev_hint_severity = current_hint_severity;
1377 }
1378 }  // namespace implementation
1379 }  // namespace V2_0
1380 }  // namespace thermal
1381 }  // namespace hardware
1382 }  // namespace android
1383