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