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