• 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 
17 #include <iterator>
18 #include <set>
19 #include <sstream>
20 #include <thread>
21 #include <vector>
22 
23 #include <android-base/file.h>
24 #include <android-base/logging.h>
25 #include <android-base/properties.h>
26 #include <android-base/stringprintf.h>
27 #include <android-base/strings.h>
28 #include <hidl/HidlTransportSupport.h>
29 
30 #include "thermal-helper.h"
31 
32 namespace android {
33 namespace hardware {
34 namespace thermal {
35 namespace V2_0 {
36 namespace implementation {
37 
38 constexpr std::string_view kCpuOnlineRoot("/sys/devices/system/cpu");
39 constexpr std::string_view kThermalSensorsRoot("/sys/devices/virtual/thermal");
40 constexpr std::string_view kCpuUsageFile("/proc/stat");
41 constexpr std::string_view kCpuOnlineFileSuffix("online");
42 constexpr std::string_view kCpuPresentFile("/sys/devices/system/cpu/present");
43 constexpr std::string_view kSensorPrefix("thermal_zone");
44 constexpr std::string_view kCoolingDevicePrefix("cooling_device");
45 constexpr std::string_view kThermalNameFile("type");
46 constexpr std::string_view kSensorPolicyFile("policy");
47 constexpr std::string_view kSensorTempSuffix("temp");
48 constexpr std::string_view kSensorTripPointTempZeroFile("trip_point_0_temp");
49 constexpr std::string_view kSensorTripPointHystZeroFile("trip_point_0_hyst");
50 constexpr std::string_view kUserSpaceSuffix("user_space");
51 constexpr std::string_view kCoolingDeviceCurStateSuffix("cur_state");
52 constexpr std::string_view kConfigProperty("vendor.thermal.config");
53 constexpr std::string_view kConfigDefaultFileName("thermal_info_config.json");
54 
55 namespace {
56 using android::base::StringPrintf;
57 
58 /*
59  * Pixel don't offline CPU, so std::thread::hardware_concurrency(); should work.
60  * However /sys/devices/system/cpu/present is preferred.
61  * The file is expected to contain single text line with two numbers %d-%d,
62  * which is a range of available cpu numbers, e.g. 0-7 would mean there
63  * are 8 cores number from 0 to 7.
64  * For Android systems this approach is safer than using cpufeatures, see bug
65  * b/36941727.
66  */
getNumberOfCores()67 std::size_t getNumberOfCores() {
68     std::string file;
69     if (!android::base::ReadFileToString(kCpuPresentFile.data(), &file)) {
70         LOG(ERROR) << "Error reading Cpu present file: " << kCpuPresentFile;
71         return 0;
72     }
73     std::vector<std::string> pieces = android::base::Split(file, "-");
74     if (pieces.size() != 2) {
75         LOG(ERROR) << "Error parsing Cpu present file content: " << file;
76         return 0;
77     }
78     auto min_core = std::stoul(pieces[0]);
79     auto max_core = std::stoul(pieces[1]);
80     if (max_core < min_core) {
81         LOG(ERROR) << "Error parsing Cpu present min and max: " << min_core << " - " << max_core;
82         return 0;
83     }
84     return static_cast<std::size_t>(max_core - min_core + 1);
85 }
86 const std::size_t kMaxCpus = getNumberOfCores();
87 
parseCpuUsagesFileAndAssignUsages(hidl_vec<CpuUsage> * cpu_usages)88 void parseCpuUsagesFileAndAssignUsages(hidl_vec<CpuUsage> *cpu_usages) {
89     uint64_t cpu_num, user, nice, system, idle;
90     std::string cpu_name;
91     std::string data;
92     if (!android::base::ReadFileToString(kCpuUsageFile.data(), &data)) {
93         LOG(ERROR) << "Error reading Cpu usage file: " << kCpuUsageFile;
94         return;
95     }
96 
97     std::istringstream stat_data(data);
98     std::string line;
99     while (std::getline(stat_data, line)) {
100         if (line.find("cpu") == 0 && isdigit(line[3])) {
101             // Split the string using spaces.
102             std::vector<std::string> words = android::base::Split(line, " ");
103             cpu_name = words[0];
104             cpu_num = std::stoi(cpu_name.substr(3));
105 
106             if (cpu_num < kMaxCpus) {
107                 user = std::stoi(words[1]);
108                 nice = std::stoi(words[2]);
109                 system = std::stoi(words[3]);
110                 idle = std::stoi(words[4]);
111 
112                 // Check if the CPU is online by reading the online file.
113                 std::string cpu_online_path =
114                         StringPrintf("%s/%s/%s", kCpuOnlineRoot.data(), cpu_name.c_str(),
115                                      kCpuOnlineFileSuffix.data());
116                 std::string is_online;
117                 if (!android::base::ReadFileToString(cpu_online_path, &is_online)) {
118                     LOG(ERROR) << "Could not open Cpu online file: " << cpu_online_path;
119                     return;
120                 }
121                 is_online = android::base::Trim(is_online);
122 
123                 (*cpu_usages)[cpu_num].name = cpu_name;
124                 (*cpu_usages)[cpu_num].active = user + nice + system;
125                 (*cpu_usages)[cpu_num].total = user + nice + system + idle;
126                 (*cpu_usages)[cpu_num].isOnline = (is_online == "1") ? true : false;
127             } else {
128                 LOG(ERROR) << "Unexpected cpu number: " << words[0];
129                 return;
130             }
131         }
132     }
133 }
134 
parseThermalPathMap(std::string_view prefix)135 std::map<std::string, std::string> parseThermalPathMap(std::string_view prefix) {
136     std::map<std::string, std::string> path_map;
137     std::unique_ptr<DIR, int (*)(DIR *)> dir(opendir(kThermalSensorsRoot.data()), closedir);
138     if (!dir) {
139         return path_map;
140     }
141 
142     // std::filesystem is not available for vendor yet
143     // see discussion: aosp/894015
144     while (struct dirent *dp = readdir(dir.get())) {
145         if (dp->d_type != DT_DIR) {
146             continue;
147         }
148 
149         if (!android::base::StartsWith(dp->d_name, prefix.data())) {
150             continue;
151         }
152 
153         std::string path = android::base::StringPrintf("%s/%s/%s", kThermalSensorsRoot.data(),
154                                                        dp->d_name, kThermalNameFile.data());
155         std::string name;
156         if (!android::base::ReadFileToString(path, &name)) {
157             PLOG(ERROR) << "Failed to read from " << path;
158             continue;
159         }
160 
161         path_map.emplace(
162                 android::base::Trim(name),
163                 android::base::StringPrintf("%s/%s", kThermalSensorsRoot.data(), dp->d_name));
164     }
165 
166     return path_map;
167 }
168 
169 }  // namespace
170 
171 /*
172  * Populate the sensor_name_to_file_map_ map by walking through the file tree,
173  * reading the type file and assigning the temp file path to the map.  If we do
174  * not succeed, abort.
175  */
ThermalHelper(const NotificationCallback & cb)176 ThermalHelper::ThermalHelper(const NotificationCallback &cb)
177     : thermal_watcher_(new ThermalWatcher(
178               std::bind(&ThermalHelper::thermalWatcherCallbackFunc, this, std::placeholders::_1))),
179       cb_(cb),
180       cooling_device_info_map_(ParseCoolingDevice(
181               "/vendor/etc/" +
182               android::base::GetProperty(kConfigProperty.data(), kConfigDefaultFileName.data()))),
183       sensor_info_map_(ParseSensorInfo(
184               "/vendor/etc/" +
185               android::base::GetProperty(kConfigProperty.data(), kConfigDefaultFileName.data()))) {
186     for (auto const &name_status_pair : sensor_info_map_) {
187         sensor_status_map_[name_status_pair.first] = {
188             .severity = ThrottlingSeverity::NONE,
189             .prev_hot_severity = ThrottlingSeverity::NONE,
190             .prev_cold_severity = ThrottlingSeverity::NONE,
191         };
192     }
193 
194     auto tz_map = parseThermalPathMap(kSensorPrefix.data());
195     auto cdev_map = parseThermalPathMap(kCoolingDevicePrefix.data());
196 
197     is_initialized_ = initializeSensorMap(tz_map) && initializeCoolingDevices(cdev_map);
198     if (!is_initialized_) {
199         LOG(FATAL) << "ThermalHAL could not be initialized properly.";
200     }
201     std::set<std::string> cdev_paths;
202     std::transform(cooling_device_info_map_.cbegin(), cooling_device_info_map_.cend(),
203                    std::inserter(cdev_paths, cdev_paths.begin()),
204                    [this](std::pair<std::string, const CoolingType> const &cdev) {
205                        std::string path =
206                                cooling_devices_.getThermalFilePath(std::string_view(cdev.first));
207                        if (!path.empty())
208                            return path;
209                        else
210                            return std::string();
211                    });
212     std::set<std::string> monitored_sensors;
213     std::transform(sensor_info_map_.cbegin(), sensor_info_map_.cend(),
214                    std::inserter(monitored_sensors, monitored_sensors.begin()),
215                    [](std::pair<std::string, SensorInfo> const &sensor) {
216                        if (sensor.second.is_monitor)
217                            return sensor.first;
218                        else
219                            return std::string();
220                    });
221 
222     thermal_watcher_->registerFilesToWatch(monitored_sensors, cdev_paths, initializeTrip(tz_map));
223 
224     // Need start watching after status map initialized
225     is_initialized_ = thermal_watcher_->startWatchingDeviceFiles();
226     if (!is_initialized_) {
227         LOG(FATAL) << "ThermalHAL could not start watching thread properly.";
228     }
229 }
230 
readCoolingDevice(std::string_view cooling_device,CoolingDevice_2_0 * out) const231 bool ThermalHelper::readCoolingDevice(std::string_view cooling_device,
232                                       CoolingDevice_2_0 *out) const {
233     // Read the file.  If the file can't be read temp will be empty string.
234     std::string data;
235 
236     if (!cooling_devices_.readThermalFile(cooling_device, &data)) {
237         LOG(ERROR) << "readCoolingDevice: failed to read cooling_device: " << cooling_device;
238         return false;
239     }
240 
241     const CoolingType &type = cooling_device_info_map_.at(cooling_device.data());
242 
243     out->type = type;
244     out->name = cooling_device.data();
245     out->value = std::stoi(data);
246 
247     return true;
248 }
249 
readTemperature(std::string_view sensor_name,Temperature_1_0 * out) const250 bool ThermalHelper::readTemperature(std::string_view sensor_name, Temperature_1_0 *out) const {
251     // Read the file.  If the file can't be read temp will be empty string.
252     std::string temp;
253 
254     if (!thermal_sensors_.readThermalFile(sensor_name, &temp)) {
255         LOG(ERROR) << "readTemperature: sensor not found: " << sensor_name;
256         return false;
257     }
258 
259     if (temp.empty()) {
260         LOG(ERROR) << "readTemperature: failed to read sensor: " << sensor_name;
261         return false;
262     }
263 
264     const SensorInfo &sensor_info = sensor_info_map_.at(sensor_name.data());
265     TemperatureType_1_0 type =
266         (static_cast<int>(sensor_info.type) > static_cast<int>(TemperatureType_1_0::SKIN))
267             ? TemperatureType_1_0::UNKNOWN
268             : static_cast<TemperatureType_1_0>(sensor_info.type);
269     out->type = type;
270     out->name = sensor_name.data();
271     out->currentValue = std::stof(temp) * sensor_info.multiplier;
272     out->throttlingThreshold =
273         sensor_info.hot_thresholds[static_cast<size_t>(ThrottlingSeverity::SEVERE)];
274     out->shutdownThreshold =
275         sensor_info.hot_thresholds[static_cast<size_t>(ThrottlingSeverity::SHUTDOWN)];
276     out->vrThrottlingThreshold = sensor_info.vr_threshold;
277 
278     return true;
279 }
280 
readTemperature(std::string_view sensor_name,Temperature_2_0 * out,std::pair<ThrottlingSeverity,ThrottlingSeverity> * throtting_status) const281 bool ThermalHelper::readTemperature(
282         std::string_view sensor_name, Temperature_2_0 *out,
283         std::pair<ThrottlingSeverity, ThrottlingSeverity> *throtting_status) const {
284     // Read the file.  If the file can't be read temp will be empty string.
285     std::string temp;
286 
287     if (!thermal_sensors_.readThermalFile(sensor_name, &temp)) {
288         LOG(ERROR) << "readTemperature: sensor not found: " << sensor_name;
289         return false;
290     }
291 
292     if (temp.empty()) {
293         LOG(ERROR) << "readTemperature: failed to read sensor: " << sensor_name;
294         return false;
295     }
296 
297     const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
298     out->type = sensor_info.type;
299     out->name = sensor_name.data();
300     out->value = std::stof(temp) * sensor_info.multiplier;
301 
302     std::pair<ThrottlingSeverity, ThrottlingSeverity> status =
303         std::make_pair(ThrottlingSeverity::NONE, ThrottlingSeverity::NONE);
304     // Only update status if the thermal sensor is being monitored
305     if (sensor_info.is_monitor) {
306         ThrottlingSeverity prev_hot_severity, prev_cold_severity;
307         {
308             // reader lock, readTemperature will be called in Binder call and the watcher thread.
309             std::shared_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
310             prev_hot_severity = sensor_status_map_.at(sensor_name.data()).prev_hot_severity;
311             prev_cold_severity = sensor_status_map_.at(sensor_name.data()).prev_cold_severity;
312         }
313         status = getSeverityFromThresholds(sensor_info.hot_thresholds, sensor_info.cold_thresholds,
314                                            sensor_info.hot_hysteresis, sensor_info.cold_hysteresis,
315                                            prev_hot_severity, prev_cold_severity, out->value);
316     }
317     if (throtting_status) {
318         *throtting_status = status;
319     }
320 
321     out->throttlingStatus = static_cast<size_t>(status.first) > static_cast<size_t>(status.second)
322                                 ? status.first
323                                 : status.second;
324 
325     return true;
326 }
327 
readTemperatureThreshold(std::string_view sensor_name,TemperatureThreshold * out) const328 bool ThermalHelper::readTemperatureThreshold(std::string_view sensor_name,
329                                              TemperatureThreshold *out) const {
330     // Read the file.  If the file can't be read temp will be empty string.
331     std::string temp;
332     std::string path;
333 
334     if (!sensor_info_map_.count(sensor_name.data())) {
335         LOG(ERROR) << __func__ << ": sensor not found: " << sensor_name;
336         return false;
337     }
338 
339     const auto &sensor_info = sensor_info_map_.at(sensor_name.data());
340 
341     out->type = sensor_info.type;
342     out->name = sensor_name.data();
343     out->hotThrottlingThresholds = sensor_info.hot_thresholds;
344     out->coldThrottlingThresholds = sensor_info.cold_thresholds;
345     out->vrThrottlingThreshold = sensor_info.vr_threshold;
346     return true;
347 }
348 
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) const349 std::pair<ThrottlingSeverity, ThrottlingSeverity> ThermalHelper::getSeverityFromThresholds(
350     const ThrottlingArray &hot_thresholds, const ThrottlingArray &cold_thresholds,
351     const ThrottlingArray &hot_hysteresis, const ThrottlingArray &cold_hysteresis,
352     ThrottlingSeverity prev_hot_severity, ThrottlingSeverity prev_cold_severity,
353     float value) const {
354     ThrottlingSeverity ret_hot = ThrottlingSeverity::NONE;
355     ThrottlingSeverity ret_hot_hysteresis = ThrottlingSeverity::NONE;
356     ThrottlingSeverity ret_cold = ThrottlingSeverity::NONE;
357     ThrottlingSeverity ret_cold_hysteresis = ThrottlingSeverity::NONE;
358 
359     // Here we want to control the iteration from high to low, and hidl_enum_range doesn't support
360     // a reverse iterator yet.
361     for (size_t i = static_cast<size_t>(ThrottlingSeverity::SHUTDOWN);
362          i > static_cast<size_t>(ThrottlingSeverity::NONE); --i) {
363         if (!std::isnan(hot_thresholds[i]) && hot_thresholds[i] <= value &&
364             ret_hot == ThrottlingSeverity::NONE) {
365             ret_hot = static_cast<ThrottlingSeverity>(i);
366         }
367         if (!std::isnan(hot_thresholds[i]) && (hot_thresholds[i] - hot_hysteresis[i]) < value &&
368             ret_hot_hysteresis == ThrottlingSeverity::NONE) {
369             ret_hot_hysteresis = static_cast<ThrottlingSeverity>(i);
370         }
371         if (!std::isnan(cold_thresholds[i]) && cold_thresholds[i] >= value &&
372             ret_cold == ThrottlingSeverity::NONE) {
373             ret_cold = static_cast<ThrottlingSeverity>(i);
374         }
375         if (!std::isnan(cold_thresholds[i]) && (cold_thresholds[i] + cold_hysteresis[i]) > value &&
376             ret_cold_hysteresis == ThrottlingSeverity::NONE) {
377             ret_cold_hysteresis = static_cast<ThrottlingSeverity>(i);
378         }
379     }
380     if (static_cast<size_t>(ret_hot) < static_cast<size_t>(prev_hot_severity)) {
381         ret_hot = ret_hot_hysteresis;
382     }
383     if (static_cast<size_t>(ret_cold) < static_cast<size_t>(prev_cold_severity)) {
384         ret_cold = ret_cold_hysteresis;
385     }
386 
387     return std::make_pair(ret_hot, ret_cold);
388 }
389 
initializeSensorMap(const std::map<std::string,std::string> & path_map)390 bool ThermalHelper::initializeSensorMap(const std::map<std::string, std::string> &path_map) {
391     for (const auto &sensor_info_pair : sensor_info_map_) {
392         std::string_view sensor_name = sensor_info_pair.first;
393         if (!path_map.count(sensor_name.data())) {
394             LOG(ERROR) << "Could not find " << sensor_name << " in sysfs";
395             continue;
396         }
397         std::string path = android::base::StringPrintf(
398                 "%s/%s", path_map.at(sensor_name.data()).c_str(), kSensorTempSuffix.data());
399         if (!thermal_sensors_.addThermalFile(sensor_name, path)) {
400             LOG(ERROR) << "Could not add " << sensor_name << "to sensors map";
401         }
402     }
403     if (sensor_info_map_.size() == thermal_sensors_.getNumThermalFiles()) {
404         return true;
405     }
406     return false;
407 }
408 
initializeCoolingDevices(const std::map<std::string,std::string> & path_map)409 bool ThermalHelper::initializeCoolingDevices(const std::map<std::string, std::string> &path_map) {
410     for (const auto &cooling_device_info_pair : cooling_device_info_map_) {
411         std::string_view cooling_device_name = cooling_device_info_pair.first;
412         if (!path_map.count(cooling_device_name.data())) {
413             LOG(ERROR) << "Could not find " << cooling_device_name << " in sysfs";
414             continue;
415         }
416         std::string path = android::base::StringPrintf(
417                 "%s/%s", path_map.at(cooling_device_name.data()).c_str(),
418                 kCoolingDeviceCurStateSuffix.data());
419         if (!cooling_devices_.addThermalFile(cooling_device_name, path)) {
420             LOG(ERROR) << "Could not add " << cooling_device_name << "to cooling device map";
421             continue;
422         }
423     }
424 
425     if (cooling_device_info_map_.size() == cooling_devices_.getNumThermalFiles()) {
426         return true;
427     }
428     return false;
429 }
430 
initializeTrip(const std::map<std::string,std::string> & path_map)431 bool ThermalHelper::initializeTrip(const std::map<std::string, std::string> &path_map) {
432     for (const auto &sensor_info : sensor_info_map_) {
433         if (sensor_info.second.is_monitor) {
434             std::string_view sensor_name = sensor_info.first;
435             std::string_view tz_path = path_map.at(sensor_name.data());
436             std::string tz_policy;
437             std::string path = android::base::StringPrintf("%s/%s", (tz_path.data()),
438                                                            kSensorPolicyFile.data());
439             if (!android::base::ReadFileToString(path, &tz_policy)) {
440                 LOG(ERROR) << sensor_name << " could not open tz policy file:" << path;
441                 return false;
442             }
443             // Check if thermal zone support uevent notify
444             tz_policy = android::base::Trim(tz_policy);
445             if (tz_policy != kUserSpaceSuffix) {
446                 LOG(ERROR) << sensor_name << " does not support uevent notify";
447                 return false;
448             }
449 
450             // Update thermal zone trip point
451             for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
452                 if (!std::isnan(sensor_info.second.hot_thresholds[i]) &&
453                     !std::isnan(sensor_info.second.hot_hysteresis[i])) {
454                     // Update trip_point_0_temp threshold
455                     std::string threshold = std::to_string(static_cast<int>(
456                             sensor_info.second.hot_thresholds[i] / sensor_info.second.multiplier));
457                     path = android::base::StringPrintf("%s/%s", (tz_path.data()),
458                                                        kSensorTripPointTempZeroFile.data());
459                     if (!android::base::WriteStringToFile(threshold, path)) {
460                         LOG(ERROR) << "fail to update " << sensor_name
461                                    << " trip point: " << threshold << path;
462                         return false;
463                     }
464                     // Update trip_point_0_hyst threshold
465                     threshold = std::to_string(static_cast<int>(
466                             sensor_info.second.hot_hysteresis[i] / sensor_info.second.multiplier));
467                     path = android::base::StringPrintf("%s/%s", (tz_path.data()),
468                                                        kSensorTripPointHystZeroFile.data());
469                     if (!android::base::WriteStringToFile(threshold, path)) {
470                         LOG(ERROR) << "fail to update " << sensor_name << "trip hyst" << threshold
471                                    << path;
472                         return false;
473                     }
474                     break;
475                 } else if (i == kThrottlingSeverityCount - 1) {
476                     LOG(ERROR) << sensor_name << ":all thresholds are NAN";
477                     return false;
478                 }
479             }
480         }
481     }
482     return true;
483 }
fillTemperatures(hidl_vec<Temperature_1_0> * temperatures) const484 bool ThermalHelper::fillTemperatures(hidl_vec<Temperature_1_0> *temperatures) const {
485     temperatures->resize(sensor_info_map_.size());
486     int current_index = 0;
487     for (const auto &name_info_pair : sensor_info_map_) {
488         Temperature_1_0 temp;
489 
490         if (readTemperature(name_info_pair.first, &temp)) {
491             (*temperatures)[current_index] = temp;
492         } else {
493             LOG(ERROR) << __func__
494                        << ": error reading temperature for sensor: " << name_info_pair.first;
495             return false;
496         }
497         ++current_index;
498     }
499     return current_index > 0;
500 }
501 
fillCurrentTemperatures(bool filterType,TemperatureType_2_0 type,hidl_vec<Temperature_2_0> * temperatures) const502 bool ThermalHelper::fillCurrentTemperatures(bool filterType, TemperatureType_2_0 type,
503                                             hidl_vec<Temperature_2_0> *temperatures) const {
504     std::vector<Temperature_2_0> ret;
505     for (const auto &name_info_pair : sensor_info_map_) {
506         Temperature_2_0 temp;
507         if (filterType && name_info_pair.second.type != type) {
508             continue;
509         }
510         if (readTemperature(name_info_pair.first, &temp)) {
511             ret.emplace_back(std::move(temp));
512         } else {
513             LOG(ERROR) << __func__
514                        << ": error reading temperature for sensor: " << name_info_pair.first;
515             return false;
516         }
517     }
518     *temperatures = ret;
519     return ret.size() > 0;
520 }
521 
fillTemperatureThresholds(bool filterType,TemperatureType_2_0 type,hidl_vec<TemperatureThreshold> * thresholds) const522 bool ThermalHelper::fillTemperatureThresholds(bool filterType, TemperatureType_2_0 type,
523                                               hidl_vec<TemperatureThreshold> *thresholds) const {
524     std::vector<TemperatureThreshold> ret;
525     for (const auto &name_info_pair : sensor_info_map_) {
526         TemperatureThreshold temp;
527         if (filterType && name_info_pair.second.type != type) {
528             continue;
529         }
530         if (readTemperatureThreshold(name_info_pair.first, &temp)) {
531             ret.emplace_back(std::move(temp));
532         } else {
533             LOG(ERROR) << __func__ << ": error reading temperature threshold for sensor: "
534                        << name_info_pair.first;
535             return false;
536         }
537     }
538     *thresholds = ret;
539     return ret.size() > 0;
540 }
541 
fillCurrentCoolingDevices(bool filterType,CoolingType type,hidl_vec<CoolingDevice_2_0> * cooling_devices) const542 bool ThermalHelper::fillCurrentCoolingDevices(bool filterType, CoolingType type,
543                                               hidl_vec<CoolingDevice_2_0> *cooling_devices) const {
544     std::vector<CoolingDevice_2_0> ret;
545     for (const auto &name_info_pair : cooling_device_info_map_) {
546         CoolingDevice_2_0 value;
547         if (filterType && name_info_pair.second != type) {
548             continue;
549         }
550         if (readCoolingDevice(name_info_pair.first, &value)) {
551             ret.emplace_back(std::move(value));
552         } else {
553             LOG(ERROR) << __func__ << ": error reading cooling device: " << name_info_pair.first;
554             return false;
555         }
556     }
557     *cooling_devices = ret;
558     return ret.size() > 0;
559 }
560 
fillCpuUsages(hidl_vec<CpuUsage> * cpu_usages) const561 bool ThermalHelper::fillCpuUsages(hidl_vec<CpuUsage> *cpu_usages) const {
562     cpu_usages->resize(kMaxCpus);
563     parseCpuUsagesFileAndAssignUsages(cpu_usages);
564     return true;
565 }
566 
567 // This is called in the different thread context and will update sensor_status
568 // uevent_sensors is the set of sensors which trigger uevent from thermal core driver.
thermalWatcherCallbackFunc(const std::set<std::string> & uevent_sensors)569 bool ThermalHelper::thermalWatcherCallbackFunc(const std::set<std::string> &uevent_sensors) {
570     std::vector<Temperature_2_0> temps;
571     bool thermal_triggered = false;
572     for (auto &name_status_pair : sensor_status_map_) {
573         Temperature_2_0 temp;
574         TemperatureThreshold threshold;
575         SensorStatus &sensor_status = name_status_pair.second;
576         const SensorInfo &sensor_info = sensor_info_map_.at(name_status_pair.first);
577         // Only send notification on whitelisted sensors
578         if (!sensor_info.is_monitor) {
579             continue;
580         }
581         // If callback is triggered by uevent, only check the sensors within uevent_sensors
582         if (uevent_sensors.size() != 0 &&
583             uevent_sensors.find(name_status_pair.first) == uevent_sensors.end()) {
584             if (sensor_status.severity != ThrottlingSeverity::NONE) {
585                 thermal_triggered = true;
586             }
587             continue;
588         }
589 
590         std::pair<ThrottlingSeverity, ThrottlingSeverity> throtting_status;
591         if (!readTemperature(name_status_pair.first, &temp, &throtting_status)) {
592             LOG(ERROR) << __func__
593                        << ": error reading temperature for sensor: " << name_status_pair.first;
594             continue;
595         }
596         if (!readTemperatureThreshold(name_status_pair.first, &threshold)) {
597             LOG(ERROR) << __func__ << ": error reading temperature threshold for sensor: "
598                        << name_status_pair.first;
599             continue;
600         }
601 
602         {
603             // writer lock
604             std::unique_lock<std::shared_mutex> _lock(sensor_status_map_mutex_);
605             if (throtting_status.first != sensor_status.prev_hot_severity) {
606                 sensor_status.prev_hot_severity = throtting_status.first;
607             }
608             if (throtting_status.second != sensor_status.prev_cold_severity) {
609                 sensor_status.prev_cold_severity = throtting_status.second;
610             }
611             if (temp.throttlingStatus != sensor_status.severity) {
612                 temps.push_back(temp);
613                 sensor_status.severity = temp.throttlingStatus;
614             }
615         }
616         if (sensor_status.severity != ThrottlingSeverity::NONE) {
617             thermal_triggered = true;
618         }
619     }
620     if (!temps.empty() && cb_) {
621         cb_(temps);
622     }
623 
624     return thermal_triggered;
625 }
626 
627 }  // namespace implementation
628 }  // namespace V2_0
629 }  // namespace thermal
630 }  // namespace hardware
631 }  // namespace android
632