• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
dumpVirtualSensorInfo(std::ostringstream * dump_buf)310 void Thermal::dumpVirtualSensorInfo(std::ostringstream *dump_buf) {
311     *dump_buf << "getVirtualSensorInfo:" << std::endl;
312     const auto &map = thermal_helper_->GetSensorInfoMap();
313     for (const auto &sensor_info_pair : map) {
314         if (sensor_info_pair.second.virtual_sensor_info != nullptr) {
315             *dump_buf << " Name: " << sensor_info_pair.first << std::endl;
316             *dump_buf << "  LinkedSensorName: [";
317             for (size_t i = 0;
318                  i < sensor_info_pair.second.virtual_sensor_info->linked_sensors.size(); i++) {
319                 *dump_buf << sensor_info_pair.second.virtual_sensor_info->linked_sensors[i] << " ";
320             }
321             *dump_buf << "]" << std::endl;
322             *dump_buf << "  LinkedSensorCoefficient: [";
323             for (size_t i = 0; i < sensor_info_pair.second.virtual_sensor_info->coefficients.size();
324                  i++) {
325                 *dump_buf << sensor_info_pair.second.virtual_sensor_info->coefficients[i] << " ";
326             }
327             *dump_buf << "]" << std::endl;
328             *dump_buf << "  Offset: " << sensor_info_pair.second.virtual_sensor_info->offset
329                       << std::endl;
330             *dump_buf << "  Trigger Sensor: ";
331             if (sensor_info_pair.second.virtual_sensor_info->trigger_sensors.empty()) {
332                 *dump_buf << "N/A" << std::endl;
333             } else {
334                 for (size_t i = 0;
335                      i < sensor_info_pair.second.virtual_sensor_info->trigger_sensors.size(); i++) {
336                     *dump_buf << sensor_info_pair.second.virtual_sensor_info->trigger_sensors[i]
337                               << " ";
338                 }
339                 *dump_buf << std::endl;
340             }
341             *dump_buf << "  Formula: ";
342             switch (sensor_info_pair.second.virtual_sensor_info->formula) {
343                 case FormulaOption::COUNT_THRESHOLD:
344                     *dump_buf << "COUNT_THRESHOLD";
345                     break;
346                 case FormulaOption::WEIGHTED_AVG:
347                     *dump_buf << "WEIGHTED_AVG";
348                     break;
349                 case FormulaOption::MAXIMUM:
350                     *dump_buf << "MAXIMUM";
351                     break;
352                 case FormulaOption::MINIMUM:
353                     *dump_buf << "MINIMUM";
354                     break;
355                 default:
356                     *dump_buf << "NONE";
357                     break;
358             }
359 
360             *dump_buf << std::endl;
361         }
362     }
363 }
364 
dumpVtEstimatorInfo(std::ostringstream * dump_buf)365 void Thermal::dumpVtEstimatorInfo(std::ostringstream *dump_buf) {
366     *dump_buf << "getVtEstimatorInfo:" << std::endl;
367     const auto &map = thermal_helper_->GetSensorInfoMap();
368     for (const auto &name_info_pair : map) {
369         thermal_helper_->dumpVtEstimatorStatus(name_info_pair.first, dump_buf);
370     }
371 }
372 
dumpThrottlingInfo(std::ostringstream * dump_buf)373 void Thermal::dumpThrottlingInfo(std::ostringstream *dump_buf) {
374     *dump_buf << "getThrottlingInfo:" << std::endl;
375     const auto &map = thermal_helper_->GetSensorInfoMap();
376     const auto &thermal_throttling_status_map = thermal_helper_->GetThermalThrottlingStatusMap();
377     for (const auto &name_info_pair : map) {
378         if (name_info_pair.second.throttling_info == nullptr) {
379             continue;
380         }
381         if (name_info_pair.second.throttling_info->binded_cdev_info_map.size()) {
382             if (thermal_throttling_status_map.find(name_info_pair.first) ==
383                 thermal_throttling_status_map.end()) {
384                 continue;
385             }
386             *dump_buf << " Name: " << name_info_pair.first << std::endl;
387             if (thermal_throttling_status_map.at(name_info_pair.first)
388                         .pid_power_budget_map.size()) {
389                 *dump_buf << "  PID Info:" << std::endl;
390                 *dump_buf << "   K_po: [";
391                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
392                     *dump_buf << name_info_pair.second.throttling_info->k_po[i] << " ";
393                 }
394                 *dump_buf << "]" << std::endl;
395                 *dump_buf << "   K_pu: [";
396                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
397                     *dump_buf << name_info_pair.second.throttling_info->k_pu[i] << " ";
398                 }
399                 *dump_buf << "]" << std::endl;
400                 *dump_buf << "   K_i: [";
401                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
402                     *dump_buf << name_info_pair.second.throttling_info->k_i[i] << " ";
403                 }
404                 *dump_buf << "]" << std::endl;
405                 *dump_buf << "   K_d: [";
406                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
407                     *dump_buf << name_info_pair.second.throttling_info->k_d[i] << " ";
408                 }
409                 *dump_buf << "]" << std::endl;
410                 *dump_buf << "   i_max: [";
411                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
412                     *dump_buf << name_info_pair.second.throttling_info->i_max[i] << " ";
413                 }
414                 *dump_buf << "]" << std::endl;
415                 *dump_buf << "   max_alloc_power: [";
416                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
417                     *dump_buf << name_info_pair.second.throttling_info->max_alloc_power[i] << " ";
418                 }
419                 *dump_buf << "]" << std::endl;
420                 *dump_buf << "   min_alloc_power: [";
421                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
422                     *dump_buf << name_info_pair.second.throttling_info->min_alloc_power[i] << " ";
423                 }
424                 *dump_buf << "]" << std::endl;
425                 *dump_buf << "   s_power: [";
426                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
427                     *dump_buf << name_info_pair.second.throttling_info->s_power[i] << " ";
428                 }
429                 *dump_buf << "]" << std::endl;
430                 *dump_buf << "   i_cutoff: [";
431                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
432                     *dump_buf << name_info_pair.second.throttling_info->i_cutoff[i] << " ";
433                 }
434                 *dump_buf << "]" << std::endl;
435             }
436             const auto &profile = thermal_throttling_status_map.at(name_info_pair.first).profile;
437             *dump_buf << "  Binded CDEV Info:" << (profile.empty() ? "default" : profile)
438                       << std::endl;
439 
440             for (const auto &binded_cdev_info_pair :
441                  name_info_pair.second.throttling_info->profile_map.count(profile)
442                          ? name_info_pair.second.throttling_info->profile_map.at(profile)
443                          : name_info_pair.second.throttling_info->binded_cdev_info_map) {
444                 *dump_buf << "   Cooling device name: " << binded_cdev_info_pair.first << std::endl;
445                 if (thermal_throttling_status_map.at(name_info_pair.first)
446                             .pid_power_budget_map.size()) {
447                     *dump_buf << "    WeightForPID: [";
448                     for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
449                         *dump_buf << binded_cdev_info_pair.second.cdev_weight_for_pid[i] << " ";
450                     }
451                     *dump_buf << "]" << std::endl;
452                 }
453                 *dump_buf << "    Ceiling: [";
454                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
455                     *dump_buf << binded_cdev_info_pair.second.cdev_ceiling[i] << " ";
456                 }
457                 *dump_buf << "]" << std::endl;
458                 *dump_buf << "    Hard limit: [";
459                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
460                     *dump_buf << binded_cdev_info_pair.second.limit_info[i] << " ";
461                 }
462                 *dump_buf << "]" << std::endl;
463 
464                 if (!binded_cdev_info_pair.second.power_rail.empty()) {
465                     *dump_buf << "    Binded power rail: "
466                               << binded_cdev_info_pair.second.power_rail << std::endl;
467                     *dump_buf << "    Power threshold: [";
468                     for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
469                         *dump_buf << binded_cdev_info_pair.second.power_thresholds[i] << " ";
470                     }
471                     *dump_buf << "]" << std::endl;
472                     *dump_buf << "    Floor with PowerLink: [";
473                     for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
474                         *dump_buf << binded_cdev_info_pair.second.cdev_floor_with_power_link[i]
475                                   << " ";
476                     }
477                     *dump_buf << "]" << std::endl;
478                     *dump_buf << "    Release logic: ";
479                     switch (binded_cdev_info_pair.second.release_logic) {
480                         case ReleaseLogic::INCREASE:
481                             *dump_buf << "INCREASE";
482                             break;
483                         case ReleaseLogic::DECREASE:
484                             *dump_buf << "DECREASE";
485                             break;
486                         case ReleaseLogic::STEPWISE:
487                             *dump_buf << "STEPWISE";
488                             break;
489                         case ReleaseLogic::RELEASE_TO_FLOOR:
490                             *dump_buf << "RELEASE_TO_FLOOR";
491                             break;
492                         default:
493                             *dump_buf << "NONE";
494                             break;
495                     }
496                     *dump_buf << std::endl;
497                     *dump_buf << "    high_power_check: " << std::boolalpha
498                               << binded_cdev_info_pair.second.high_power_check << std::endl;
499                     *dump_buf << "    throttling_with_power_link: " << std::boolalpha
500                               << binded_cdev_info_pair.second.throttling_with_power_link
501                               << std::endl;
502                 }
503             }
504         }
505     }
506 }
507 
dumpThrottlingRequestStatus(std::ostringstream * dump_buf)508 void Thermal::dumpThrottlingRequestStatus(std::ostringstream *dump_buf) {
509     const auto &thermal_throttling_status_map = thermal_helper_->GetThermalThrottlingStatusMap();
510     if (!thermal_throttling_status_map.size()) {
511         return;
512     }
513     *dump_buf << "getThrottlingRequestStatus:" << std::endl;
514     for (const auto &thermal_throttling_status_pair : thermal_throttling_status_map) {
515         *dump_buf << " Name: " << thermal_throttling_status_pair.first << std::endl;
516         if (thermal_throttling_status_pair.second.pid_power_budget_map.size()) {
517             *dump_buf << "  power budget request state" << std::endl;
518             for (const auto &request_pair :
519                  thermal_throttling_status_pair.second.pid_power_budget_map) {
520                 *dump_buf << "   " << request_pair.first << ": " << request_pair.second
521                           << std::endl;
522             }
523         }
524         if (thermal_throttling_status_pair.second.pid_cdev_request_map.size()) {
525             *dump_buf << "  pid cdev request state" << std::endl;
526             for (const auto &request_pair :
527                  thermal_throttling_status_pair.second.pid_cdev_request_map) {
528                 *dump_buf << "   " << request_pair.first << ": " << request_pair.second
529                           << std::endl;
530             }
531         }
532         if (thermal_throttling_status_pair.second.hardlimit_cdev_request_map.size()) {
533             *dump_buf << "  hard limit cdev request state" << std::endl;
534             for (const auto &request_pair :
535                  thermal_throttling_status_pair.second.hardlimit_cdev_request_map) {
536                 *dump_buf << "   " << request_pair.first << ": " << request_pair.second
537                           << std::endl;
538             }
539         }
540         if (thermal_throttling_status_pair.second.throttling_release_map.size()) {
541             *dump_buf << "  cdev release state" << std::endl;
542             for (const auto &request_pair :
543                  thermal_throttling_status_pair.second.throttling_release_map) {
544                 *dump_buf << "   " << request_pair.first << ": " << request_pair.second
545                           << std::endl;
546             }
547         }
548         if (thermal_throttling_status_pair.second.cdev_status_map.size()) {
549             *dump_buf << "  cdev request state" << std::endl;
550             for (const auto &request_pair : thermal_throttling_status_pair.second.cdev_status_map) {
551                 *dump_buf << "   " << request_pair.first << ": " << request_pair.second
552                           << std::endl;
553             }
554         }
555     }
556 }
557 
dumpPowerRailInfo(std::ostringstream * dump_buf)558 void Thermal::dumpPowerRailInfo(std::ostringstream *dump_buf) {
559     const auto &power_rail_info_map = thermal_helper_->GetPowerRailInfoMap();
560     const auto &power_status_map = thermal_helper_->GetPowerStatusMap();
561 
562     *dump_buf << "getPowerRailInfo:" << std::endl;
563     for (const auto &power_rail_pair : power_rail_info_map) {
564         *dump_buf << " Power Rail: " << power_rail_pair.first << std::endl;
565         *dump_buf << "  Power Sample Count: " << power_rail_pair.second.power_sample_count
566                   << std::endl;
567         *dump_buf << "  Power Sample Delay: " << power_rail_pair.second.power_sample_delay.count()
568                   << std::endl;
569         if (power_status_map.count(power_rail_pair.first)) {
570             auto power_history = power_status_map.at(power_rail_pair.first).power_history;
571             *dump_buf << "  Last Updated AVG Power: "
572                       << power_status_map.at(power_rail_pair.first).last_updated_avg_power << " mW"
573                       << std::endl;
574             if (power_rail_pair.second.virtual_power_rail_info != nullptr) {
575                 *dump_buf << "  Formula=";
576                 switch (power_rail_pair.second.virtual_power_rail_info->formula) {
577                     case FormulaOption::COUNT_THRESHOLD:
578                         *dump_buf << "COUNT_THRESHOLD";
579                         break;
580                     case FormulaOption::WEIGHTED_AVG:
581                         *dump_buf << "WEIGHTED_AVG";
582                         break;
583                     case FormulaOption::MAXIMUM:
584                         *dump_buf << "MAXIMUM";
585                         break;
586                     case FormulaOption::MINIMUM:
587                         *dump_buf << "MINIMUM";
588                         break;
589                     default:
590                         *dump_buf << "NONE";
591                         break;
592                 }
593                 *dump_buf << std::endl;
594             }
595             for (size_t i = 0; i < power_history.size(); ++i) {
596                 if (power_rail_pair.second.virtual_power_rail_info != nullptr) {
597                     *dump_buf
598                             << "  Linked power rail "
599                             << power_rail_pair.second.virtual_power_rail_info->linked_power_rails[i]
600                             << std::endl;
601                     *dump_buf << "   Coefficient="
602                               << power_rail_pair.second.virtual_power_rail_info->coefficients[i]
603                               << std::endl;
604                     *dump_buf << "   Power Samples: ";
605                 } else {
606                     *dump_buf << "  Power Samples: ";
607                 }
608                 while (power_history[i].size() > 0) {
609                     const auto power_sample = power_history[i].front();
610                     power_history[i].pop();
611                     *dump_buf << "(T=" << power_sample.duration
612                               << ", uWs=" << power_sample.energy_counter << ") ";
613                 }
614                 *dump_buf << std::endl;
615             }
616         }
617     }
618 }
619 
dumpStatsRecord(std::ostringstream * dump_buf,const StatsRecord & stats_record,std::string_view line_prefix)620 void Thermal::dumpStatsRecord(std::ostringstream *dump_buf, const StatsRecord &stats_record,
621                               std::string_view line_prefix) {
622     const auto now = boot_clock::now();
623     *dump_buf << line_prefix << "Time Since Last Stats Report: "
624               << std::chrono::duration_cast<std::chrono::minutes>(
625                          now - stats_record.last_stats_report_time)
626                          .count()
627               << " mins" << std::endl;
628     *dump_buf << line_prefix << "Time in State ms: [";
629     for (const auto &time_in_state : stats_record.time_in_state_ms) {
630         *dump_buf << time_in_state.count() << " ";
631     }
632     *dump_buf << "]" << std::endl;
633 }
634 
dumpThermalStats(std::ostringstream * dump_buf)635 void Thermal::dumpThermalStats(std::ostringstream *dump_buf) {
636     *dump_buf << "getThermalStatsInfo:" << std::endl;
637     *dump_buf << " Sensor Temp Stats Info:" << std::endl;
638     const auto &sensor_temp_stats_map_ = thermal_helper_->GetSensorTempStatsSnapshot();
639     const std::string sensor_temp_stats_line_prefix("    ");
640     for (const auto &sensor_temp_stats_pair : sensor_temp_stats_map_) {
641         *dump_buf << "  Sensor Name: " << sensor_temp_stats_pair.first << std::endl;
642         const auto &sensor_temp_stats = sensor_temp_stats_pair.second;
643         *dump_buf << "   Max Temp: " << sensor_temp_stats.max_temp << ", TimeStamp: "
644                   << system_clock::to_time_t(sensor_temp_stats.max_temp_timestamp) << std::endl;
645         *dump_buf << "   Min Temp: " << sensor_temp_stats.min_temp << ", TimeStamp: "
646                   << system_clock::to_time_t(sensor_temp_stats.min_temp_timestamp) << std::endl;
647         for (const auto &stats_by_threshold : sensor_temp_stats.stats_by_custom_threshold) {
648             *dump_buf << "   Record by Threshold: [";
649             for (const auto &threshold : stats_by_threshold.thresholds) {
650                 *dump_buf << threshold << " ";
651             }
652             *dump_buf << "]" << std::endl;
653             if (stats_by_threshold.logging_name.has_value()) {
654                 *dump_buf << "    Logging Name: " << stats_by_threshold.logging_name.value()
655                           << std::endl;
656             }
657             dumpStatsRecord(dump_buf, stats_by_threshold.stats_record,
658                             sensor_temp_stats_line_prefix);
659         }
660 
661         if (sensor_temp_stats.stats_by_default_threshold.has_value()) {
662             *dump_buf << "   Record by Severity:" << std::endl;
663             dumpStatsRecord(dump_buf, sensor_temp_stats.stats_by_default_threshold.value(),
664                             sensor_temp_stats_line_prefix);
665         }
666     }
667     *dump_buf << " Sensor Cdev Request Stats Info:" << std::endl;
668     const auto &sensor_cdev_request_stats_map_ =
669             thermal_helper_->GetSensorCoolingDeviceRequestStatsSnapshot();
670     const std::string sensor_cdev_request_stats_line_prefix("     ");
671     for (const auto &sensor_cdev_request_stats_pair : sensor_cdev_request_stats_map_) {
672         *dump_buf << "  Sensor Name: " << sensor_cdev_request_stats_pair.first << std::endl;
673         for (const auto &cdev_request_stats_pair : sensor_cdev_request_stats_pair.second) {
674             *dump_buf << "   Cooling Device Name: " << cdev_request_stats_pair.first << std::endl;
675             const auto &request_stats = cdev_request_stats_pair.second;
676             for (const auto &stats_by_threshold : request_stats.stats_by_custom_threshold) {
677                 *dump_buf << "    Record by Threshold: [";
678                 for (const auto &threshold : stats_by_threshold.thresholds) {
679                     *dump_buf << threshold << " ";
680                 }
681                 *dump_buf << "]" << std::endl;
682                 if (stats_by_threshold.logging_name.has_value()) {
683                     *dump_buf << "     Logging Name: " << stats_by_threshold.logging_name.value()
684                               << std::endl;
685                 }
686                 dumpStatsRecord(dump_buf, stats_by_threshold.stats_record,
687                                 sensor_cdev_request_stats_line_prefix);
688             }
689             if (request_stats.stats_by_default_threshold.has_value()) {
690                 *dump_buf << "    Record by All State" << std::endl;
691                 dumpStatsRecord(dump_buf, request_stats.stats_by_default_threshold.value(),
692                                 sensor_cdev_request_stats_line_prefix);
693             }
694         }
695     }
696 }
697 
dumpThermalData(int fd,const char ** args,uint32_t numArgs)698 void Thermal::dumpThermalData(int fd, const char **args, uint32_t numArgs) {
699     std::ostringstream dump_buf;
700 
701     if (!thermal_helper_->isInitializedOk()) {
702         dump_buf << "ThermalHAL not initialized properly." << std::endl;
703     } else if (numArgs == 0 || std::string(args[0]) == "-a") {
704         const auto &sensor_status_map = thermal_helper_->GetSensorStatusMap();
705         {
706             dump_buf << "getCachedTemperatures:" << std::endl;
707             boot_clock::time_point now = boot_clock::now();
708             for (const auto &sensor_status_pair : sensor_status_map) {
709                 if ((sensor_status_pair.second.thermal_cached.timestamp) ==
710                     boot_clock::time_point::min()) {
711                     continue;
712                 }
713                 dump_buf << " Name: " << sensor_status_pair.first
714                          << " CachedValue: " << sensor_status_pair.second.thermal_cached.temp
715                          << " TimeToCache: "
716                          << std::chrono::duration_cast<std::chrono::milliseconds>(
717                                     now - sensor_status_pair.second.thermal_cached.timestamp)
718                                     .count()
719                          << "ms" << std::endl;
720             }
721         }
722         {
723             dump_buf << "getEmulSettings:" << std::endl;
724             for (const auto &sensor_status_pair : sensor_status_map) {
725                 if (sensor_status_pair.second.override_status.emul_temp == nullptr) {
726                     continue;
727                 }
728                 dump_buf << " Name: " << sensor_status_pair.first << " EmulTemp: "
729                          << sensor_status_pair.second.override_status.emul_temp->temp
730                          << " EmulSeverity: "
731                          << sensor_status_pair.second.override_status.emul_temp->severity
732                          << " maxThrottling: " << std::boolalpha
733                          << sensor_status_pair.second.override_status.max_throttling << std::endl;
734             }
735         }
736         {
737             const auto &map = thermal_helper_->GetSensorInfoMap();
738             dump_buf << "getCurrentTemperatures:" << std::endl;
739             Temperature temp_2_0;
740             for (const auto &name_info_pair : map) {
741                 thermal_helper_->readTemperature(name_info_pair.first, &temp_2_0, nullptr, true);
742                 dump_buf << " Type: " << toString(temp_2_0.type)
743                          << " Name: " << name_info_pair.first << " CurrentValue: " << temp_2_0.value
744                          << " ThrottlingStatus: " << toString(temp_2_0.throttlingStatus)
745                          << std::endl;
746             }
747             dump_buf << "getTemperatureThresholds:" << std::endl;
748             for (const auto &name_info_pair : map) {
749                 if (!name_info_pair.second.is_watch) {
750                     continue;
751                 }
752                 dump_buf << " Type: " << toString(name_info_pair.second.type)
753                          << " Name: " << name_info_pair.first;
754                 dump_buf << " hotThrottlingThreshold: [";
755                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
756                     dump_buf << name_info_pair.second.hot_thresholds[i] << " ";
757                 }
758                 dump_buf << "] coldThrottlingThreshold: [";
759                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
760                     dump_buf << name_info_pair.second.cold_thresholds[i] << " ";
761                 }
762                 dump_buf << "] vrThrottlingThreshold: " << name_info_pair.second.vr_threshold;
763                 dump_buf << std::endl;
764             }
765             dump_buf << "getHysteresis:" << std::endl;
766             for (const auto &name_info_pair : map) {
767                 if (!name_info_pair.second.is_watch) {
768                     continue;
769                 }
770                 dump_buf << " Name: " << name_info_pair.first;
771                 dump_buf << " hotHysteresis: [";
772                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
773                     dump_buf << name_info_pair.second.hot_hysteresis[i] << " ";
774                 }
775                 dump_buf << "] coldHysteresis: [";
776                 for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
777                     dump_buf << name_info_pair.second.cold_hysteresis[i] << " ";
778                 }
779                 dump_buf << "]" << std::endl;
780             }
781         }
782         {
783             dump_buf << "getCurrentCoolingDevices:" << std::endl;
784             std::vector<CoolingDevice> cooling_devices;
785             if (!thermal_helper_->fillCurrentCoolingDevices(false, CoolingType::CPU,
786                                                             &cooling_devices)) {
787                 dump_buf << " Failed to getCurrentCoolingDevices." << std::endl;
788             }
789 
790             for (const auto &c : cooling_devices) {
791                 dump_buf << " Type: " << toString(c.type) << " Name: " << c.name
792                          << " CurrentValue: " << c.value << std::endl;
793             }
794         }
795         {
796             dump_buf << "getCallbacks:" << std::endl;
797             dump_buf << " Total: " << callbacks_.size() << std::endl;
798             for (const auto &c : callbacks_) {
799                 dump_buf << " IsFilter: " << c.is_filter_type << " Type: " << toString(c.type)
800                          << std::endl;
801             }
802         }
803         {
804             dump_buf << "sendCallback:" << std::endl;
805             dump_buf << "  Enabled List: ";
806             const auto &map = thermal_helper_->GetSensorInfoMap();
807             for (const auto &name_info_pair : map) {
808                 if (name_info_pair.second.send_cb) {
809                     dump_buf << name_info_pair.first << " ";
810                 }
811             }
812             dump_buf << std::endl;
813         }
814         {
815             dump_buf << "sendPowerHint:" << std::endl;
816             dump_buf << "  Enabled List: ";
817             const auto &map = thermal_helper_->GetSensorInfoMap();
818             for (const auto &name_info_pair : map) {
819                 if (name_info_pair.second.send_powerhint) {
820                     dump_buf << name_info_pair.first << " ";
821                 }
822             }
823             dump_buf << std::endl;
824         }
825         dumpVirtualSensorInfo(&dump_buf);
826         dumpVtEstimatorInfo(&dump_buf);
827         dumpThrottlingInfo(&dump_buf);
828         dumpThrottlingRequestStatus(&dump_buf);
829         dumpPowerRailInfo(&dump_buf);
830         dumpThermalStats(&dump_buf);
831         {
832             dump_buf << "getAIDLPowerHalInfo:" << std::endl;
833             dump_buf << " Exist: " << std::boolalpha << thermal_helper_->isAidlPowerHalExist()
834                      << std::endl;
835             dump_buf << " Connected: " << std::boolalpha << thermal_helper_->isPowerHalConnected()
836                      << std::endl;
837             dump_buf << " Ext connected: " << std::boolalpha
838                      << thermal_helper_->isPowerHalExtConnected() << std::endl;
839         }
840     } else if (std::string(args[0]) == "-vt-estimator") {
841         dumpVtEstimatorInfo(&dump_buf);
842     }
843 
844     std::string buf = dump_buf.str();
845     if (!::android::base::WriteStringToFd(buf, fd)) {
846         PLOG(ERROR) << "Failed to dump state to fd";
847     }
848     fsync(fd);
849 }
850 
dump(int fd,const char ** args,uint32_t numArgs)851 binder_status_t Thermal::dump(int fd, const char **args, uint32_t numArgs) {
852     if (numArgs == 0 || std::string(args[0]) == "-a" || std::string(args[0]) == "-vt-estimator") {
853         dumpThermalData(fd, args, numArgs);
854         return STATUS_OK;
855     }
856 
857     if (std::string(args[0]) == "emul_temp" && numArgs >= 3) {
858         return thermal_helper_->emulTemp(
859                        std::string(args[1]), std::atof(args[2]),
860                        numArgs == 3 ? false : std::string(args[3]) == "max_throttling")
861                        ? STATUS_OK
862                        : STATUS_BAD_VALUE;
863     } else if (std::string(args[0]) == "emul_severity" && numArgs >= 3) {
864         return thermal_helper_->emulSeverity(
865                        std::string(args[1]), std::atof(args[2]),
866                        numArgs == 3 ? false : std::string(args[3]) == "max_throttling")
867                        ? STATUS_OK
868                        : STATUS_BAD_VALUE;
869     } else if (std::string(args[0]) == "emul_clear") {
870         return (numArgs != 2 || !thermal_helper_->emulClear(std::string(args[1])))
871                        ? STATUS_BAD_VALUE
872                        : STATUS_OK;
873     }
874     return STATUS_BAD_VALUE;
875 }
876 
addEvent(const Thermal::Looper::Event & e)877 void Thermal::Looper::addEvent(const Thermal::Looper::Event &e) {
878     std::unique_lock<std::mutex> lock(mutex_);
879     events_.push(e);
880     cv_.notify_all();
881 }
882 
~Looper()883 Thermal::Looper::~Looper() {
884     {
885         std::unique_lock<std::mutex> lock(mutex_);
886         aborted_ = true;
887     }
888     cv_.notify_one();
889     thread_.join();
890 }
891 
loop()892 void Thermal::Looper::loop() {
893     while (!aborted_) {
894         std::unique_lock<std::mutex> lock(mutex_);
895         cv_.wait(lock, [&] { return aborted_ || !events_.empty(); });
896         if (!aborted_ && !events_.empty()) {
897             Event event = events_.front();
898             events_.pop();
899             lock.unlock();
900             event.handler();
901         }
902     }
903 }
904 
905 }  // namespace implementation
906 }  // namespace thermal
907 }  // namespace hardware
908 }  // namespace android
909 }  // namespace aidl
910