1 /*
2  * Copyright (C) 2022 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 #define ATRACE_TAG (ATRACE_TAG_THERMAL | ATRACE_TAG_HAL)
18 
19 #include "Thermal.h"
20 
21 #include <android-base/file.h>
22 #include <android-base/logging.h>
23 #include <utils/Trace.h>
24 
25 namespace aidl {
26 namespace android {
27 namespace hardware {
28 namespace thermal {
29 namespace implementation {
30 
31 namespace {
32 
initErrorStatus()33 ndk::ScopedAStatus initErrorStatus() {
34     return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE,
35                                                             "ThermalHAL not initialized properly.");
36 }
37 
readErrorStatus()38 ndk::ScopedAStatus readErrorStatus() {
39     return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
40             EX_ILLEGAL_STATE, "ThermalHal cannot read any sensor data");
41 }
42 
interfacesEqual(const std::shared_ptr<::ndk::ICInterface> left,const std::shared_ptr<::ndk::ICInterface> right)43 bool interfacesEqual(const std::shared_ptr<::ndk::ICInterface> left,
44                      const std::shared_ptr<::ndk::ICInterface> right) {
45     if (left == nullptr || right == nullptr || !left->isRemote() || !right->isRemote()) {
46         return left == right;
47     }
48     return left->asBinder() == right->asBinder();
49 }
50 
51 }  // namespace
52 
Thermal()53 Thermal::Thermal() {
54     thermal_helper_ = std::make_shared<ThermalHelperImpl>(
55             std::bind(&Thermal::sendThermalChangedCallback, this, std::placeholders::_1));
56 }
57 
Thermal(const std::shared_ptr<ThermalHelper> & helper)58 Thermal::Thermal(const std::shared_ptr<ThermalHelper> &helper) {
59     thermal_helper_ = helper;
60 }
61 
getTemperatures(std::vector<Temperature> * _aidl_return)62 ndk::ScopedAStatus Thermal::getTemperatures(std::vector<Temperature> *_aidl_return) {
63     return getFilteredTemperatures(false, TemperatureType::UNKNOWN, _aidl_return);
64 }
65 
getTemperaturesWithType(TemperatureType type,std::vector<Temperature> * _aidl_return)66 ndk::ScopedAStatus Thermal::getTemperaturesWithType(TemperatureType type,
67                                                     std::vector<Temperature> *_aidl_return) {
68     return getFilteredTemperatures(true, type, _aidl_return);
69 }
70 
getFilteredTemperatures(bool filterType,TemperatureType type,std::vector<Temperature> * _aidl_return)71 ndk::ScopedAStatus Thermal::getFilteredTemperatures(bool filterType, TemperatureType type,
72                                                     std::vector<Temperature> *_aidl_return) {
73     *_aidl_return = {};
74     if (!thermal_helper_->isInitializedOk()) {
75         return initErrorStatus();
76     }
77     if (!thermal_helper_->fillCurrentTemperatures(filterType, false, type, _aidl_return)) {
78         return readErrorStatus();
79     }
80     return ndk::ScopedAStatus::ok();
81 }
82 
getCoolingDevices(std::vector<CoolingDevice> * _aidl_return)83 ndk::ScopedAStatus Thermal::getCoolingDevices(std::vector<CoolingDevice> *_aidl_return) {
84     return getFilteredCoolingDevices(false, CoolingType::BATTERY, _aidl_return);
85 }
86 
getCoolingDevicesWithType(CoolingType type,std::vector<CoolingDevice> * _aidl_return)87 ndk::ScopedAStatus Thermal::getCoolingDevicesWithType(CoolingType type,
88                                                       std::vector<CoolingDevice> *_aidl_return) {
89     return getFilteredCoolingDevices(true, type, _aidl_return);
90 }
91 
getFilteredCoolingDevices(bool filterType,CoolingType type,std::vector<CoolingDevice> * _aidl_return)92 ndk::ScopedAStatus Thermal::getFilteredCoolingDevices(bool filterType, CoolingType type,
93                                                       std::vector<CoolingDevice> *_aidl_return) {
94     *_aidl_return = {};
95     if (!thermal_helper_->isInitializedOk()) {
96         return initErrorStatus();
97     }
98     if (!thermal_helper_->fillCurrentCoolingDevices(filterType, type, _aidl_return)) {
99         return readErrorStatus();
100     }
101     return ndk::ScopedAStatus::ok();
102 }
103 
getTemperatureThresholds(std::vector<TemperatureThreshold> * _aidl_return)104 ndk::ScopedAStatus Thermal::getTemperatureThresholds(
105         std::vector<TemperatureThreshold> *_aidl_return) {
106     *_aidl_return = {};
107     return getFilteredTemperatureThresholds(false, TemperatureType::UNKNOWN, _aidl_return);
108 }
109 
getTemperatureThresholdsWithType(TemperatureType type,std::vector<TemperatureThreshold> * _aidl_return)110 ndk::ScopedAStatus Thermal::getTemperatureThresholdsWithType(
111         TemperatureType type, std::vector<TemperatureThreshold> *_aidl_return) {
112     return getFilteredTemperatureThresholds(true, type, _aidl_return);
113 }
114 
getFilteredTemperatureThresholds(bool filterType,TemperatureType type,std::vector<TemperatureThreshold> * _aidl_return)115 ndk::ScopedAStatus Thermal::getFilteredTemperatureThresholds(
116         bool filterType, TemperatureType type, std::vector<TemperatureThreshold> *_aidl_return) {
117     *_aidl_return = {};
118     if (!thermal_helper_->isInitializedOk()) {
119         return initErrorStatus();
120     }
121     if (!thermal_helper_->fillTemperatureThresholds(filterType, type, _aidl_return)) {
122         return readErrorStatus();
123     }
124     return ndk::ScopedAStatus::ok();
125 }
126 
registerThermalChangedCallback(const std::shared_ptr<IThermalChangedCallback> & callback)127 ndk::ScopedAStatus Thermal::registerThermalChangedCallback(
128         const std::shared_ptr<IThermalChangedCallback> &callback) {
129     ATRACE_CALL();
130     return registerThermalChangedCallback(callback, false, TemperatureType::UNKNOWN);
131 }
132 
registerThermalChangedCallbackWithType(const std::shared_ptr<IThermalChangedCallback> & callback,TemperatureType type)133 ndk::ScopedAStatus Thermal::registerThermalChangedCallbackWithType(
134         const std::shared_ptr<IThermalChangedCallback> &callback, TemperatureType type) {
135     ATRACE_CALL();
136     return registerThermalChangedCallback(callback, true, type);
137 }
138 
unregisterThermalChangedCallback(const std::shared_ptr<IThermalChangedCallback> & callback)139 ndk::ScopedAStatus Thermal::unregisterThermalChangedCallback(
140         const std::shared_ptr<IThermalChangedCallback> &callback) {
141     if (callback == nullptr) {
142         return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
143                                                                 "Invalid nullptr callback");
144     }
145     bool removed = false;
146     std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
147     callbacks_.erase(
148             std::remove_if(
149                     callbacks_.begin(), callbacks_.end(),
150                     [&](const CallbackSetting &c) {
151                         if (interfacesEqual(c.callback, callback)) {
152                             LOG(INFO)
153                                     << "a callback has been unregistered to ThermalHAL, isFilter: "
154                                     << c.is_filter_type << " Type: " << toString(c.type);
155                             removed = true;
156                             return true;
157                         }
158                         return false;
159                     }),
160             callbacks_.end());
161     if (!removed) {
162         return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
163                                                                 "Callback wasn't registered");
164     }
165     return ndk::ScopedAStatus::ok();
166 }
167 
registerThermalChangedCallback(const std::shared_ptr<IThermalChangedCallback> & callback,bool filterType,TemperatureType type)168 ndk::ScopedAStatus Thermal::registerThermalChangedCallback(
169         const std::shared_ptr<IThermalChangedCallback> &callback, bool filterType,
170         TemperatureType type) {
171     ATRACE_CALL();
172     if (callback == nullptr) {
173         return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
174                                                                 "Invalid nullptr callback");
175     }
176     if (!thermal_helper_->isInitializedOk()) {
177         return initErrorStatus();
178     }
179     std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
180     if (std::any_of(callbacks_.begin(), callbacks_.end(), [&](const CallbackSetting &c) {
181             return interfacesEqual(c.callback, callback);
182         })) {
183         return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
184                                                                 "Callback already registered");
185     }
186     auto c = callbacks_.emplace_back(callback, filterType, type);
187     LOG(INFO) << "a callback has been registered to ThermalHAL, isFilter: " << c.is_filter_type
188               << " Type: " << toString(c.type);
189     // Send notification right away after successful thermal callback registration
190     std::function<void()> handler = [this, c, filterType, type]() {
191         std::vector<Temperature> temperatures;
192         if (thermal_helper_->fillCurrentTemperatures(filterType, true, type, &temperatures)) {
193             std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
194             auto it = std::find_if(callbacks_.begin(), callbacks_.end(),
195                                    [&](const CallbackSetting &cc) {
196                                        return interfacesEqual(c.callback, cc.callback);
197                                    });
198             if (it != callbacks_.end()) {
199                 if (AIBinder_isAlive(c.callback->asBinder().get())) {
200                     for (const auto &t : temperatures) {
201                         if (!filterType || t.type == type) {
202                             LOG(INFO) << "Sending notification: "
203                                       << " Type: " << toString(t.type) << " Name: " << t.name
204                                       << " CurrentValue: " << t.value
205                                       << " ThrottlingStatus: " << toString(t.throttlingStatus);
206                             c.callback->notifyThrottling(t);
207                         }
208                     }
209                 } else {
210                     callbacks_.erase(it);
211                 }
212             }
213         }
214     };
215     looper_.addEvent(Looper::Event{handler});
216     return ndk::ScopedAStatus::ok();
217 }
218 
sendThermalChangedCallback(const Temperature & t)219 void Thermal::sendThermalChangedCallback(const Temperature &t) {
220     ATRACE_CALL();
221     std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
222     LOG(VERBOSE) << "Sending notification: "
223                  << " Type: " << toString(t.type) << " Name: " << t.name
224                  << " CurrentValue: " << t.value
225                  << " ThrottlingStatus: " << toString(t.throttlingStatus);
226 
227     callbacks_.erase(std::remove_if(callbacks_.begin(), callbacks_.end(),
228                                     [&](const CallbackSetting &c) {
229                                         if (!c.is_filter_type || t.type == c.type) {
230                                             ::ndk::ScopedAStatus ret =
231                                                     c.callback->notifyThrottling(t);
232                                             if (!ret.isOk()) {
233                                                 LOG(ERROR) << "a Thermal callback is dead, removed "
234                                                               "from callback list.";
235                                                 return true;
236                                             }
237                                             return false;
238                                         }
239                                         return false;
240                                     }),
241                      callbacks_.end());
242 }
243 
registerCoolingDeviceChangedCallbackWithType(const std::shared_ptr<ICoolingDeviceChangedCallback> & callback,CoolingType type)244 ndk::ScopedAStatus Thermal::registerCoolingDeviceChangedCallbackWithType(
245         const std::shared_ptr<ICoolingDeviceChangedCallback> &callback, CoolingType type) {
246     ATRACE_CALL();
247 
248     if (callback == nullptr) {
249         return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
250                                                                 "Invalid nullptr callback");
251     }
252 
253     if (!thermal_helper_->isInitializedOk()) {
254         return initErrorStatus();
255     }
256 
257     std::lock_guard<std::mutex> _lock(cdev_callback_mutex_);
258     if (std::any_of(cdev_callbacks_.begin(), cdev_callbacks_.end(),
259                     [&](const CoolingDeviceCallbackSetting &c) {
260                         return interfacesEqual(c.callback, callback);
261                     })) {
262         return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
263                                                                 "Callback already registered");
264     }
265     cdev_callbacks_.emplace_back(callback, true, type);
266 
267     // b/315858553 to develope the callback
268     LOG(INFO) << __func__ << ":" << toString(type) << " is under development";
269 
270     return ndk::ScopedAStatus::ok();
271 }
272 
unregisterCoolingDeviceChangedCallback(const std::shared_ptr<ICoolingDeviceChangedCallback> & callback)273 ndk::ScopedAStatus Thermal::unregisterCoolingDeviceChangedCallback(
274         const std::shared_ptr<ICoolingDeviceChangedCallback> &callback) {
275     ATRACE_CALL();
276 
277     if (callback == nullptr) {
278         return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
279                                                                 "Invalid nullptr callback");
280     }
281 
282     bool removed = false;
283     std::lock_guard<std::mutex> _lock(cdev_callback_mutex_);
284     cdev_callbacks_.erase(
285             std::remove_if(
286                     cdev_callbacks_.begin(), cdev_callbacks_.end(),
287                     [&](const CoolingDeviceCallbackSetting &c) {
288                         if (interfacesEqual(c.callback, callback)) {
289                             LOG(INFO)
290                                     << "a callback has been unregistered to ThermalHAL, isFilter: "
291                                     << c.is_filter_type << " Type: " << toString(c.type);
292                             removed = true;
293                             return true;
294                         }
295                         return false;
296                     }),
297             cdev_callbacks_.end());
298 
299     if (!removed) {
300         return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
301                                                                 "Callback wasn't registered");
302     }
303 
304     // b/315858553 to develope the callback
305     LOG(INFO) << __func__ << " is under development";
306 
307     return ndk::ScopedAStatus::ok();
308 }
309 
forecastSkinTemperature(int32_t,float *)310 ndk::ScopedAStatus Thermal::forecastSkinTemperature(int32_t, float *) {
311     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
312 }
313 
dumpVirtualSensorInfo(std::ostringstream * dump_buf)314 void Thermal::dumpVirtualSensorInfo(std::ostringstream *dump_buf) {
315     *dump_buf << "getVirtualSensorInfo:" << std::endl;
316     const auto &map = thermal_helper_->GetSensorInfoMap();
317     for (const auto &sensor_info_pair : map) {
318         if (sensor_info_pair.second.virtual_sensor_info != nullptr) {
319             *dump_buf << " Name: " << sensor_info_pair.first << std::endl;
320             *dump_buf << "  LinkedSensorName: [";
321             for (size_t i = 0;
322                  i < sensor_info_pair.second.virtual_sensor_info->linked_sensors.size(); i++) {
323                 *dump_buf << sensor_info_pair.second.virtual_sensor_info->linked_sensors[i] << " ";
324             }
325             *dump_buf << "]" << std::endl;
326             *dump_buf << "  LinkedSensorCoefficient: [";
327             for (size_t i = 0; i < sensor_info_pair.second.virtual_sensor_info->coefficients.size();
328                  i++) {
329                 *dump_buf << sensor_info_pair.second.virtual_sensor_info->coefficients[i] << " ";
330             }
331             *dump_buf << "]" << std::endl;
332             *dump_buf << "  Offset: " << sensor_info_pair.second.virtual_sensor_info->offset
333                       << std::endl;
334             *dump_buf << "  Trigger Sensor: ";
335             if (sensor_info_pair.second.virtual_sensor_info->trigger_sensors.empty()) {
336                 *dump_buf << "N/A" << std::endl;
337             } else {
338                 for (size_t i = 0;
339                      i < sensor_info_pair.second.virtual_sensor_info->trigger_sensors.size(); i++) {
340                     *dump_buf << sensor_info_pair.second.virtual_sensor_info->trigger_sensors[i]
341                               << " ";
342                 }
343                 *dump_buf << std::endl;
344             }
345             *dump_buf << "  Formula: ";
346             switch (sensor_info_pair.second.virtual_sensor_info->formula) {
347                 case FormulaOption::COUNT_THRESHOLD:
348                     *dump_buf << "COUNT_THRESHOLD";
349                     break;
350                 case FormulaOption::WEIGHTED_AVG:
351                     *dump_buf << "WEIGHTED_AVG";
352                     break;
353                 case FormulaOption::MAXIMUM:
354                     *dump_buf << "MAXIMUM";
355                     break;
356                 case FormulaOption::MINIMUM:
357                     *dump_buf << "MINIMUM";
358                     break;
359                 default:
360                     *dump_buf << "NONE";
361                     break;
362             }
363 
364             *dump_buf << std::endl;
365         }
366     }
367 }
368 
dumpVtEstimatorInfo(std::ostringstream * dump_buf)369 void Thermal::dumpVtEstimatorInfo(std::ostringstream *dump_buf) {
370     *dump_buf << "getVtEstimatorInfo:" << std::endl;
371     const auto &map = thermal_helper_->GetSensorInfoMap();
372     for (const auto &name_info_pair : map) {
373         thermal_helper_->dumpVtEstimatorStatus(name_info_pair.first, dump_buf);
374     }
375 }
376 
dumpThrottlingInfo(std::ostringstream * dump_buf)377 void Thermal::dumpThrottlingInfo(std::ostringstream *dump_buf) {
378     *dump_buf << "getThrottlingInfo:" << std::endl;
379     const auto &map = thermal_helper_->GetSensorInfoMap();
380     const auto &thermal_throttling_status_map = thermal_helper_->GetThermalThrottlingStatusMap();
381     for (const auto &name_info_pair : map) {
382         if (name_info_pair.second.throttling_info == nullptr) {
383             continue;
384         }
385         if (name_info_pair.second.throttling_info->binded_cdev_info_map.size()) {
386             if (thermal_throttling_status_map.find(name_info_pair.first) ==
387                 thermal_throttling_status_map.end()) {
388                 continue;
389             }
390             *dump_buf << " Name: " << name_info_pair.first << std::endl;
391             if (thermal_throttling_status_map.at(name_info_pair.first)
392                         .pid_power_budget_map.size()) {
393                 *dump_buf << "  PID Info:" << std::endl;
394                 *dump_buf << "   K_po: [";
395                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
396                     *dump_buf << name_info_pair.second.throttling_info->k_po[i] << " ";
397                 }
398                 *dump_buf << "]" << std::endl;
399                 *dump_buf << "   K_pu: [";
400                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
401                     *dump_buf << name_info_pair.second.throttling_info->k_pu[i] << " ";
402                 }
403                 *dump_buf << "]" << std::endl;
404                 *dump_buf << "   K_io: [";
405                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
406                     *dump_buf << name_info_pair.second.throttling_info->k_io[i] << " ";
407                 }
408                 *dump_buf << "]" << std::endl;
409                 *dump_buf << "   K_iu: [";
410                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
411                     *dump_buf << name_info_pair.second.throttling_info->k_iu[i] << " ";
412                 }
413                 *dump_buf << "]" << std::endl;
414                 *dump_buf << "   K_d: [";
415                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
416                     *dump_buf << name_info_pair.second.throttling_info->k_d[i] << " ";
417                 }
418                 *dump_buf << "]" << std::endl;
419                 *dump_buf << "   i_max: [";
420                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
421                     *dump_buf << name_info_pair.second.throttling_info->i_max[i] << " ";
422                 }
423                 *dump_buf << "]" << std::endl;
424                 *dump_buf << "   max_alloc_power: [";
425                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
426                     *dump_buf << name_info_pair.second.throttling_info->max_alloc_power[i] << " ";
427                 }
428                 *dump_buf << "]" << std::endl;
429                 *dump_buf << "   min_alloc_power: [";
430                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
431                     *dump_buf << name_info_pair.second.throttling_info->min_alloc_power[i] << " ";
432                 }
433                 *dump_buf << "]" << std::endl;
434                 *dump_buf << "   s_power: [";
435                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
436                     *dump_buf << name_info_pair.second.throttling_info->s_power[i] << " ";
437                 }
438                 *dump_buf << "]" << std::endl;
439                 *dump_buf << "   i_cutoff: [";
440                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
441                     *dump_buf << name_info_pair.second.throttling_info->i_cutoff[i] << " ";
442                 }
443                 *dump_buf << "]" << std::endl;
444             }
445             const auto &profile = thermal_throttling_status_map.at(name_info_pair.first).profile;
446             *dump_buf << "  Binded CDEV Info:" << (profile.empty() ? "default" : profile)
447                       << std::endl;
448 
449             for (const auto &binded_cdev_info_pair :
450                  name_info_pair.second.throttling_info->profile_map.count(profile)
451                          ? name_info_pair.second.throttling_info->profile_map.at(profile)
452                          : name_info_pair.second.throttling_info->binded_cdev_info_map) {
453                 *dump_buf << "   Cooling device name: " << binded_cdev_info_pair.first << std::endl;
454                 if (thermal_throttling_status_map.at(name_info_pair.first)
455                             .pid_power_budget_map.size()) {
456                     *dump_buf << "    WeightForPID: [";
457                     for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
458                         *dump_buf << binded_cdev_info_pair.second.cdev_weight_for_pid[i] << " ";
459                     }
460                     *dump_buf << "]" << std::endl;
461                 }
462                 *dump_buf << "    Ceiling: [";
463                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
464                     *dump_buf << binded_cdev_info_pair.second.cdev_ceiling[i] << " ";
465                 }
466                 *dump_buf << "]" << std::endl;
467                 *dump_buf << "    Hard limit: [";
468                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
469                     *dump_buf << binded_cdev_info_pair.second.limit_info[i] << " ";
470                 }
471                 *dump_buf << "]" << std::endl;
472 
473                 if (!binded_cdev_info_pair.second.power_rail.empty()) {
474                     *dump_buf << "    Binded power rail: "
475                               << binded_cdev_info_pair.second.power_rail << std::endl;
476                     *dump_buf << "    Power threshold: [";
477                     for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
478                         *dump_buf << binded_cdev_info_pair.second.power_thresholds[i] << " ";
479                     }
480                     *dump_buf << "]" << std::endl;
481                     *dump_buf << "    Floor with PowerLink: [";
482                     for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
483                         *dump_buf << binded_cdev_info_pair.second.cdev_floor_with_power_link[i]
484                                   << " ";
485                     }
486                     *dump_buf << "]" << std::endl;
487                     *dump_buf << "    Release logic: ";
488                     switch (binded_cdev_info_pair.second.release_logic) {
489                         case ReleaseLogic::INCREASE:
490                             *dump_buf << "INCREASE";
491                             break;
492                         case ReleaseLogic::DECREASE:
493                             *dump_buf << "DECREASE";
494                             break;
495                         case ReleaseLogic::STEPWISE:
496                             *dump_buf << "STEPWISE";
497                             break;
498                         case ReleaseLogic::RELEASE_TO_FLOOR:
499                             *dump_buf << "RELEASE_TO_FLOOR";
500                             break;
501                         default:
502                             *dump_buf << "NONE";
503                             break;
504                     }
505                     *dump_buf << std::endl;
506                     *dump_buf << "    high_power_check: " << std::boolalpha
507                               << binded_cdev_info_pair.second.high_power_check << std::endl;
508                     *dump_buf << "    throttling_with_power_link: " << std::boolalpha
509                               << binded_cdev_info_pair.second.throttling_with_power_link
510                               << std::endl;
511                 }
512             }
513         }
514     }
515 }
516 
dumpThrottlingRequestStatus(std::ostringstream * dump_buf)517 void Thermal::dumpThrottlingRequestStatus(std::ostringstream *dump_buf) {
518     const auto &thermal_throttling_status_map = thermal_helper_->GetThermalThrottlingStatusMap();
519     if (!thermal_throttling_status_map.size()) {
520         return;
521     }
522     *dump_buf << "getThrottlingRequestStatus:" << std::endl;
523     for (const auto &thermal_throttling_status_pair : thermal_throttling_status_map) {
524         *dump_buf << " Name: " << thermal_throttling_status_pair.first << std::endl;
525         if (thermal_throttling_status_pair.second.pid_power_budget_map.size()) {
526             *dump_buf << "  power budget request state" << std::endl;
527             for (const auto &request_pair :
528                  thermal_throttling_status_pair.second.pid_power_budget_map) {
529                 *dump_buf << "   " << request_pair.first << ": " << request_pair.second
530                           << std::endl;
531             }
532         }
533         if (thermal_throttling_status_pair.second.pid_cdev_request_map.size()) {
534             *dump_buf << "  pid cdev request state" << std::endl;
535             for (const auto &request_pair :
536                  thermal_throttling_status_pair.second.pid_cdev_request_map) {
537                 *dump_buf << "   " << request_pair.first << ": " << request_pair.second
538                           << std::endl;
539             }
540         }
541         if (thermal_throttling_status_pair.second.hardlimit_cdev_request_map.size()) {
542             *dump_buf << "  hard limit cdev request state" << std::endl;
543             for (const auto &request_pair :
544                  thermal_throttling_status_pair.second.hardlimit_cdev_request_map) {
545                 *dump_buf << "   " << request_pair.first << ": " << request_pair.second
546                           << std::endl;
547             }
548         }
549         if (thermal_throttling_status_pair.second.throttling_release_map.size()) {
550             *dump_buf << "  cdev release state" << std::endl;
551             for (const auto &request_pair :
552                  thermal_throttling_status_pair.second.throttling_release_map) {
553                 *dump_buf << "   " << request_pair.first << ": " << request_pair.second
554                           << std::endl;
555             }
556         }
557         if (thermal_throttling_status_pair.second.cdev_status_map.size()) {
558             *dump_buf << "  cdev request state" << std::endl;
559             for (const auto &request_pair : thermal_throttling_status_pair.second.cdev_status_map) {
560                 *dump_buf << "   " << request_pair.first << ": " << request_pair.second
561                           << std::endl;
562             }
563         }
564     }
565 }
566 
dumpPowerRailInfo(std::ostringstream * dump_buf)567 void Thermal::dumpPowerRailInfo(std::ostringstream *dump_buf) {
568     const auto &power_rail_info_map = thermal_helper_->GetPowerRailInfoMap();
569     const auto &power_status_map = thermal_helper_->GetPowerStatusMap();
570 
571     *dump_buf << "getPowerRailInfo:" << std::endl;
572     for (const auto &power_rail_pair : power_rail_info_map) {
573         *dump_buf << " Power Rail: " << power_rail_pair.first << std::endl;
574         *dump_buf << "  Power Sample Count: " << power_rail_pair.second.power_sample_count
575                   << std::endl;
576         *dump_buf << "  Power Sample Delay: " << power_rail_pair.second.power_sample_delay.count()
577                   << std::endl;
578         if (power_status_map.count(power_rail_pair.first)) {
579             auto power_history = power_status_map.at(power_rail_pair.first).power_history;
580             *dump_buf << "  Last Updated AVG Power: "
581                       << power_status_map.at(power_rail_pair.first).last_updated_avg_power << " mW"
582                       << std::endl;
583             if (power_rail_pair.second.virtual_power_rail_info != nullptr) {
584                 *dump_buf << "  Formula=";
585                 switch (power_rail_pair.second.virtual_power_rail_info->formula) {
586                     case FormulaOption::COUNT_THRESHOLD:
587                         *dump_buf << "COUNT_THRESHOLD";
588                         break;
589                     case FormulaOption::WEIGHTED_AVG:
590                         *dump_buf << "WEIGHTED_AVG";
591                         break;
592                     case FormulaOption::MAXIMUM:
593                         *dump_buf << "MAXIMUM";
594                         break;
595                     case FormulaOption::MINIMUM:
596                         *dump_buf << "MINIMUM";
597                         break;
598                     default:
599                         *dump_buf << "NONE";
600                         break;
601                 }
602                 *dump_buf << std::endl;
603             }
604             for (size_t i = 0; i < power_history.size(); ++i) {
605                 if (power_rail_pair.second.virtual_power_rail_info != nullptr) {
606                     *dump_buf
607                             << "  Linked power rail "
608                             << power_rail_pair.second.virtual_power_rail_info->linked_power_rails[i]
609                             << std::endl;
610                     *dump_buf << "   Coefficient="
611                               << power_rail_pair.second.virtual_power_rail_info->coefficients[i]
612                               << std::endl;
613                     *dump_buf << "   Power Samples: ";
614                 } else {
615                     *dump_buf << "  Power Samples: ";
616                 }
617                 while (power_history[i].size() > 0) {
618                     const auto power_sample = power_history[i].front();
619                     power_history[i].pop();
620                     *dump_buf << "(T=" << power_sample.duration
621                               << ", uWs=" << power_sample.energy_counter << ") ";
622                 }
623                 *dump_buf << std::endl;
624             }
625         }
626     }
627 }
628 
dumpStatsRecord(std::ostringstream * dump_buf,const StatsRecord & stats_record,std::string_view line_prefix)629 void Thermal::dumpStatsRecord(std::ostringstream *dump_buf, const StatsRecord &stats_record,
630                               std::string_view line_prefix) {
631     const auto now = boot_clock::now();
632     *dump_buf << line_prefix << "Time Since Last Stats Report: "
633               << std::chrono::duration_cast<std::chrono::minutes>(
634                          now - stats_record.last_stats_report_time)
635                          .count()
636               << " mins" << std::endl;
637     *dump_buf << line_prefix << "Time in State ms: [";
638     for (const auto &time_in_state : stats_record.time_in_state_ms) {
639         *dump_buf << time_in_state.count() << " ";
640     }
641     *dump_buf << "]" << std::endl;
642 }
643 
dumpThermalStats(std::ostringstream * dump_buf)644 void Thermal::dumpThermalStats(std::ostringstream *dump_buf) {
645     *dump_buf << "getThermalStatsInfo:" << std::endl;
646     *dump_buf << " Sensor Temp Stats Info:" << std::endl;
647     const auto &sensor_temp_stats_map_ = thermal_helper_->GetSensorTempStatsSnapshot();
648     const std::string sensor_temp_stats_line_prefix("    ");
649     for (const auto &sensor_temp_stats_pair : sensor_temp_stats_map_) {
650         *dump_buf << "  Sensor Name: " << sensor_temp_stats_pair.first << std::endl;
651         const auto &sensor_temp_stats = sensor_temp_stats_pair.second;
652         *dump_buf << "   Max Temp: " << sensor_temp_stats.max_temp << ", TimeStamp: "
653                   << system_clock::to_time_t(sensor_temp_stats.max_temp_timestamp) << std::endl;
654         *dump_buf << "   Min Temp: " << sensor_temp_stats.min_temp << ", TimeStamp: "
655                   << system_clock::to_time_t(sensor_temp_stats.min_temp_timestamp) << std::endl;
656         for (const auto &stats_by_threshold : sensor_temp_stats.stats_by_custom_threshold) {
657             *dump_buf << "   Record by Threshold: [";
658             for (const auto &threshold : stats_by_threshold.thresholds) {
659                 *dump_buf << threshold << " ";
660             }
661             *dump_buf << "]" << std::endl;
662             if (stats_by_threshold.logging_name.has_value()) {
663                 *dump_buf << "    Logging Name: " << stats_by_threshold.logging_name.value()
664                           << std::endl;
665             }
666             dumpStatsRecord(dump_buf, stats_by_threshold.stats_record,
667                             sensor_temp_stats_line_prefix);
668         }
669 
670         if (sensor_temp_stats.stats_by_default_threshold.has_value()) {
671             *dump_buf << "   Record by Severity:" << std::endl;
672             dumpStatsRecord(dump_buf, sensor_temp_stats.stats_by_default_threshold.value(),
673                             sensor_temp_stats_line_prefix);
674         }
675     }
676     *dump_buf << " Sensor Cdev Request Stats Info:" << std::endl;
677     const auto &sensor_cdev_request_stats_map_ =
678             thermal_helper_->GetSensorCoolingDeviceRequestStatsSnapshot();
679     const std::string sensor_cdev_request_stats_line_prefix("     ");
680     for (const auto &sensor_cdev_request_stats_pair : sensor_cdev_request_stats_map_) {
681         *dump_buf << "  Sensor Name: " << sensor_cdev_request_stats_pair.first << std::endl;
682         for (const auto &cdev_request_stats_pair : sensor_cdev_request_stats_pair.second) {
683             *dump_buf << "   Cooling Device Name: " << cdev_request_stats_pair.first << std::endl;
684             const auto &request_stats = cdev_request_stats_pair.second;
685             for (const auto &stats_by_threshold : request_stats.stats_by_custom_threshold) {
686                 *dump_buf << "    Record by Threshold: [";
687                 for (const auto &threshold : stats_by_threshold.thresholds) {
688                     *dump_buf << threshold << " ";
689                 }
690                 *dump_buf << "]" << std::endl;
691                 if (stats_by_threshold.logging_name.has_value()) {
692                     *dump_buf << "     Logging Name: " << stats_by_threshold.logging_name.value()
693                               << std::endl;
694                 }
695                 dumpStatsRecord(dump_buf, stats_by_threshold.stats_record,
696                                 sensor_cdev_request_stats_line_prefix);
697             }
698             if (request_stats.stats_by_default_threshold.has_value()) {
699                 *dump_buf << "    Record by All State" << std::endl;
700                 dumpStatsRecord(dump_buf, request_stats.stats_by_default_threshold.value(),
701                                 sensor_cdev_request_stats_line_prefix);
702             }
703         }
704     }
705 }
706 
dumpThermalData(int fd,const char ** args,uint32_t numArgs)707 void Thermal::dumpThermalData(int fd, const char **args, uint32_t numArgs) {
708     std::ostringstream dump_buf;
709 
710     if (!thermal_helper_->isInitializedOk()) {
711         dump_buf << "ThermalHAL not initialized properly." << std::endl;
712     } else if (numArgs == 0 || std::string(args[0]) == "-a") {
713         const auto &sensor_status_map = thermal_helper_->GetSensorStatusMap();
714         {
715             dump_buf << "getCachedTemperatures:" << std::endl;
716             boot_clock::time_point now = boot_clock::now();
717             for (const auto &sensor_status_pair : sensor_status_map) {
718                 if ((sensor_status_pair.second.thermal_cached.timestamp) ==
719                     boot_clock::time_point::min()) {
720                     continue;
721                 }
722                 dump_buf << " Name: " << sensor_status_pair.first
723                          << " CachedValue: " << sensor_status_pair.second.thermal_cached.temp
724                          << " TimeToCache: "
725                          << std::chrono::duration_cast<std::chrono::milliseconds>(
726                                     now - sensor_status_pair.second.thermal_cached.timestamp)
727                                     .count()
728                          << "ms" << std::endl;
729             }
730         }
731         {
732             dump_buf << "getEmulSettings:" << std::endl;
733             for (const auto &sensor_status_pair : sensor_status_map) {
734                 if (sensor_status_pair.second.override_status.emul_temp == nullptr) {
735                     continue;
736                 }
737                 dump_buf << " Name: " << sensor_status_pair.first << " EmulTemp: "
738                          << sensor_status_pair.second.override_status.emul_temp->temp
739                          << " EmulSeverity: "
740                          << sensor_status_pair.second.override_status.emul_temp->severity
741                          << " maxThrottling: " << std::boolalpha
742                          << sensor_status_pair.second.override_status.max_throttling << std::endl;
743             }
744         }
745         {
746             const auto &map = thermal_helper_->GetSensorInfoMap();
747             dump_buf << "getCurrentTemperatures:" << std::endl;
748             Temperature temp_2_0;
749             for (const auto &name_info_pair : map) {
750                 thermal_helper_->readTemperature(name_info_pair.first, &temp_2_0, true);
751                 dump_buf << " Type: " << toString(temp_2_0.type)
752                          << " Name: " << name_info_pair.first << " CurrentValue: " << temp_2_0.value
753                          << " ThrottlingStatus: " << toString(temp_2_0.throttlingStatus)
754                          << std::endl;
755             }
756             dump_buf << "getTemperatureThresholds:" << std::endl;
757             for (const auto &name_info_pair : map) {
758                 if (!name_info_pair.second.is_watch) {
759                     continue;
760                 }
761                 dump_buf << " Type: " << toString(name_info_pair.second.type)
762                          << " Name: " << name_info_pair.first;
763                 dump_buf << " hotThrottlingThreshold: [";
764                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
765                     dump_buf << name_info_pair.second.hot_thresholds[i] << " ";
766                 }
767                 dump_buf << "] coldThrottlingThreshold: [";
768                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
769                     dump_buf << name_info_pair.second.cold_thresholds[i] << " ";
770                 }
771                 dump_buf << "] vrThrottlingThreshold: " << name_info_pair.second.vr_threshold;
772                 dump_buf << std::endl;
773             }
774             dump_buf << "getHysteresis:" << std::endl;
775             for (const auto &name_info_pair : map) {
776                 if (!name_info_pair.second.is_watch) {
777                     continue;
778                 }
779                 dump_buf << " Name: " << name_info_pair.first;
780                 dump_buf << " hotHysteresis: [";
781                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
782                     dump_buf << name_info_pair.second.hot_hysteresis[i] << " ";
783                 }
784                 dump_buf << "] coldHysteresis: [";
785                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
786                     dump_buf << name_info_pair.second.cold_hysteresis[i] << " ";
787                 }
788                 dump_buf << "]" << std::endl;
789             }
790         }
791         {
792             dump_buf << "getCurrentCoolingDevices:" << std::endl;
793             std::vector<CoolingDevice> cooling_devices;
794             if (!thermal_helper_->fillCurrentCoolingDevices(false, CoolingType::CPU,
795                                                             &cooling_devices)) {
796                 dump_buf << " Failed to getCurrentCoolingDevices." << std::endl;
797             }
798 
799             for (const auto &c : cooling_devices) {
800                 dump_buf << " Type: " << toString(c.type) << " Name: " << c.name
801                          << " CurrentValue: " << c.value << std::endl;
802             }
803         }
804         {
805             dump_buf << "getCallbacks:" << std::endl;
806             dump_buf << " Total: " << callbacks_.size() << std::endl;
807             for (const auto &c : callbacks_) {
808                 dump_buf << " IsFilter: " << c.is_filter_type << " Type: " << toString(c.type)
809                          << std::endl;
810             }
811         }
812         {
813             dump_buf << "sendCallback:" << std::endl;
814             dump_buf << "  Enabled List: ";
815             const auto &map = thermal_helper_->GetSensorInfoMap();
816             for (const auto &name_info_pair : map) {
817                 if (name_info_pair.second.send_cb) {
818                     dump_buf << name_info_pair.first << " ";
819                 }
820             }
821             dump_buf << std::endl;
822         }
823         {
824             dump_buf << "sendPowerHint:" << std::endl;
825             dump_buf << "  Enabled List: ";
826             const auto &map = thermal_helper_->GetSensorInfoMap();
827             for (const auto &name_info_pair : map) {
828                 if (name_info_pair.second.send_powerhint) {
829                     dump_buf << name_info_pair.first << " ";
830                 }
831             }
832             dump_buf << std::endl;
833         }
834         dumpVirtualSensorInfo(&dump_buf);
835         dumpVtEstimatorInfo(&dump_buf);
836         dumpThrottlingInfo(&dump_buf);
837         dumpThrottlingRequestStatus(&dump_buf);
838         dumpPowerRailInfo(&dump_buf);
839         dumpThermalStats(&dump_buf);
840         {
841             dump_buf << "getAIDLPowerHalInfo:" << std::endl;
842             dump_buf << " Exist: " << std::boolalpha << thermal_helper_->isAidlPowerHalExist()
843                      << std::endl;
844             dump_buf << " Connected: " << std::boolalpha << thermal_helper_->isPowerHalConnected()
845                      << std::endl;
846             dump_buf << " Ext connected: " << std::boolalpha
847                      << thermal_helper_->isPowerHalExtConnected() << std::endl;
848         }
849     } else if (std::string(args[0]) == "-vt-estimator") {
850         dumpVtEstimatorInfo(&dump_buf);
851     }
852 
853     std::string buf = dump_buf.str();
854     if (!::android::base::WriteStringToFd(buf, fd)) {
855         PLOG(ERROR) << "Failed to dump state to fd";
856     }
857     fsync(fd);
858 }
859 
dump(int fd,const char ** args,uint32_t numArgs)860 binder_status_t Thermal::dump(int fd, const char **args, uint32_t numArgs) {
861     if (numArgs == 0 || std::string(args[0]) == "-a" || std::string(args[0]) == "-vt-estimator") {
862         dumpThermalData(fd, args, numArgs);
863         return STATUS_OK;
864     }
865 
866     if (std::string(args[0]) == "emul_temp" && numArgs >= 3) {
867         return thermal_helper_->emulTemp(
868                        std::string(args[1]), std::atof(args[2]),
869                        numArgs == 3 ? false : std::string(args[3]) == "max_throttling")
870                        ? STATUS_OK
871                        : STATUS_BAD_VALUE;
872     } else if (std::string(args[0]) == "emul_severity" && numArgs >= 3) {
873         return thermal_helper_->emulSeverity(
874                        std::string(args[1]), std::atof(args[2]),
875                        numArgs == 3 ? false : std::string(args[3]) == "max_throttling")
876                        ? STATUS_OK
877                        : STATUS_BAD_VALUE;
878     } else if (std::string(args[0]) == "emul_clear") {
879         return (numArgs != 2 || !thermal_helper_->emulClear(std::string(args[1])))
880                        ? STATUS_BAD_VALUE
881                        : STATUS_OK;
882     }
883     return STATUS_BAD_VALUE;
884 }
885 
addEvent(const Thermal::Looper::Event & e)886 void Thermal::Looper::addEvent(const Thermal::Looper::Event &e) {
887     std::unique_lock<std::mutex> lock(mutex_);
888     events_.push(e);
889     cv_.notify_all();
890 }
891 
~Looper()892 Thermal::Looper::~Looper() {
893     {
894         std::unique_lock<std::mutex> lock(mutex_);
895         aborted_ = true;
896     }
897     cv_.notify_one();
898     thread_.join();
899 }
900 
loop()901 void Thermal::Looper::loop() {
902     while (!aborted_) {
903         std::unique_lock<std::mutex> lock(mutex_);
904         cv_.wait(lock, [&] { return aborted_ || !events_.empty(); });
905         if (!aborted_ && !events_.empty()) {
906             Event event = events_.front();
907             events_.pop();
908             lock.unlock();
909             event.handler();
910         }
911     }
912 }
913 
914 }  // namespace implementation
915 }  // namespace thermal
916 }  // namespace hardware
917 }  // namespace android
918 }  // namespace aidl
919