Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 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 | */ |
TeYuan Wang | d0979f8 | 2022-02-11 19:17:51 +0800 | [diff] [blame] | 16 | #define ATRACE_TAG (ATRACE_TAG_THERMAL | ATRACE_TAG_HAL) |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 17 | |
TeYuan Wang | d0979f8 | 2022-02-11 19:17:51 +0800 | [diff] [blame] | 18 | #include "thermal-helper.h" |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 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> |
TeYuan Wang | d0979f8 | 2022-02-11 19:17:51 +0800 | [diff] [blame] | 25 | #include <utils/Trace.h> |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 26 | |
TeYuan Wang | d0979f8 | 2022-02-11 19:17:51 +0800 | [diff] [blame] | 27 | #include <iterator> |
| 28 | #include <set> |
| 29 | #include <sstream> |
| 30 | #include <thread> |
| 31 | #include <vector> |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 32 | |
| 33 | namespace android { |
| 34 | namespace hardware { |
| 35 | namespace thermal { |
| 36 | namespace V2_0 { |
| 37 | namespace implementation { |
| 38 | |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 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"); |
TeYuan Wang | c618626 | 2021-04-27 15:11:44 +0800 | [diff] [blame] | 53 | constexpr std::string_view kCoolingDeviceMaxStateSuffix("max_state"); |
David Chao | d774cbb | 2021-06-09 11:08:18 +0800 | [diff] [blame] | 54 | constexpr std::string_view kCoolingDeviceState2powerSuffix("state2power_table"); |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 55 | constexpr std::string_view kConfigProperty("vendor.thermal.config"); |
| 56 | constexpr std::string_view kConfigDefaultFileName("thermal_info_config.json"); |
davidchao | ca114b7 | 2020-11-12 14:02:23 +0800 | [diff] [blame] | 57 | constexpr std::string_view kThermalGenlProperty("persist.vendor.enable.thermal.genl"); |
TeYuan Wang | 2f5576d | 2021-03-03 15:03:53 +0800 | [diff] [blame] | 58 | constexpr std::string_view kThermalDisabledProperty("vendor.disable.thermal.control"); |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 59 | |
| 60 | namespace { |
| 61 | using android::base::StringPrintf; |
| 62 | |
Wei Wang | be44475 | 2019-02-01 15:12:28 -0800 | [diff] [blame] | 63 | /* |
| 64 | * Pixel don't offline CPU, so std::thread::hardware_concurrency(); should work. |
| 65 | * However /sys/devices/system/cpu/present is preferred. |
| 66 | * The file is expected to contain single text line with two numbers %d-%d, |
| 67 | * which is a range of available cpu numbers, e.g. 0-7 would mean there |
| 68 | * are 8 cores number from 0 to 7. |
| 69 | * For Android systems this approach is safer than using cpufeatures, see bug |
| 70 | * b/36941727. |
| 71 | */ |
Wei Wang | a1c7507 | 2020-07-28 14:22:39 -0700 | [diff] [blame] | 72 | static int getNumberOfCores() { |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 73 | std::string file; |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 74 | if (!android::base::ReadFileToString(kCpuPresentFile.data(), &file)) { |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 75 | LOG(ERROR) << "Error reading CPU present file: " << kCpuPresentFile; |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 76 | return 0; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 77 | } |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 78 | std::vector<std::string> pieces = android::base::Split(file, "-"); |
| 79 | if (pieces.size() != 2) { |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 80 | LOG(ERROR) << "Error parsing CPU present file content: " << file; |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 81 | return 0; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 82 | } |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 83 | auto min_core = std::stoul(pieces[0]); |
| 84 | auto max_core = std::stoul(pieces[1]); |
| 85 | if (max_core < min_core) { |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 86 | LOG(ERROR) << "Error parsing CPU present min and max: " << min_core << " - " << max_core; |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 87 | return 0; |
| 88 | } |
| 89 | return static_cast<std::size_t>(max_core - min_core + 1); |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 90 | } |
Wei Wang | a1c7507 | 2020-07-28 14:22:39 -0700 | [diff] [blame] | 91 | const int kMaxCpus = getNumberOfCores(); |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 92 | |
| 93 | void parseCpuUsagesFileAndAssignUsages(hidl_vec<CpuUsage> *cpu_usages) { |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 94 | std::string data; |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 95 | if (!android::base::ReadFileToString(kCpuUsageFile.data(), &data)) { |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 96 | LOG(ERROR) << "Error reading CPU usage file: " << kCpuUsageFile; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 97 | return; |
| 98 | } |
| 99 | |
| 100 | std::istringstream stat_data(data); |
| 101 | std::string line; |
| 102 | while (std::getline(stat_data, line)) { |
davidchao | e145bf8 | 2021-02-10 03:28:21 +0800 | [diff] [blame] | 103 | if (!line.find("cpu") && isdigit(line[3])) { |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 104 | // Split the string using spaces. |
| 105 | std::vector<std::string> words = android::base::Split(line, " "); |
Wei Wang | a1c7507 | 2020-07-28 14:22:39 -0700 | [diff] [blame] | 106 | std::string cpu_name = words[0]; |
| 107 | int cpu_num = std::stoi(cpu_name.substr(3)); |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 108 | |
| 109 | if (cpu_num < kMaxCpus) { |
Wei Wang | a1c7507 | 2020-07-28 14:22:39 -0700 | [diff] [blame] | 110 | uint64_t user = std::stoull(words[1]); |
| 111 | uint64_t nice = std::stoull(words[2]); |
| 112 | uint64_t system = std::stoull(words[3]); |
| 113 | uint64_t idle = std::stoull(words[4]); |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 114 | |
| 115 | // Check if the CPU is online by reading the online file. |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 116 | std::string cpu_online_path = |
| 117 | StringPrintf("%s/%s/%s", kCpuOnlineRoot.data(), cpu_name.c_str(), |
| 118 | kCpuOnlineFileSuffix.data()); |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 119 | std::string is_online; |
| 120 | if (!android::base::ReadFileToString(cpu_online_path, &is_online)) { |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 121 | LOG(ERROR) << "Could not open CPU online file: " << cpu_online_path; |
Wei Wang | 0fb7834 | 2020-07-20 17:38:09 -0700 | [diff] [blame] | 122 | if (cpu_num != 0) { |
| 123 | return; |
| 124 | } |
| 125 | // Some architecture cannot offline cpu0, so assuming it is online |
| 126 | is_online = "1"; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 127 | } |
| 128 | is_online = android::base::Trim(is_online); |
| 129 | |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 130 | (*cpu_usages)[cpu_num].active = user + nice + system; |
| 131 | (*cpu_usages)[cpu_num].total = user + nice + system + idle; |
| 132 | (*cpu_usages)[cpu_num].isOnline = (is_online == "1") ? true : false; |
| 133 | } else { |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 134 | LOG(ERROR) << "Unexpected CPU number: " << words[0]; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 135 | return; |
| 136 | } |
| 137 | } |
| 138 | } |
| 139 | } |
| 140 | |
TeYuan Wang | 5013fe4 | 2021-03-16 19:52:06 +0800 | [diff] [blame] | 141 | std::unordered_map<std::string, std::string> parseThermalPathMap(std::string_view prefix) { |
| 142 | std::unordered_map<std::string, std::string> path_map; |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 143 | std::unique_ptr<DIR, int (*)(DIR *)> dir(opendir(kThermalSensorsRoot.data()), closedir); |
Wei Wang | be44475 | 2019-02-01 15:12:28 -0800 | [diff] [blame] | 144 | if (!dir) { |
| 145 | return path_map; |
| 146 | } |
| 147 | |
| 148 | // std::filesystem is not available for vendor yet |
| 149 | // see discussion: aosp/894015 |
| 150 | while (struct dirent *dp = readdir(dir.get())) { |
| 151 | if (dp->d_type != DT_DIR) { |
| 152 | continue; |
| 153 | } |
| 154 | |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 155 | if (!android::base::StartsWith(dp->d_name, prefix.data())) { |
Wei Wang | be44475 | 2019-02-01 15:12:28 -0800 | [diff] [blame] | 156 | continue; |
| 157 | } |
| 158 | |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 159 | std::string path = android::base::StringPrintf("%s/%s/%s", kThermalSensorsRoot.data(), |
| 160 | dp->d_name, kThermalNameFile.data()); |
Wei Wang | be44475 | 2019-02-01 15:12:28 -0800 | [diff] [blame] | 161 | std::string name; |
| 162 | if (!android::base::ReadFileToString(path, &name)) { |
| 163 | PLOG(ERROR) << "Failed to read from " << path; |
| 164 | continue; |
| 165 | } |
| 166 | |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 167 | path_map.emplace( |
| 168 | android::base::Trim(name), |
| 169 | android::base::StringPrintf("%s/%s", kThermalSensorsRoot.data(), dp->d_name)); |
Wei Wang | be44475 | 2019-02-01 15:12:28 -0800 | [diff] [blame] | 170 | } |
| 171 | |
| 172 | return path_map; |
| 173 | } |
| 174 | |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 175 | } // namespace |
| 176 | |
| 177 | /* |
| 178 | * Populate the sensor_name_to_file_map_ map by walking through the file tree, |
| 179 | * reading the type file and assigning the temp file path to the map. If we do |
| 180 | * not succeed, abort. |
| 181 | */ |
Wei Wang | 8720c72 | 2018-11-05 13:43:04 -0800 | [diff] [blame] | 182 | ThermalHelper::ThermalHelper(const NotificationCallback &cb) |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 183 | : thermal_watcher_(new ThermalWatcher( |
| 184 | std::bind(&ThermalHelper::thermalWatcherCallbackFunc, this, std::placeholders::_1))), |
TeYuan Wang | b8173c1 | 2021-07-08 17:45:58 +0800 | [diff] [blame] | 185 | cb_(cb) { |
| 186 | const std::string config_path = |
| 187 | "/vendor/etc/" + |
| 188 | android::base::GetProperty(kConfigProperty.data(), kConfigDefaultFileName.data()); |
TeYuan Wang | 2ec4c03 | 2022-03-14 17:33:15 +0800 | [diff] [blame] | 189 | bool thermal_throttling_disabled = |
| 190 | android::base::GetBoolProperty(kThermalDisabledProperty.data(), false); |
| 191 | |
| 192 | is_initialized_ = ParseCoolingDevice(config_path, &cooling_device_info_map_) && |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 193 | ParseSensorInfo(config_path, &sensor_info_map_); |
TeYuan Wang | 2ec4c03 | 2022-03-14 17:33:15 +0800 | [diff] [blame] | 194 | |
| 195 | if (thermal_throttling_disabled) { |
| 196 | return; |
| 197 | } |
| 198 | |
| 199 | if (!is_initialized_) { |
| 200 | LOG(FATAL) << "Failed to parse thermal configs"; |
| 201 | } |
| 202 | |
TeYuan Wang | c618626 | 2021-04-27 15:11:44 +0800 | [diff] [blame] | 203 | auto tz_map = parseThermalPathMap(kSensorPrefix.data()); |
| 204 | auto cdev_map = parseThermalPathMap(kCoolingDevicePrefix.data()); |
| 205 | |
| 206 | is_initialized_ = initializeSensorMap(tz_map) && initializeCoolingDevices(cdev_map); |
TeYuan Wang | 2ec4c03 | 2022-03-14 17:33:15 +0800 | [diff] [blame] | 207 | |
TeYuan Wang | c618626 | 2021-04-27 15:11:44 +0800 | [diff] [blame] | 208 | if (!is_initialized_) { |
| 209 | LOG(FATAL) << "ThermalHAL could not be initialized properly."; |
| 210 | } |
| 211 | |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 212 | if (!power_files_.registerPowerRailsToWatch(config_path)) { |
| 213 | LOG(FATAL) << "Failed to register power rails"; |
| 214 | } |
| 215 | |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 216 | for (auto const &name_status_pair : sensor_info_map_) { |
| 217 | sensor_status_map_[name_status_pair.first] = { |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 218 | .severity = ThrottlingSeverity::NONE, |
| 219 | .prev_hot_severity = ThrottlingSeverity::NONE, |
| 220 | .prev_cold_severity = ThrottlingSeverity::NONE, |
| 221 | .prev_hint_severity = ThrottlingSeverity::NONE, |
TeYuan Wang | 8daf64c | 2021-07-05 11:17:05 +0800 | [diff] [blame] | 222 | .last_update_time = boot_clock::time_point::min(), |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 223 | .thermal_cached = {NAN, boot_clock::time_point::min()}, |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 224 | }; |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 225 | |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 226 | if (name_status_pair.second.throttling_info != nullptr) { |
| 227 | if (!thermal_throttling_.registerThermalThrottling( |
| 228 | name_status_pair.first, name_status_pair.second.throttling_info, |
| 229 | cooling_device_info_map_)) { |
| 230 | LOG(FATAL) << name_status_pair.first << " failed to register thermal throttling"; |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | // Update cooling device max state |
TeYuan Wang | c09e57e | 2022-05-10 12:12:50 +0800 | [diff] [blame] | 235 | for (auto &binded_cdev_info_pair : |
TeYuan Wang | 5013fe4 | 2021-03-16 19:52:06 +0800 | [diff] [blame] | 236 | name_status_pair.second.throttling_info->binded_cdev_info_map) { |
TeYuan Wang | c09e57e | 2022-05-10 12:12:50 +0800 | [diff] [blame] | 237 | const auto &cdev_info = cooling_device_info_map_.at(binded_cdev_info_pair.first); |
TeYuan Wang | cf16c81 | 2021-07-07 00:10:03 +0800 | [diff] [blame] | 238 | |
TeYuan Wang | c09e57e | 2022-05-10 12:12:50 +0800 | [diff] [blame] | 239 | for (auto &cdev_ceiling : binded_cdev_info_pair.second.cdev_ceiling) { |
TeYuan Wang | b8173c1 | 2021-07-08 17:45:58 +0800 | [diff] [blame] | 240 | if (cdev_ceiling > cdev_info.max_state) { |
| 241 | if (cdev_ceiling != std::numeric_limits<int>::max()) { |
TeYuan Wang | c09e57e | 2022-05-10 12:12:50 +0800 | [diff] [blame] | 242 | LOG(ERROR) |
| 243 | << "Sensor " << name_status_pair.first << "'s " |
| 244 | << binded_cdev_info_pair.first << " cdev_ceiling:" << cdev_ceiling |
| 245 | << " is higher than max state:" << cdev_info.max_state; |
TeYuan Wang | b8173c1 | 2021-07-08 17:45:58 +0800 | [diff] [blame] | 246 | } |
TeYuan Wang | cf16c81 | 2021-07-07 00:10:03 +0800 | [diff] [blame] | 247 | cdev_ceiling = cdev_info.max_state; |
| 248 | } |
TeYuan Wang | 5013fe4 | 2021-03-16 19:52:06 +0800 | [diff] [blame] | 249 | } |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 250 | } |
| 251 | |
TeYuan Wang | 4bc02eb | 2021-01-05 21:56:07 +0800 | [diff] [blame] | 252 | if (name_status_pair.second.virtual_sensor_info != nullptr && |
TeYuan Wang | e80ff15 | 2022-06-28 16:33:12 +0800 | [diff] [blame] | 253 | !name_status_pair.second.virtual_sensor_info->trigger_sensors.empty() && |
TeYuan Wang | a520348 | 2022-04-01 17:50:50 +0800 | [diff] [blame] | 254 | name_status_pair.second.is_watch) { |
TeYuan Wang | e80ff15 | 2022-06-28 16:33:12 +0800 | [diff] [blame] | 255 | for (size_t i = 0; |
| 256 | i < name_status_pair.second.virtual_sensor_info->trigger_sensors.size(); i++) { |
| 257 | if (sensor_info_map_.find( |
| 258 | name_status_pair.second.virtual_sensor_info->trigger_sensors[i]) != |
| 259 | sensor_info_map_.end()) { |
| 260 | sensor_info_map_[name_status_pair.second.virtual_sensor_info |
| 261 | ->trigger_sensors[i]] |
| 262 | .is_watch = true; |
| 263 | } else { |
| 264 | LOG(FATAL) << name_status_pair.first << "'s trigger sensor: " |
| 265 | << name_status_pair.second.virtual_sensor_info->trigger_sensors[i] |
| 266 | << " is invalid"; |
| 267 | } |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 268 | } |
| 269 | } |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 270 | } |
| 271 | |
davidchao | ca114b7 | 2020-11-12 14:02:23 +0800 | [diff] [blame] | 272 | const bool thermal_genl_enabled = |
| 273 | android::base::GetBoolProperty(kThermalGenlProperty.data(), false); |
TeYuan Wang | 6326082 | 2021-02-02 16:57:19 +0800 | [diff] [blame] | 274 | |
| 275 | std::set<std::string> monitored_sensors; |
| 276 | initializeTrip(tz_map, &monitored_sensors, thermal_genl_enabled); |
| 277 | |
davidchao | ca114b7 | 2020-11-12 14:02:23 +0800 | [diff] [blame] | 278 | if (thermal_genl_enabled) { |
| 279 | thermal_watcher_->registerFilesToWatchNl(monitored_sensors); |
| 280 | } else { |
| 281 | thermal_watcher_->registerFilesToWatch(monitored_sensors); |
| 282 | } |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 283 | |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 284 | // Need start watching after status map initialized |
| 285 | is_initialized_ = thermal_watcher_->startWatchingDeviceFiles(); |
| 286 | if (!is_initialized_) { |
| 287 | LOG(FATAL) << "ThermalHAL could not start watching thread properly."; |
| 288 | } |
Kyle Lin | 7c8556b | 2020-08-07 17:02:55 +0800 | [diff] [blame] | 289 | |
| 290 | if (!connectToPowerHal()) { |
| 291 | LOG(ERROR) << "Fail to connect to Power Hal"; |
| 292 | } else { |
| 293 | updateSupportedPowerHints(); |
| 294 | } |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 295 | } |
| 296 | |
davidchao | d9a195e | 2020-10-26 19:41:29 +0800 | [diff] [blame] | 297 | bool getThermalZoneTypeById(int tz_id, std::string *type) { |
| 298 | std::string tz_type; |
| 299 | std::string path = |
| 300 | android::base::StringPrintf("%s/%s%d/%s", kThermalSensorsRoot.data(), |
| 301 | kSensorPrefix.data(), tz_id, kThermalNameFile.data()); |
| 302 | LOG(INFO) << "TZ Path: " << path; |
| 303 | if (!::android::base::ReadFileToString(path, &tz_type)) { |
| 304 | LOG(ERROR) << "Failed to read sensor: " << tz_type; |
| 305 | return false; |
| 306 | } |
| 307 | |
| 308 | // Strip the newline. |
| 309 | *type = ::android::base::Trim(tz_type); |
| 310 | LOG(INFO) << "TZ type: " << *type; |
| 311 | return true; |
| 312 | } |
| 313 | |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 314 | bool ThermalHelper::readCoolingDevice(std::string_view cooling_device, |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 315 | CoolingDevice_2_0 *out) const { |
| 316 | // Read the file. If the file can't be read temp will be empty string. |
Wei Wang | be44475 | 2019-02-01 15:12:28 -0800 | [diff] [blame] | 317 | std::string data; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 318 | |
Wei Wang | be44475 | 2019-02-01 15:12:28 -0800 | [diff] [blame] | 319 | if (!cooling_devices_.readThermalFile(cooling_device, &data)) { |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 320 | LOG(ERROR) << "readCoolingDevice: failed to read cooling_device: " << cooling_device; |
| 321 | return false; |
| 322 | } |
| 323 | |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 324 | const CdevInfo &cdev_info = cooling_device_info_map_.at(cooling_device.data()); |
| 325 | const CoolingType &type = cdev_info.type; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 326 | |
| 327 | out->type = type; |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 328 | out->name = cooling_device.data(); |
Wei Wang | be44475 | 2019-02-01 15:12:28 -0800 | [diff] [blame] | 329 | out->value = std::stoi(data); |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 330 | |
| 331 | return true; |
| 332 | } |
| 333 | |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 334 | bool ThermalHelper::readTemperature(std::string_view sensor_name, Temperature_1_0 *out) { |
| 335 | // Return fail if the thermal sensor cannot be read. |
| 336 | float temp; |
TeYuan Wang | aadb90a | 2022-09-23 17:16:36 +0800 | [diff] [blame] | 337 | std::string sensor_log; |
| 338 | if (!readThermalSensor(sensor_name, &temp, false, &sensor_log)) { |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 339 | LOG(ERROR) << "readTemperature: failed to read sensor: " << sensor_name; |
| 340 | return false; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 341 | } |
| 342 | |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 343 | const SensorInfo &sensor_info = sensor_info_map_.at(sensor_name.data()); |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 344 | TemperatureType_1_0 type = |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 345 | (static_cast<int>(sensor_info.type) > static_cast<int>(TemperatureType_1_0::SKIN)) |
| 346 | ? TemperatureType_1_0::UNKNOWN |
| 347 | : static_cast<TemperatureType_1_0>(sensor_info.type); |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 348 | out->type = type; |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 349 | out->name = sensor_name.data(); |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 350 | out->currentValue = temp * sensor_info.multiplier; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 351 | out->throttlingThreshold = |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 352 | sensor_info.hot_thresholds[static_cast<size_t>(ThrottlingSeverity::SEVERE)]; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 353 | out->shutdownThreshold = |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 354 | sensor_info.hot_thresholds[static_cast<size_t>(ThrottlingSeverity::SHUTDOWN)]; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 355 | out->vrThrottlingThreshold = sensor_info.vr_threshold; |
| 356 | |
TeYuan Wang | aadb90a | 2022-09-23 17:16:36 +0800 | [diff] [blame] | 357 | if (sensor_info.is_watch) { |
| 358 | LOG(INFO) << sensor_name.data() << ":" << out->currentValue << " raw data:[" << sensor_log |
| 359 | << "]"; |
| 360 | } |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 361 | return true; |
| 362 | } |
| 363 | |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 364 | bool ThermalHelper::readTemperature( |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 365 | std::string_view sensor_name, Temperature_2_0 *out, |
George Lee | 9af1e97 | 2020-10-05 11:59:36 -0700 | [diff] [blame] | 366 | std::pair<ThrottlingSeverity, ThrottlingSeverity> *throtting_status, |
TeYuan Wang | e80ff15 | 2022-06-28 16:33:12 +0800 | [diff] [blame] | 367 | const bool force_no_cache) { |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 368 | // Return fail if the thermal sensor cannot be read. |
| 369 | float temp; |
TeYuan Wang | aadb90a | 2022-09-23 17:16:36 +0800 | [diff] [blame] | 370 | std::string sensor_log; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 371 | |
TeYuan Wang | aadb90a | 2022-09-23 17:16:36 +0800 | [diff] [blame] | 372 | if (!readThermalSensor(sensor_name, &temp, force_no_cache, &sensor_log)) { |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 373 | LOG(ERROR) << "readTemperature: failed to read sensor: " << sensor_name; |
| 374 | return false; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 375 | } |
| 376 | |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 377 | const auto &sensor_info = sensor_info_map_.at(sensor_name.data()); |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 378 | out->type = sensor_info.type; |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 379 | out->name = sensor_name.data(); |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 380 | out->value = temp * sensor_info.multiplier; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 381 | |
Wei Wang | 12ad0a8 | 2019-02-19 16:18:25 -0800 | [diff] [blame] | 382 | std::pair<ThrottlingSeverity, ThrottlingSeverity> status = |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 383 | std::make_pair(ThrottlingSeverity::NONE, ThrottlingSeverity::NONE); |
Wei Wang | 12ad0a8 | 2019-02-19 16:18:25 -0800 | [diff] [blame] | 384 | // Only update status if the thermal sensor is being monitored |
TeYuan Wang | a520348 | 2022-04-01 17:50:50 +0800 | [diff] [blame] | 385 | if (sensor_info.is_watch) { |
Wei Wang | 12ad0a8 | 2019-02-19 16:18:25 -0800 | [diff] [blame] | 386 | ThrottlingSeverity prev_hot_severity, prev_cold_severity; |
| 387 | { |
| 388 | // reader lock, readTemperature will be called in Binder call and the watcher thread. |
| 389 | std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_); |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 390 | prev_hot_severity = sensor_status_map_.at(sensor_name.data()).prev_hot_severity; |
| 391 | prev_cold_severity = sensor_status_map_.at(sensor_name.data()).prev_cold_severity; |
Wei Wang | 12ad0a8 | 2019-02-19 16:18:25 -0800 | [diff] [blame] | 392 | } |
| 393 | status = getSeverityFromThresholds(sensor_info.hot_thresholds, sensor_info.cold_thresholds, |
| 394 | sensor_info.hot_hysteresis, sensor_info.cold_hysteresis, |
| 395 | prev_hot_severity, prev_cold_severity, out->value); |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 396 | } |
Wei Wang | 12ad0a8 | 2019-02-19 16:18:25 -0800 | [diff] [blame] | 397 | if (throtting_status) { |
| 398 | *throtting_status = status; |
| 399 | } |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 400 | |
| 401 | out->throttlingStatus = static_cast<size_t>(status.first) > static_cast<size_t>(status.second) |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 402 | ? status.first |
| 403 | : status.second; |
TeYuan Wang | aadb90a | 2022-09-23 17:16:36 +0800 | [diff] [blame] | 404 | if (sensor_info.is_watch) { |
| 405 | LOG(INFO) << sensor_name.data() << ":" << out->value << " raw data:[" << sensor_log << "]"; |
| 406 | } |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 407 | return true; |
| 408 | } |
| 409 | |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 410 | bool ThermalHelper::readTemperatureThreshold(std::string_view sensor_name, |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 411 | TemperatureThreshold *out) const { |
| 412 | // Read the file. If the file can't be read temp will be empty string. |
| 413 | std::string temp; |
| 414 | std::string path; |
| 415 | |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 416 | if (!sensor_info_map_.count(sensor_name.data())) { |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 417 | LOG(ERROR) << __func__ << ": sensor not found: " << sensor_name; |
| 418 | return false; |
| 419 | } |
| 420 | |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 421 | const auto &sensor_info = sensor_info_map_.at(sensor_name.data()); |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 422 | |
| 423 | out->type = sensor_info.type; |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 424 | out->name = sensor_name.data(); |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 425 | out->hotThrottlingThresholds = sensor_info.hot_thresholds; |
| 426 | out->coldThrottlingThresholds = sensor_info.cold_thresholds; |
| 427 | out->vrThrottlingThreshold = sensor_info.vr_threshold; |
| 428 | return true; |
| 429 | } |
| 430 | |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 431 | void ThermalHelper::updateCoolingDevices(const std::vector<std::string> &updated_cdev) { |
TeYuan Wang | b8173c1 | 2021-07-08 17:45:58 +0800 | [diff] [blame] | 432 | int max_state; |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 433 | |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 434 | const auto &thermal_throttling_status_map = thermal_throttling_.GetThermalThrottlingStatusMap(); |
| 435 | |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 436 | for (const auto &target_cdev : updated_cdev) { |
| 437 | max_state = 0; |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 438 | for (const auto &thermal_throttling_status_pair : thermal_throttling_status_map) { |
| 439 | if (!thermal_throttling_status_pair.second.cdev_status_map.count(target_cdev)) { |
| 440 | continue; |
| 441 | } |
| 442 | const auto state = |
| 443 | thermal_throttling_status_pair.second.cdev_status_map.at(target_cdev); |
| 444 | if (state > max_state) { |
| 445 | max_state = state; |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 446 | } |
| 447 | } |
| 448 | if (cooling_devices_.writeCdevFile(target_cdev, std::to_string(max_state))) { |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 449 | LOG(INFO) << "Successfully update cdev " << target_cdev << " sysfs to " << max_state; |
TeYuan Wang | d2920b9 | 2022-05-25 15:40:20 +0800 | [diff] [blame] | 450 | } else { |
| 451 | LOG(ERROR) << "Failed to update cdev " << target_cdev << " sysfs to " << max_state; |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 452 | } |
| 453 | } |
| 454 | } |
| 455 | |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 456 | std::pair<ThrottlingSeverity, ThrottlingSeverity> ThermalHelper::getSeverityFromThresholds( |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 457 | const ThrottlingArray &hot_thresholds, const ThrottlingArray &cold_thresholds, |
| 458 | const ThrottlingArray &hot_hysteresis, const ThrottlingArray &cold_hysteresis, |
| 459 | ThrottlingSeverity prev_hot_severity, ThrottlingSeverity prev_cold_severity, |
| 460 | float value) const { |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 461 | ThrottlingSeverity ret_hot = ThrottlingSeverity::NONE; |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 462 | ThrottlingSeverity ret_hot_hysteresis = ThrottlingSeverity::NONE; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 463 | ThrottlingSeverity ret_cold = ThrottlingSeverity::NONE; |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 464 | ThrottlingSeverity ret_cold_hysteresis = ThrottlingSeverity::NONE; |
| 465 | |
| 466 | // Here we want to control the iteration from high to low, and hidl_enum_range doesn't support |
| 467 | // a reverse iterator yet. |
| 468 | for (size_t i = static_cast<size_t>(ThrottlingSeverity::SHUTDOWN); |
| 469 | i > static_cast<size_t>(ThrottlingSeverity::NONE); --i) { |
| 470 | if (!std::isnan(hot_thresholds[i]) && hot_thresholds[i] <= value && |
| 471 | ret_hot == ThrottlingSeverity::NONE) { |
| 472 | ret_hot = static_cast<ThrottlingSeverity>(i); |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 473 | } |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 474 | if (!std::isnan(hot_thresholds[i]) && (hot_thresholds[i] - hot_hysteresis[i]) < value && |
| 475 | ret_hot_hysteresis == ThrottlingSeverity::NONE) { |
| 476 | ret_hot_hysteresis = static_cast<ThrottlingSeverity>(i); |
| 477 | } |
| 478 | if (!std::isnan(cold_thresholds[i]) && cold_thresholds[i] >= value && |
| 479 | ret_cold == ThrottlingSeverity::NONE) { |
| 480 | ret_cold = static_cast<ThrottlingSeverity>(i); |
| 481 | } |
| 482 | if (!std::isnan(cold_thresholds[i]) && (cold_thresholds[i] + cold_hysteresis[i]) > value && |
| 483 | ret_cold_hysteresis == ThrottlingSeverity::NONE) { |
| 484 | ret_cold_hysteresis = static_cast<ThrottlingSeverity>(i); |
| 485 | } |
| 486 | } |
| 487 | if (static_cast<size_t>(ret_hot) < static_cast<size_t>(prev_hot_severity)) { |
| 488 | ret_hot = ret_hot_hysteresis; |
| 489 | } |
| 490 | if (static_cast<size_t>(ret_cold) < static_cast<size_t>(prev_cold_severity)) { |
| 491 | ret_cold = ret_cold_hysteresis; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 492 | } |
| 493 | |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 494 | return std::make_pair(ret_hot, ret_cold); |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 495 | } |
| 496 | |
TeYuan Wang | 5013fe4 | 2021-03-16 19:52:06 +0800 | [diff] [blame] | 497 | bool ThermalHelper::initializeSensorMap( |
| 498 | const std::unordered_map<std::string, std::string> &path_map) { |
Wei Wang | be44475 | 2019-02-01 15:12:28 -0800 | [diff] [blame] | 499 | for (const auto &sensor_info_pair : sensor_info_map_) { |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 500 | std::string_view sensor_name = sensor_info_pair.first; |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 501 | if (sensor_info_pair.second.virtual_sensor_info != nullptr) { |
| 502 | continue; |
George Lee | 9af1e97 | 2020-10-05 11:59:36 -0700 | [diff] [blame] | 503 | } |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 504 | if (!path_map.count(sensor_name.data())) { |
Wei Wang | be44475 | 2019-02-01 15:12:28 -0800 | [diff] [blame] | 505 | LOG(ERROR) << "Could not find " << sensor_name << " in sysfs"; |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 506 | return false; |
Wei Wang | be44475 | 2019-02-01 15:12:28 -0800 | [diff] [blame] | 507 | } |
YiHo Cheng | f1da54d | 2021-07-08 19:33:11 +0800 | [diff] [blame] | 508 | |
| 509 | std::string path; |
| 510 | if (sensor_info_pair.second.temp_path.empty()) { |
| 511 | path = android::base::StringPrintf("%s/%s", path_map.at(sensor_name.data()).c_str(), |
| 512 | kSensorTempSuffix.data()); |
| 513 | } else { |
| 514 | path = sensor_info_pair.second.temp_path; |
| 515 | } |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 516 | |
Wei Wang | be44475 | 2019-02-01 15:12:28 -0800 | [diff] [blame] | 517 | if (!thermal_sensors_.addThermalFile(sensor_name, path)) { |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 518 | LOG(ERROR) << "Could not add " << sensor_name << "to sensors map"; |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 519 | return false; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 520 | } |
| 521 | } |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 522 | return true; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 523 | } |
| 524 | |
TeYuan Wang | 5013fe4 | 2021-03-16 19:52:06 +0800 | [diff] [blame] | 525 | bool ThermalHelper::initializeCoolingDevices( |
| 526 | const std::unordered_map<std::string, std::string> &path_map) { |
TeYuan Wang | c618626 | 2021-04-27 15:11:44 +0800 | [diff] [blame] | 527 | for (auto &cooling_device_info_pair : cooling_device_info_map_) { |
TeYuan Wang | 6326082 | 2021-02-02 16:57:19 +0800 | [diff] [blame] | 528 | std::string cooling_device_name = cooling_device_info_pair.first; |
| 529 | if (!path_map.count(cooling_device_name)) { |
Wei Wang | be44475 | 2019-02-01 15:12:28 -0800 | [diff] [blame] | 530 | LOG(ERROR) << "Could not find " << cooling_device_name << " in sysfs"; |
TeYuan Wang | 2ec4c03 | 2022-03-14 17:33:15 +0800 | [diff] [blame] | 531 | return false; |
Wei Wang | be44475 | 2019-02-01 15:12:28 -0800 | [diff] [blame] | 532 | } |
TeYuan Wang | 6326082 | 2021-02-02 16:57:19 +0800 | [diff] [blame] | 533 | // Add cooling device path for thermalHAL to get current state |
| 534 | std::string_view path = path_map.at(cooling_device_name); |
| 535 | std::string read_path; |
| 536 | if (!cooling_device_info_pair.second.read_path.empty()) { |
| 537 | read_path = cooling_device_info_pair.second.read_path.data(); |
| 538 | } else { |
| 539 | read_path = android::base::StringPrintf("%s/%s", path.data(), |
| 540 | kCoolingDeviceCurStateSuffix.data()); |
| 541 | } |
| 542 | if (!cooling_devices_.addThermalFile(cooling_device_name, read_path)) { |
| 543 | LOG(ERROR) << "Could not add " << cooling_device_name |
| 544 | << " read path to cooling device map"; |
TeYuan Wang | 2ec4c03 | 2022-03-14 17:33:15 +0800 | [diff] [blame] | 545 | return false; |
TeYuan Wang | 6326082 | 2021-02-02 16:57:19 +0800 | [diff] [blame] | 546 | } |
| 547 | |
David Chao | d774cbb | 2021-06-09 11:08:18 +0800 | [diff] [blame] | 548 | std::string state2power_path = android::base::StringPrintf( |
| 549 | "%s/%s", path.data(), kCoolingDeviceState2powerSuffix.data()); |
| 550 | std::string state2power_str; |
| 551 | if (android::base::ReadFileToString(state2power_path, &state2power_str)) { |
| 552 | LOG(INFO) << "Cooling device " << cooling_device_info_pair.first |
| 553 | << " use state2power read from sysfs"; |
| 554 | cooling_device_info_pair.second.state2power.clear(); |
| 555 | |
| 556 | std::stringstream power(state2power_str); |
| 557 | unsigned int power_number; |
| 558 | int i = 0; |
| 559 | while (power >> power_number) { |
| 560 | cooling_device_info_pair.second.state2power.push_back( |
| 561 | static_cast<float>(power_number)); |
| 562 | LOG(INFO) << "Cooling device " << cooling_device_info_pair.first << " state:" << i |
| 563 | << " power: " << power_number; |
| 564 | i++; |
| 565 | } |
| 566 | } |
| 567 | |
TeYuan Wang | c618626 | 2021-04-27 15:11:44 +0800 | [diff] [blame] | 568 | // Get max cooling device request state |
| 569 | std::string max_state; |
| 570 | std::string max_state_path = android::base::StringPrintf( |
| 571 | "%s/%s", path.data(), kCoolingDeviceMaxStateSuffix.data()); |
| 572 | if (!android::base::ReadFileToString(max_state_path, &max_state)) { |
| 573 | LOG(ERROR) << cooling_device_info_pair.first |
| 574 | << " could not open max state file:" << max_state_path; |
TeYuan Wang | b8173c1 | 2021-07-08 17:45:58 +0800 | [diff] [blame] | 575 | cooling_device_info_pair.second.max_state = std::numeric_limits<int>::max(); |
TeYuan Wang | c618626 | 2021-04-27 15:11:44 +0800 | [diff] [blame] | 576 | } else { |
| 577 | cooling_device_info_pair.second.max_state = std::stoi(android::base::Trim(max_state)); |
| 578 | LOG(INFO) << "Cooling device " << cooling_device_info_pair.first |
David Chao | d774cbb | 2021-06-09 11:08:18 +0800 | [diff] [blame] | 579 | << " max state: " << cooling_device_info_pair.second.max_state |
| 580 | << " state2power number: " |
| 581 | << cooling_device_info_pair.second.state2power.size(); |
| 582 | if (cooling_device_info_pair.second.state2power.size() > 0 && |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 583 | static_cast<int>(cooling_device_info_pair.second.state2power.size()) != |
| 584 | (cooling_device_info_pair.second.max_state + 1)) { |
David Chao | d774cbb | 2021-06-09 11:08:18 +0800 | [diff] [blame] | 585 | LOG(ERROR) << "Invalid state2power number: " |
| 586 | << cooling_device_info_pair.second.state2power.size() |
| 587 | << ", number should be " << cooling_device_info_pair.second.max_state + 1 |
| 588 | << " (max_state + 1)"; |
TeYuan Wang | 2ec4c03 | 2022-03-14 17:33:15 +0800 | [diff] [blame] | 589 | return false; |
David Chao | d774cbb | 2021-06-09 11:08:18 +0800 | [diff] [blame] | 590 | } |
TeYuan Wang | c618626 | 2021-04-27 15:11:44 +0800 | [diff] [blame] | 591 | } |
| 592 | |
TeYuan Wang | 6326082 | 2021-02-02 16:57:19 +0800 | [diff] [blame] | 593 | // Add cooling device path for thermalHAL to request state |
| 594 | cooling_device_name = |
| 595 | android::base::StringPrintf("%s_%s", cooling_device_name.c_str(), "w"); |
| 596 | std::string write_path; |
| 597 | if (!cooling_device_info_pair.second.write_path.empty()) { |
| 598 | write_path = cooling_device_info_pair.second.write_path.data(); |
| 599 | } else { |
| 600 | write_path = android::base::StringPrintf("%s/%s", path.data(), |
| 601 | kCoolingDeviceCurStateSuffix.data()); |
| 602 | } |
| 603 | |
| 604 | if (!cooling_devices_.addThermalFile(cooling_device_name, write_path)) { |
| 605 | LOG(ERROR) << "Could not add " << cooling_device_name |
| 606 | << " write path to cooling device map"; |
TeYuan Wang | 2ec4c03 | 2022-03-14 17:33:15 +0800 | [diff] [blame] | 607 | return false; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 608 | } |
| 609 | } |
Wei Wang | 197195f | 2021-04-02 16:57:32 -0700 | [diff] [blame] | 610 | return true; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 611 | } |
| 612 | |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 613 | void ThermalHelper::setMinTimeout(SensorInfo *sensor_info) { |
| 614 | sensor_info->polling_delay = kMinPollIntervalMs; |
| 615 | sensor_info->passive_delay = kMinPollIntervalMs; |
| 616 | } |
| 617 | |
TeYuan Wang | 5013fe4 | 2021-03-16 19:52:06 +0800 | [diff] [blame] | 618 | void ThermalHelper::initializeTrip(const std::unordered_map<std::string, std::string> &path_map, |
TeYuan Wang | 6326082 | 2021-02-02 16:57:19 +0800 | [diff] [blame] | 619 | std::set<std::string> *monitored_sensors, |
| 620 | bool thermal_genl_enabled) { |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 621 | for (auto &sensor_info : sensor_info_map_) { |
TeYuan Wang | a520348 | 2022-04-01 17:50:50 +0800 | [diff] [blame] | 622 | if (!sensor_info.second.is_watch || (sensor_info.second.virtual_sensor_info != nullptr)) { |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 623 | continue; |
| 624 | } |
| 625 | |
TeYuan Wang | 4edd2aa | 2021-02-18 21:40:27 +0800 | [diff] [blame] | 626 | bool trip_update = false; |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 627 | std::string_view sensor_name = sensor_info.first; |
| 628 | std::string_view tz_path = path_map.at(sensor_name.data()); |
| 629 | std::string tz_policy; |
| 630 | std::string path = |
| 631 | android::base::StringPrintf("%s/%s", (tz_path.data()), kSensorPolicyFile.data()); |
TeYuan Wang | 4edd2aa | 2021-02-18 21:40:27 +0800 | [diff] [blame] | 632 | |
| 633 | if (thermal_genl_enabled) { |
| 634 | trip_update = true; |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 635 | } else { |
TeYuan Wang | 4edd2aa | 2021-02-18 21:40:27 +0800 | [diff] [blame] | 636 | // Check if thermal zone support uevent notify |
| 637 | if (!android::base::ReadFileToString(path, &tz_policy)) { |
| 638 | LOG(ERROR) << sensor_name << " could not open tz policy file:" << path; |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 639 | } else { |
TeYuan Wang | 4edd2aa | 2021-02-18 21:40:27 +0800 | [diff] [blame] | 640 | tz_policy = android::base::Trim(tz_policy); |
| 641 | if (tz_policy != kUserSpaceSuffix) { |
| 642 | LOG(ERROR) << sensor_name << " does not support uevent notify"; |
| 643 | } else { |
| 644 | trip_update = true; |
| 645 | } |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 646 | } |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 647 | } |
TeYuan Wang | 4edd2aa | 2021-02-18 21:40:27 +0800 | [diff] [blame] | 648 | if (trip_update) { |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 649 | // Update thermal zone trip point |
| 650 | for (size_t i = 0; i < kThrottlingSeverityCount; ++i) { |
| 651 | if (!std::isnan(sensor_info.second.hot_thresholds[i]) && |
| 652 | !std::isnan(sensor_info.second.hot_hysteresis[i])) { |
| 653 | // Update trip_point_0_temp threshold |
| 654 | std::string threshold = std::to_string(static_cast<int>( |
| 655 | sensor_info.second.hot_thresholds[i] / sensor_info.second.multiplier)); |
| 656 | path = android::base::StringPrintf("%s/%s", (tz_path.data()), |
| 657 | kSensorTripPointTempZeroFile.data()); |
| 658 | if (!android::base::WriteStringToFile(threshold, path)) { |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 659 | LOG(ERROR) << "fail to update " << sensor_name << " trip point: " << path |
| 660 | << " to " << threshold; |
TeYuan Wang | 4edd2aa | 2021-02-18 21:40:27 +0800 | [diff] [blame] | 661 | trip_update = false; |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 662 | break; |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 663 | } |
| 664 | // Update trip_point_0_hyst threshold |
| 665 | threshold = std::to_string(static_cast<int>( |
| 666 | sensor_info.second.hot_hysteresis[i] / sensor_info.second.multiplier)); |
| 667 | path = android::base::StringPrintf("%s/%s", (tz_path.data()), |
| 668 | kSensorTripPointHystZeroFile.data()); |
| 669 | if (!android::base::WriteStringToFile(threshold, path)) { |
| 670 | LOG(ERROR) << "fail to update " << sensor_name << "trip hyst" << threshold |
| 671 | << path; |
TeYuan Wang | 4edd2aa | 2021-02-18 21:40:27 +0800 | [diff] [blame] | 672 | trip_update = false; |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 673 | break; |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 674 | } |
| 675 | break; |
| 676 | } else if (i == kThrottlingSeverityCount - 1) { |
| 677 | LOG(ERROR) << sensor_name << ":all thresholds are NAN"; |
TeYuan Wang | 4edd2aa | 2021-02-18 21:40:27 +0800 | [diff] [blame] | 678 | trip_update = false; |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 679 | break; |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 680 | } |
| 681 | } |
TeYuan Wang | 4edd2aa | 2021-02-18 21:40:27 +0800 | [diff] [blame] | 682 | monitored_sensors->insert(sensor_info.first); |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 683 | } |
TeYuan Wang | 6326082 | 2021-02-02 16:57:19 +0800 | [diff] [blame] | 684 | |
TeYuan Wang | 4edd2aa | 2021-02-18 21:40:27 +0800 | [diff] [blame] | 685 | if (!trip_update) { |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 686 | LOG(INFO) << "config Sensor: " << sensor_info.first |
| 687 | << " to default polling interval: " << kMinPollIntervalMs.count(); |
| 688 | setMinTimeout(&sensor_info.second); |
| 689 | } |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 690 | } |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 691 | } |
TeYuan Wang | 4edd2aa | 2021-02-18 21:40:27 +0800 | [diff] [blame] | 692 | |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 693 | bool ThermalHelper::fillTemperatures(hidl_vec<Temperature_1_0> *temperatures) { |
TeYuan Wang | 2d3c666 | 2022-04-06 11:36:07 +0800 | [diff] [blame] | 694 | std::vector<Temperature_1_0> ret; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 695 | for (const auto &name_info_pair : sensor_info_map_) { |
| 696 | Temperature_1_0 temp; |
| 697 | |
TeYuan Wang | a520348 | 2022-04-01 17:50:50 +0800 | [diff] [blame] | 698 | if (name_info_pair.second.is_hidden) { |
| 699 | continue; |
| 700 | } |
| 701 | |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 702 | if (readTemperature(name_info_pair.first, &temp)) { |
TeYuan Wang | 2d3c666 | 2022-04-06 11:36:07 +0800 | [diff] [blame] | 703 | ret.emplace_back(std::move(temp)); |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 704 | } else { |
| 705 | LOG(ERROR) << __func__ |
| 706 | << ": error reading temperature for sensor: " << name_info_pair.first; |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 707 | return false; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 708 | } |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 709 | } |
TeYuan Wang | 2d3c666 | 2022-04-06 11:36:07 +0800 | [diff] [blame] | 710 | *temperatures = ret; |
TeYuan Wang | 2d3c666 | 2022-04-06 11:36:07 +0800 | [diff] [blame] | 711 | return ret.size() > 0; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 712 | } |
| 713 | |
TeYuan Wang | b9f33ac | 2021-08-04 20:39:42 +0800 | [diff] [blame] | 714 | bool ThermalHelper::fillCurrentTemperatures(bool filterType, bool filterCallback, |
| 715 | TemperatureType_2_0 type, |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 716 | hidl_vec<Temperature_2_0> *temperatures) { |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 717 | std::vector<Temperature_2_0> ret; |
| 718 | for (const auto &name_info_pair : sensor_info_map_) { |
| 719 | Temperature_2_0 temp; |
TeYuan Wang | a520348 | 2022-04-01 17:50:50 +0800 | [diff] [blame] | 720 | if (name_info_pair.second.is_hidden) { |
| 721 | continue; |
| 722 | } |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 723 | if (filterType && name_info_pair.second.type != type) { |
| 724 | continue; |
| 725 | } |
TeYuan Wang | b9f33ac | 2021-08-04 20:39:42 +0800 | [diff] [blame] | 726 | if (filterCallback && !name_info_pair.second.send_cb) { |
| 727 | continue; |
| 728 | } |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 729 | if (readTemperature(name_info_pair.first, &temp, nullptr, false)) { |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 730 | ret.emplace_back(std::move(temp)); |
| 731 | } else { |
| 732 | LOG(ERROR) << __func__ |
| 733 | << ": error reading temperature for sensor: " << name_info_pair.first; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 734 | } |
| 735 | } |
| 736 | *temperatures = ret; |
| 737 | return ret.size() > 0; |
| 738 | } |
| 739 | |
| 740 | bool ThermalHelper::fillTemperatureThresholds(bool filterType, TemperatureType_2_0 type, |
| 741 | hidl_vec<TemperatureThreshold> *thresholds) const { |
| 742 | std::vector<TemperatureThreshold> ret; |
| 743 | for (const auto &name_info_pair : sensor_info_map_) { |
| 744 | TemperatureThreshold temp; |
TeYuan Wang | a520348 | 2022-04-01 17:50:50 +0800 | [diff] [blame] | 745 | if (name_info_pair.second.is_hidden) { |
| 746 | continue; |
| 747 | } |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 748 | if (filterType && name_info_pair.second.type != type) { |
| 749 | continue; |
| 750 | } |
| 751 | if (readTemperatureThreshold(name_info_pair.first, &temp)) { |
| 752 | ret.emplace_back(std::move(temp)); |
| 753 | } else { |
| 754 | LOG(ERROR) << __func__ << ": error reading temperature threshold for sensor: " |
| 755 | << name_info_pair.first; |
| 756 | return false; |
| 757 | } |
| 758 | } |
| 759 | *thresholds = ret; |
| 760 | return ret.size() > 0; |
| 761 | } |
| 762 | |
| 763 | bool ThermalHelper::fillCurrentCoolingDevices(bool filterType, CoolingType type, |
| 764 | hidl_vec<CoolingDevice_2_0> *cooling_devices) const { |
| 765 | std::vector<CoolingDevice_2_0> ret; |
| 766 | for (const auto &name_info_pair : cooling_device_info_map_) { |
| 767 | CoolingDevice_2_0 value; |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 768 | if (filterType && name_info_pair.second.type != type) { |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 769 | continue; |
| 770 | } |
| 771 | if (readCoolingDevice(name_info_pair.first, &value)) { |
| 772 | ret.emplace_back(std::move(value)); |
| 773 | } else { |
| 774 | LOG(ERROR) << __func__ << ": error reading cooling device: " << name_info_pair.first; |
| 775 | return false; |
| 776 | } |
| 777 | } |
| 778 | *cooling_devices = ret; |
| 779 | return ret.size() > 0; |
| 780 | } |
| 781 | |
| 782 | bool ThermalHelper::fillCpuUsages(hidl_vec<CpuUsage> *cpu_usages) const { |
| 783 | cpu_usages->resize(kMaxCpus); |
Wei Wang | a1c7507 | 2020-07-28 14:22:39 -0700 | [diff] [blame] | 784 | for (int i = 0; i < kMaxCpus; i++) { |
| 785 | (*cpu_usages)[i].name = StringPrintf("cpu%d", i); |
| 786 | (*cpu_usages)[i].active = 0; |
| 787 | (*cpu_usages)[i].total = 0; |
| 788 | (*cpu_usages)[i].isOnline = false; |
| 789 | } |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 790 | parseCpuUsagesFileAndAssignUsages(cpu_usages); |
| 791 | return true; |
| 792 | } |
| 793 | |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 794 | bool ThermalHelper::readThermalSensor(std::string_view sensor_name, float *temp, |
TeYuan Wang | aadb90a | 2022-09-23 17:16:36 +0800 | [diff] [blame] | 795 | const bool force_no_cache, std::string *sensor_log) { |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 796 | float temp_val = 0.0; |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 797 | std::string file_reading; |
TeYuan Wang | aadb90a | 2022-09-23 17:16:36 +0800 | [diff] [blame] | 798 | std::string sub_sensor_log; |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 799 | boot_clock::time_point now = boot_clock::now(); |
| 800 | |
TeYuan Wang | d0979f8 | 2022-02-11 19:17:51 +0800 | [diff] [blame] | 801 | ATRACE_NAME(StringPrintf("ThermalHelper::readThermalSensor - %s", sensor_name.data()).c_str()); |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 802 | if (!(sensor_info_map_.count(sensor_name.data()) && |
| 803 | sensor_status_map_.count(sensor_name.data()))) { |
| 804 | return false; |
| 805 | } |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 806 | |
| 807 | const auto &sensor_info = sensor_info_map_.at(sensor_name.data()); |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 808 | auto &sensor_status = sensor_status_map_.at(sensor_name.data()); |
| 809 | |
| 810 | // Check if thermal data need to be read from buffer |
TeYuan Wang | e80ff15 | 2022-06-28 16:33:12 +0800 | [diff] [blame] | 811 | if (!force_no_cache && |
| 812 | (sensor_status.thermal_cached.timestamp != boot_clock::time_point::min()) && |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 813 | (std::chrono::duration_cast<std::chrono::milliseconds>( |
| 814 | now - sensor_status.thermal_cached.timestamp) < sensor_info.time_resolution) && |
| 815 | !isnan(sensor_status.thermal_cached.temp)) { |
| 816 | *temp = sensor_status.thermal_cached.temp; |
TeYuan Wang | aadb90a | 2022-09-23 17:16:36 +0800 | [diff] [blame] | 817 | sensor_log->append(StringPrintf("%s:%0.f ", sensor_name.data(), *temp)); |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 818 | LOG(VERBOSE) << "read " << sensor_name.data() << " from buffer, value:" << *temp; |
| 819 | return true; |
| 820 | } |
| 821 | |
| 822 | // Reading thermal sensor according to it's composition |
| 823 | if (sensor_info.virtual_sensor_info == nullptr) { |
| 824 | if (!thermal_sensors_.readThermalFile(sensor_name.data(), &file_reading)) { |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 825 | return false; |
George Lee | 9af1e97 | 2020-10-05 11:59:36 -0700 | [diff] [blame] | 826 | } |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 827 | |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 828 | if (file_reading.empty()) { |
| 829 | LOG(ERROR) << "failed to read sensor: " << sensor_name; |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 830 | return false; |
George Lee | 9af1e97 | 2020-10-05 11:59:36 -0700 | [diff] [blame] | 831 | } |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 832 | *temp = std::stof(::android::base::Trim(file_reading)); |
TeYuan Wang | aadb90a | 2022-09-23 17:16:36 +0800 | [diff] [blame] | 833 | sensor_log->append(StringPrintf("%s:%0.f ", sensor_name.data(), *temp)); |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 834 | } else { |
| 835 | for (size_t i = 0; i < sensor_info.virtual_sensor_info->linked_sensors.size(); i++) { |
| 836 | float sensor_reading = 0.0; |
| 837 | if (!readThermalSensor(sensor_info.virtual_sensor_info->linked_sensors[i], |
TeYuan Wang | aadb90a | 2022-09-23 17:16:36 +0800 | [diff] [blame] | 838 | &sensor_reading, force_no_cache, &sub_sensor_log)) { |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 839 | return false; |
| 840 | } |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 841 | if (std::isnan(sensor_info.virtual_sensor_info->coefficients[i])) { |
| 842 | return false; |
| 843 | } |
| 844 | |
| 845 | float coefficient = sensor_info.virtual_sensor_info->coefficients[i]; |
| 846 | switch (sensor_info.virtual_sensor_info->formula) { |
| 847 | case FormulaOption::COUNT_THRESHOLD: |
| 848 | if ((coefficient < 0 && sensor_reading < -coefficient) || |
| 849 | (coefficient >= 0 && sensor_reading >= coefficient)) |
| 850 | temp_val += 1; |
| 851 | break; |
| 852 | case FormulaOption::WEIGHTED_AVG: |
| 853 | temp_val += sensor_reading * coefficient; |
| 854 | break; |
| 855 | case FormulaOption::MAXIMUM: |
| 856 | if (i == 0) |
| 857 | temp_val = std::numeric_limits<float>::lowest(); |
| 858 | if (sensor_reading * coefficient > temp_val) |
| 859 | temp_val = sensor_reading * coefficient; |
| 860 | break; |
| 861 | case FormulaOption::MINIMUM: |
| 862 | if (i == 0) |
| 863 | temp_val = std::numeric_limits<float>::max(); |
| 864 | if (sensor_reading * coefficient < temp_val) |
| 865 | temp_val = sensor_reading * coefficient; |
| 866 | break; |
| 867 | default: |
| 868 | break; |
| 869 | } |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 870 | } |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 871 | *temp = (temp_val + sensor_info.virtual_sensor_info->offset); |
TeYuan Wang | aadb90a | 2022-09-23 17:16:36 +0800 | [diff] [blame] | 872 | sensor_log->append( |
| 873 | StringPrintf("%s:%0.f(%s) ", sensor_name.data(), *temp, sub_sensor_log.data())); |
George Lee | 9af1e97 | 2020-10-05 11:59:36 -0700 | [diff] [blame] | 874 | } |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 875 | |
| 876 | { |
| 877 | std::unique_lock<std::shared_mutex> _lock(sensor_status_map_mutex_); |
| 878 | sensor_status.thermal_cached.temp = *temp; |
| 879 | sensor_status.thermal_cached.timestamp = now; |
| 880 | } |
| 881 | |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 882 | return true; |
George Lee | 9af1e97 | 2020-10-05 11:59:36 -0700 | [diff] [blame] | 883 | } |
| 884 | |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 885 | // This is called in the different thread context and will update sensor_status |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 886 | // uevent_sensors is the set of sensors which trigger uevent from thermal core driver. |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 887 | std::chrono::milliseconds ThermalHelper::thermalWatcherCallbackFunc( |
| 888 | const std::set<std::string> &uevent_sensors) { |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 889 | std::vector<Temperature_2_0> temps; |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 890 | std::vector<std::string> cooling_devices_to_update; |
| 891 | boot_clock::time_point now = boot_clock::now(); |
TeYuan Wang | 5013fe4 | 2021-03-16 19:52:06 +0800 | [diff] [blame] | 892 | auto min_sleep_ms = std::chrono::milliseconds::max(); |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 893 | bool power_data_is_updated = false; |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 894 | |
TeYuan Wang | d0979f8 | 2022-02-11 19:17:51 +0800 | [diff] [blame] | 895 | ATRACE_CALL(); |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 896 | for (auto &name_status_pair : sensor_status_map_) { |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 897 | bool force_update = false; |
TeYuan Wang | e80ff15 | 2022-06-28 16:33:12 +0800 | [diff] [blame] | 898 | bool force_no_cache = false; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 899 | Temperature_2_0 temp; |
| 900 | TemperatureThreshold threshold; |
| 901 | SensorStatus &sensor_status = name_status_pair.second; |
| 902 | const SensorInfo &sensor_info = sensor_info_map_.at(name_status_pair.first); |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 903 | |
| 904 | // Only handle the sensors in allow list |
TeYuan Wang | 996a9e1 | 2022-04-13 11:38:45 +0800 | [diff] [blame] | 905 | if (!sensor_info.is_watch) { |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 906 | continue; |
| 907 | } |
George Lee | 9af1e97 | 2020-10-05 11:59:36 -0700 | [diff] [blame] | 908 | |
TeYuan Wang | d0979f8 | 2022-02-11 19:17:51 +0800 | [diff] [blame] | 909 | ATRACE_NAME(StringPrintf("ThermalHelper::thermalWatcherCallbackFunc - %s", |
| 910 | name_status_pair.first.data()) |
| 911 | .c_str()); |
| 912 | |
TeYuan Wang | 8daf64c | 2021-07-05 11:17:05 +0800 | [diff] [blame] | 913 | std::chrono::milliseconds time_elapsed_ms = std::chrono::milliseconds::zero(); |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 914 | auto sleep_ms = (sensor_status.severity != ThrottlingSeverity::NONE) |
| 915 | ? sensor_info.passive_delay |
| 916 | : sensor_info.polling_delay; |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 917 | |
| 918 | if (sensor_info.virtual_sensor_info != nullptr && |
TeYuan Wang | e80ff15 | 2022-06-28 16:33:12 +0800 | [diff] [blame] | 919 | !sensor_info.virtual_sensor_info->trigger_sensors.empty()) { |
| 920 | for (size_t i = 0; i < sensor_info.virtual_sensor_info->trigger_sensors.size(); i++) { |
| 921 | const auto &trigger_sensor_status = |
| 922 | sensor_status_map_.at(sensor_info.virtual_sensor_info->trigger_sensors[i]); |
| 923 | if (trigger_sensor_status.severity != ThrottlingSeverity::NONE) { |
| 924 | sleep_ms = sensor_info.passive_delay; |
| 925 | } |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 926 | } |
| 927 | } |
TeYuan Wang | 8daf64c | 2021-07-05 11:17:05 +0800 | [diff] [blame] | 928 | // Check if the sensor need to be updated |
| 929 | if (sensor_status.last_update_time == boot_clock::time_point::min()) { |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 930 | force_update = true; |
TeYuan Wang | e80ff15 | 2022-06-28 16:33:12 +0800 | [diff] [blame] | 931 | force_no_cache = true; |
TeYuan Wang | 8daf64c | 2021-07-05 11:17:05 +0800 | [diff] [blame] | 932 | } else { |
| 933 | time_elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>( |
| 934 | now - sensor_status.last_update_time); |
TeYuan Wang | e80ff15 | 2022-06-28 16:33:12 +0800 | [diff] [blame] | 935 | if (uevent_sensors.size()) { |
| 936 | if (sensor_info.virtual_sensor_info != nullptr) { |
| 937 | for (size_t i = 0; i < sensor_info.virtual_sensor_info->trigger_sensors.size(); |
| 938 | i++) { |
| 939 | if (uevent_sensors.find( |
| 940 | sensor_info.virtual_sensor_info->trigger_sensors[i]) != |
| 941 | uevent_sensors.end()) { |
| 942 | force_update = true; |
| 943 | force_no_cache = true; |
| 944 | } |
| 945 | } |
| 946 | } else if (uevent_sensors.find(name_status_pair.first) != uevent_sensors.end()) { |
| 947 | force_update = true; |
| 948 | force_no_cache = true; |
| 949 | } |
| 950 | } else if (time_elapsed_ms > sleep_ms) { |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 951 | force_update = true; |
| 952 | } |
| 953 | } |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 954 | LOG(VERBOSE) << "sensor " << name_status_pair.first |
| 955 | << ": time_elpased=" << time_elapsed_ms.count() |
TeYuan Wang | 1a3d017 | 2021-12-23 15:30:16 +0800 | [diff] [blame] | 956 | << ", sleep_ms=" << sleep_ms.count() << ", force_update = " << force_update |
TeYuan Wang | e80ff15 | 2022-06-28 16:33:12 +0800 | [diff] [blame] | 957 | << ", force_no_cache = " << force_no_cache; |
TeYuan Wang | 8cbada8 | 2020-12-10 15:49:53 +0800 | [diff] [blame] | 958 | |
| 959 | if (!force_update) { |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 960 | auto timeout_remaining = sleep_ms - time_elapsed_ms; |
| 961 | if (min_sleep_ms > timeout_remaining) { |
| 962 | min_sleep_ms = timeout_remaining; |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 963 | } |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 964 | LOG(VERBOSE) << "sensor " << name_status_pair.first |
| 965 | << ": timeout_remaining=" << timeout_remaining.count(); |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 966 | continue; |
| 967 | } |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 968 | |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 969 | std::pair<ThrottlingSeverity, ThrottlingSeverity> throtting_status; |
TeYuan Wang | e80ff15 | 2022-06-28 16:33:12 +0800 | [diff] [blame] | 970 | if (!readTemperature(name_status_pair.first, &temp, &throtting_status, force_no_cache)) { |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 971 | LOG(ERROR) << __func__ |
| 972 | << ": error reading temperature for sensor: " << name_status_pair.first; |
| 973 | continue; |
| 974 | } |
| 975 | if (!readTemperatureThreshold(name_status_pair.first, &threshold)) { |
| 976 | LOG(ERROR) << __func__ << ": error reading temperature threshold for sensor: " |
| 977 | << name_status_pair.first; |
| 978 | continue; |
| 979 | } |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 980 | |
| 981 | { |
| 982 | // writer lock |
| 983 | std::unique_lock<std::shared_mutex> _lock(sensor_status_map_mutex_); |
| 984 | if (throtting_status.first != sensor_status.prev_hot_severity) { |
| 985 | sensor_status.prev_hot_severity = throtting_status.first; |
| 986 | } |
| 987 | if (throtting_status.second != sensor_status.prev_cold_severity) { |
| 988 | sensor_status.prev_cold_severity = throtting_status.second; |
| 989 | } |
| 990 | if (temp.throttlingStatus != sensor_status.severity) { |
| 991 | temps.push_back(temp); |
| 992 | sensor_status.severity = temp.throttlingStatus; |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 993 | sleep_ms = (sensor_status.severity != ThrottlingSeverity::NONE) |
| 994 | ? sensor_info.passive_delay |
| 995 | : sensor_info.polling_delay; |
Wei Wang | 1c47356 | 2018-10-23 21:14:06 -0700 | [diff] [blame] | 996 | } |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 997 | } |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 998 | |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 999 | if (!power_data_is_updated) { |
| 1000 | power_files_.refreshPowerStatus(); |
| 1001 | power_data_is_updated = true; |
| 1002 | } |
| 1003 | |
| 1004 | if (sensor_status.severity == ThrottlingSeverity::NONE) { |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 1005 | thermal_throttling_.clearThrottlingData(name_status_pair.first, sensor_info); |
| 1006 | } else { |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 1007 | // update thermal throttling request |
| 1008 | thermal_throttling_.thermalThrottlingUpdate( |
| 1009 | temp, sensor_info, sensor_status.severity, time_elapsed_ms, |
| 1010 | power_files_.GetPowerStatusMap(), cooling_device_info_map_); |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 1011 | } |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 1012 | |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 1013 | thermal_throttling_.computeCoolingDevicesRequest(name_status_pair.first, sensor_info, |
| 1014 | sensor_status.severity, |
| 1015 | &cooling_devices_to_update); |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 1016 | if (min_sleep_ms > sleep_ms) { |
| 1017 | min_sleep_ms = sleep_ms; |
| 1018 | } |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 1019 | |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 1020 | LOG(VERBOSE) << "Sensor " << name_status_pair.first << ": sleep_ms=" << sleep_ms.count() |
| 1021 | << ", min_sleep_ms voting result=" << min_sleep_ms.count(); |
| 1022 | sensor_status.last_update_time = now; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 1023 | } |
TeYuan Wang | 2f5b7f6 | 2019-01-07 13:39:21 +0800 | [diff] [blame] | 1024 | |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 1025 | if (!cooling_devices_to_update.empty()) { |
| 1026 | updateCoolingDevices(cooling_devices_to_update); |
| 1027 | } |
| 1028 | |
| 1029 | if (!temps.empty()) { |
| 1030 | for (const auto &t : temps) { |
| 1031 | if (sensor_info_map_.at(t.name).send_cb && cb_) { |
| 1032 | cb_(t); |
| 1033 | } |
| 1034 | |
| 1035 | if (sensor_info_map_.at(t.name).send_powerhint && isAidlPowerHalExist()) { |
| 1036 | sendPowerExtHint(t); |
| 1037 | } |
| 1038 | } |
| 1039 | } |
| 1040 | |
TeYuan Wang | 708a1df | 2022-03-28 20:26:06 +0800 | [diff] [blame] | 1041 | return min_sleep_ms; |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 1042 | } |
| 1043 | |
Kyle Lin | 7c8556b | 2020-08-07 17:02:55 +0800 | [diff] [blame] | 1044 | bool ThermalHelper::connectToPowerHal() { |
| 1045 | return power_hal_service_.connect(); |
| 1046 | } |
| 1047 | |
| 1048 | void ThermalHelper::updateSupportedPowerHints() { |
| 1049 | for (auto const &name_status_pair : sensor_info_map_) { |
TeYuan Wang | dcee68c | 2020-10-21 16:29:37 +0800 | [diff] [blame] | 1050 | if (!(name_status_pair.second.send_powerhint)) { |
Kyle Lin | 7c8556b | 2020-08-07 17:02:55 +0800 | [diff] [blame] | 1051 | continue; |
| 1052 | } |
| 1053 | ThrottlingSeverity current_severity = ThrottlingSeverity::NONE; |
| 1054 | for (const auto &severity : hidl_enum_range<ThrottlingSeverity>()) { |
Kyle Lin | 7c8556b | 2020-08-07 17:02:55 +0800 | [diff] [blame] | 1055 | if (severity == ThrottlingSeverity::NONE) { |
| 1056 | supported_powerhint_map_[name_status_pair.first][ThrottlingSeverity::NONE] = |
| 1057 | ThrottlingSeverity::NONE; |
| 1058 | continue; |
| 1059 | } |
| 1060 | |
| 1061 | bool isSupported = false; |
| 1062 | ndk::ScopedAStatus isSupportedResult; |
| 1063 | |
| 1064 | if (power_hal_service_.isPowerHalExtConnected()) { |
| 1065 | isSupported = power_hal_service_.isModeSupported(name_status_pair.first, severity); |
| 1066 | } |
| 1067 | if (isSupported) |
| 1068 | current_severity = severity; |
| 1069 | supported_powerhint_map_[name_status_pair.first][severity] = current_severity; |
| 1070 | } |
| 1071 | } |
| 1072 | } |
| 1073 | |
| 1074 | void ThermalHelper::sendPowerExtHint(const Temperature_2_0 &t) { |
TeYuan Wang | d0979f8 | 2022-02-11 19:17:51 +0800 | [diff] [blame] | 1075 | ATRACE_CALL(); |
Kyle Lin | 7c8556b | 2020-08-07 17:02:55 +0800 | [diff] [blame] | 1076 | std::lock_guard<std::shared_mutex> lock(sensor_status_map_mutex_); |
Kyle Lin | 7c8556b | 2020-08-07 17:02:55 +0800 | [diff] [blame] | 1077 | ThrottlingSeverity prev_hint_severity; |
| 1078 | prev_hint_severity = sensor_status_map_.at(t.name).prev_hint_severity; |
| 1079 | ThrottlingSeverity current_hint_severity = supported_powerhint_map_[t.name][t.throttlingStatus]; |
| 1080 | |
| 1081 | if (prev_hint_severity == current_hint_severity) |
| 1082 | return; |
| 1083 | |
| 1084 | if (prev_hint_severity != ThrottlingSeverity::NONE) { |
| 1085 | power_hal_service_.setMode(t.name, prev_hint_severity, false); |
| 1086 | } |
| 1087 | |
| 1088 | if (current_hint_severity != ThrottlingSeverity::NONE) { |
| 1089 | power_hal_service_.setMode(t.name, current_hint_severity, true); |
| 1090 | } |
| 1091 | |
| 1092 | sensor_status_map_[t.name].prev_hint_severity = current_hint_severity; |
| 1093 | } |
Wei Wang | 086a2b2 | 2018-10-22 13:54:33 -0700 | [diff] [blame] | 1094 | } // namespace implementation |
| 1095 | } // namespace V2_0 |
| 1096 | } // namespace thermal |
| 1097 | } // namespace hardware |
| 1098 | } // namespace android |