1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <cerrno>
18 #include <mutex>
19 #include <string>
20 
21 #include <android-base/file.h>
22 #include <android-base/logging.h>
23 #include <hidl/HidlTransportSupport.h>
24 
25 #include "Thermal.h"
26 #include "thermal-helper.h"
27 
28 namespace android {
29 namespace hardware {
30 namespace thermal {
31 namespace V2_0 {
32 namespace implementation {
33 
34 namespace {
35 
36 using ::android::hardware::interfacesEqual;
37 using ::android::hardware::thermal::V1_0::ThermalStatus;
38 using ::android::hardware::thermal::V1_0::ThermalStatusCode;
39 
40 template <typename T, typename U>
setFailureAndCallback(T _hidl_cb,hidl_vec<U> data,std::string_view debug_msg)41 Return<void> setFailureAndCallback(T _hidl_cb, hidl_vec<U> data, std::string_view debug_msg) {
42     ThermalStatus status;
43     status.code = ThermalStatusCode::FAILURE;
44     status.debugMessage = debug_msg.data();
45     _hidl_cb(status, data);
46     return Void();
47 }
48 
49 template <typename T, typename U>
setInitFailureAndCallback(T _hidl_cb,hidl_vec<U> data)50 Return<void> setInitFailureAndCallback(T _hidl_cb, hidl_vec<U> data) {
51     return setFailureAndCallback(_hidl_cb, data, "Failure initializing thermal HAL");
52 }
53 
54 }  // namespace
55 
56 // On init we will spawn a thread which will continually watch for
57 // throttling.  When throttling is seen, if we have a callback registered
58 // the thread will call notifyThrottling() else it will log the dropped
59 // throttling event and do nothing.  The thread is only killed when
60 // Thermal() is killed.
Thermal()61 Thermal::Thermal()
62     : thermal_helper_(
63           std::bind(&Thermal::sendThermalChangedCallback, this, std::placeholders::_1)) {}
64 
65 // Methods from ::android::hardware::thermal::V1_0::IThermal.
getTemperatures(getTemperatures_cb _hidl_cb)66 Return<void> Thermal::getTemperatures(getTemperatures_cb _hidl_cb) {
67     ThermalStatus status;
68     status.code = ThermalStatusCode::SUCCESS;
69     hidl_vec<Temperature_1_0> temperatures;
70 
71     if (!thermal_helper_.isInitializedOk()) {
72         LOG(ERROR) << "ThermalHAL not initialized properly.";
73         return setInitFailureAndCallback(_hidl_cb, temperatures);
74     }
75 
76     if (!thermal_helper_.fillTemperatures(&temperatures)) {
77         return setFailureAndCallback(_hidl_cb, temperatures, "Failed to read thermal sensors.");
78     }
79 
80     _hidl_cb(status, temperatures);
81     return Void();
82 }
83 
getCpuUsages(getCpuUsages_cb _hidl_cb)84 Return<void> Thermal::getCpuUsages(getCpuUsages_cb _hidl_cb) {
85     ThermalStatus status;
86     status.code = ThermalStatusCode::SUCCESS;
87     hidl_vec<CpuUsage> cpu_usages;
88 
89     if (!thermal_helper_.isInitializedOk()) {
90         return setInitFailureAndCallback(_hidl_cb, cpu_usages);
91     }
92 
93     if (!thermal_helper_.fillCpuUsages(&cpu_usages)) {
94         return setFailureAndCallback(_hidl_cb, cpu_usages, "Failed to get CPU usages.");
95     }
96 
97     _hidl_cb(status, cpu_usages);
98     return Void();
99 }
100 
getCoolingDevices(getCoolingDevices_cb _hidl_cb)101 Return<void> Thermal::getCoolingDevices(getCoolingDevices_cb _hidl_cb) {
102     ThermalStatus status;
103     status.code = ThermalStatusCode::SUCCESS;
104     hidl_vec<CoolingDevice_1_0> cooling_devices;
105 
106     if (!thermal_helper_.isInitializedOk()) {
107         return setInitFailureAndCallback(_hidl_cb, cooling_devices);
108     }
109     _hidl_cb(status, cooling_devices);
110     return Void();
111 }
112 
getCurrentTemperatures(bool filterType,TemperatureType_2_0 type,getCurrentTemperatures_cb _hidl_cb)113 Return<void> Thermal::getCurrentTemperatures(bool filterType, TemperatureType_2_0 type,
114                                              getCurrentTemperatures_cb _hidl_cb) {
115     ThermalStatus status;
116     status.code = ThermalStatusCode::SUCCESS;
117     hidl_vec<Temperature_2_0> temperatures;
118 
119     if (!thermal_helper_.isInitializedOk()) {
120         LOG(ERROR) << "ThermalHAL not initialized properly.";
121         return setInitFailureAndCallback(_hidl_cb, temperatures);
122     }
123 
124     if (!thermal_helper_.fillCurrentTemperatures(filterType, false, type, &temperatures)) {
125         return setFailureAndCallback(_hidl_cb, temperatures, "Failed to read thermal sensors.");
126     }
127 
128     _hidl_cb(status, temperatures);
129     return Void();
130 }
131 
getTemperatureThresholds(bool filterType,TemperatureType_2_0 type,getTemperatureThresholds_cb _hidl_cb)132 Return<void> Thermal::getTemperatureThresholds(bool filterType, TemperatureType_2_0 type,
133                                                getTemperatureThresholds_cb _hidl_cb) {
134     ThermalStatus status;
135     status.code = ThermalStatusCode::SUCCESS;
136     hidl_vec<TemperatureThreshold> temperatures;
137 
138     if (!thermal_helper_.isInitializedOk()) {
139         LOG(ERROR) << "ThermalHAL not initialized properly.";
140         return setInitFailureAndCallback(_hidl_cb, temperatures);
141     }
142 
143     if (!thermal_helper_.fillTemperatureThresholds(filterType, type, &temperatures)) {
144         return setFailureAndCallback(_hidl_cb, temperatures, "Failed to read thermal sensors.");
145     }
146 
147     _hidl_cb(status, temperatures);
148     return Void();
149 }
150 
getCurrentCoolingDevices(bool filterType,CoolingType type,getCurrentCoolingDevices_cb _hidl_cb)151 Return<void> Thermal::getCurrentCoolingDevices(bool filterType, CoolingType type,
152                                                getCurrentCoolingDevices_cb _hidl_cb) {
153     ThermalStatus status;
154     status.code = ThermalStatusCode::SUCCESS;
155     hidl_vec<CoolingDevice_2_0> cooling_devices;
156 
157     if (!thermal_helper_.isInitializedOk()) {
158         LOG(ERROR) << "ThermalHAL not initialized properly.";
159         return setInitFailureAndCallback(_hidl_cb, cooling_devices);
160     }
161 
162     if (!thermal_helper_.fillCurrentCoolingDevices(filterType, type, &cooling_devices)) {
163         return setFailureAndCallback(_hidl_cb, cooling_devices, "Failed to read thermal sensors.");
164     }
165 
166     _hidl_cb(status, cooling_devices);
167     return Void();
168 }
169 
registerThermalChangedCallback(const sp<IThermalChangedCallback> & callback,bool filterType,TemperatureType_2_0 type,registerThermalChangedCallback_cb _hidl_cb)170 Return<void> Thermal::registerThermalChangedCallback(const sp<IThermalChangedCallback> &callback,
171                                                      bool filterType, TemperatureType_2_0 type,
172                                                      registerThermalChangedCallback_cb _hidl_cb) {
173     ThermalStatus status;
174     hidl_vec<Temperature_2_0> temperatures;
175 
176     if (callback == nullptr) {
177         status.code = ThermalStatusCode::FAILURE;
178         status.debugMessage = "Invalid nullptr callback";
179         LOG(ERROR) << status.debugMessage;
180         _hidl_cb(status);
181         return Void();
182     } else {
183         status.code = ThermalStatusCode::SUCCESS;
184     }
185     std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
186     if (std::any_of(callbacks_.begin(), callbacks_.end(), [&](const CallbackSetting &c) {
187             return interfacesEqual(c.callback, callback);
188         })) {
189         status.code = ThermalStatusCode::FAILURE;
190         status.debugMessage = "Same callback registered already";
191         LOG(ERROR) << status.debugMessage;
192     } else {
193         callbacks_.emplace_back(callback, filterType, type);
194         LOG(INFO) << "a callback has been registered to ThermalHAL, isFilter: " << filterType
195                   << " Type: " << android::hardware::thermal::V2_0::toString(type);
196     }
197     _hidl_cb(status);
198 
199     // Send notification right away after thermal callback registration
200     if (thermal_helper_.fillCurrentTemperatures(filterType, true, type, &temperatures)) {
201         for (const auto &t : temperatures) {
202             if (!filterType || t.type == type) {
203                 LOG(INFO) << "Sending notification: "
204                           << " Type: " << android::hardware::thermal::V2_0::toString(t.type)
205                           << " Name: " << t.name << " CurrentValue: " << t.value
206                           << " ThrottlingStatus: "
207                           << android::hardware::thermal::V2_0::toString(t.throttlingStatus);
208                 callback->notifyThrottling(t);
209             }
210         }
211     }
212 
213     return Void();
214 }
215 
unregisterThermalChangedCallback(const sp<IThermalChangedCallback> & callback,unregisterThermalChangedCallback_cb _hidl_cb)216 Return<void> Thermal::unregisterThermalChangedCallback(
217     const sp<IThermalChangedCallback> &callback, unregisterThermalChangedCallback_cb _hidl_cb) {
218     ThermalStatus status;
219     if (callback == nullptr) {
220         status.code = ThermalStatusCode::FAILURE;
221         status.debugMessage = "Invalid nullptr callback";
222         LOG(ERROR) << status.debugMessage;
223         _hidl_cb(status);
224         return Void();
225     } else {
226         status.code = ThermalStatusCode::SUCCESS;
227     }
228     bool removed = false;
229     std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
230     callbacks_.erase(
231         std::remove_if(callbacks_.begin(), callbacks_.end(),
232                        [&](const CallbackSetting &c) {
233                            if (interfacesEqual(c.callback, callback)) {
234                                LOG(INFO)
235                                    << "a callback has been unregistered to ThermalHAL, isFilter: "
236                                    << c.is_filter_type << " Type: "
237                                    << android::hardware::thermal::V2_0::toString(c.type);
238                                removed = true;
239                                return true;
240                            }
241                            return false;
242                        }),
243         callbacks_.end());
244     if (!removed) {
245         status.code = ThermalStatusCode::FAILURE;
246         status.debugMessage = "The callback was not registered before";
247         LOG(ERROR) << status.debugMessage;
248     }
249     _hidl_cb(status);
250     return Void();
251 }
252 
sendThermalChangedCallback(const Temperature_2_0 & t)253 void Thermal::sendThermalChangedCallback(const Temperature_2_0 &t) {
254     std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
255 
256     LOG(VERBOSE) << "Sending notification: "
257                  << " Type: " << android::hardware::thermal::V2_0::toString(t.type)
258                  << " Name: " << t.name << " CurrentValue: " << t.value << " ThrottlingStatus: "
259                  << android::hardware::thermal::V2_0::toString(t.throttlingStatus);
260 
261     callbacks_.erase(
262             std::remove_if(callbacks_.begin(), callbacks_.end(),
263                            [&](const CallbackSetting &c) {
264                                if (!c.is_filter_type || t.type == c.type) {
265                                    Return<void> ret = c.callback->notifyThrottling(t);
266                                    if (!ret.isOk()) {
267                                        LOG(ERROR) << "a Thermal callback is dead, removed from "
268                                                      "callback list.";
269                                        return true;
270                                    }
271                                    return false;
272                                }
273                                return false;
274                            }),
275             callbacks_.end());
276 }
277 
dumpVirtualSensorInfo(std::ostringstream * dump_buf)278 void Thermal::dumpVirtualSensorInfo(std::ostringstream *dump_buf) {
279     *dump_buf << "VirtualSensorInfo:" << std::endl;
280     const auto &map = thermal_helper_.GetSensorInfoMap();
281     for (const auto &sensor_info_pair : map) {
282         if (sensor_info_pair.second.virtual_sensor_info != nullptr) {
283             *dump_buf << " Name: " << sensor_info_pair.first << std::endl;
284             *dump_buf << "  LinkedSensorName: [";
285             for (size_t i = 0;
286                  i < sensor_info_pair.second.virtual_sensor_info->linked_sensors.size(); i++) {
287                 *dump_buf << sensor_info_pair.second.virtual_sensor_info->linked_sensors[i] << " ";
288             }
289             *dump_buf << "]" << std::endl;
290             *dump_buf << "  LinkedSensorCoefficient: [";
291             for (size_t i = 0; i < sensor_info_pair.second.virtual_sensor_info->coefficients.size();
292                  i++) {
293                 *dump_buf << sensor_info_pair.second.virtual_sensor_info->coefficients[i] << " ";
294             }
295             *dump_buf << "]" << std::endl;
296             *dump_buf << "  Offset: " << sensor_info_pair.second.virtual_sensor_info->offset
297                       << std::endl;
298             *dump_buf << "  Trigger Sensor: "
299                       << (sensor_info_pair.second.virtual_sensor_info->trigger_sensor.empty()
300                                   ? "N/A"
301                                   : sensor_info_pair.second.virtual_sensor_info->trigger_sensor)
302                       << std::endl;
303             *dump_buf << "  Formula: ";
304             switch (sensor_info_pair.second.virtual_sensor_info->formula) {
305                 case FormulaOption::COUNT_THRESHOLD:
306                     *dump_buf << "COUNT_THRESHOLD";
307                     break;
308                 case FormulaOption::WEIGHTED_AVG:
309                     *dump_buf << "WEIGHTED_AVG";
310                     break;
311                 case FormulaOption::MAXIMUM:
312                     *dump_buf << "MAXIMUM";
313                     break;
314                 case FormulaOption::MINIMUM:
315                     *dump_buf << "MINIMUM";
316                     break;
317                 default:
318                     *dump_buf << "NONE";
319                     break;
320             }
321 
322             *dump_buf << std::endl;
323         }
324     }
325 }
326 
dumpThrottlingInfo(std::ostringstream * dump_buf)327 void Thermal::dumpThrottlingInfo(std::ostringstream *dump_buf) {
328     *dump_buf << "Throttling Info:" << std::endl;
329     const auto &map = thermal_helper_.GetSensorInfoMap();
330     for (const auto &name_info_pair : map) {
331         if (name_info_pair.second.throttling_info->binded_cdev_info_map.size()) {
332             *dump_buf << " Name: " << name_info_pair.first << std::endl;
333             *dump_buf << "  PID Info:" << std::endl;
334             *dump_buf << "   K_po: [";
335             for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
336                 *dump_buf << name_info_pair.second.throttling_info->k_po[i] << " ";
337             }
338             *dump_buf << "]" << std::endl;
339             *dump_buf << "   K_pu: [";
340             for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
341                 *dump_buf << name_info_pair.second.throttling_info->k_pu[i] << " ";
342             }
343             *dump_buf << "]" << std::endl;
344             *dump_buf << "   K_i: [";
345             for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
346                 *dump_buf << name_info_pair.second.throttling_info->k_i[i] << " ";
347             }
348             *dump_buf << "]" << std::endl;
349             *dump_buf << "   K_d: [";
350             for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
351                 *dump_buf << name_info_pair.second.throttling_info->k_d[i] << " ";
352             }
353             *dump_buf << "]" << std::endl;
354             *dump_buf << "   i_max: [";
355             for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
356                 *dump_buf << name_info_pair.second.throttling_info->i_max[i] << " ";
357             }
358             *dump_buf << "]" << std::endl;
359             *dump_buf << "   max_alloc_power: [";
360             for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
361                 *dump_buf << name_info_pair.second.throttling_info->max_alloc_power[i] << " ";
362             }
363             *dump_buf << "]" << std::endl;
364             *dump_buf << "   min_alloc_power: [";
365             for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
366                 *dump_buf << name_info_pair.second.throttling_info->min_alloc_power[i] << " ";
367             }
368             *dump_buf << "]" << std::endl;
369             *dump_buf << "   s_power: [";
370             for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
371                 *dump_buf << name_info_pair.second.throttling_info->s_power[i] << " ";
372             }
373             *dump_buf << "]" << std::endl;
374             *dump_buf << "   i_cutoff: [";
375             for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
376                 *dump_buf << name_info_pair.second.throttling_info->i_cutoff[i] << " ";
377             }
378             *dump_buf << "]" << std::endl;
379             *dump_buf << "  Binded CDEV Info:" << std::endl;
380             if (name_info_pair.second.throttling_info->binded_cdev_info_map.size()) {
381                 for (const auto &binded_cdev_info_pair :
382                      name_info_pair.second.throttling_info->binded_cdev_info_map) {
383                     *dump_buf << "   Cooling device name: " << binded_cdev_info_pair.first
384                               << std::endl;
385                     *dump_buf << "    WeightForPID: [";
386                     for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
387                         *dump_buf << binded_cdev_info_pair.second.cdev_weight_for_pid[i] << " ";
388                     }
389                     *dump_buf << "]" << std::endl;
390                     *dump_buf << "    Ceiling: [";
391                     for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
392                         *dump_buf << binded_cdev_info_pair.second.cdev_ceiling[i] << " ";
393                     }
394                     *dump_buf << "]" << std::endl;
395                     *dump_buf << "    Floor with PowerLink: [";
396                     for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
397                         *dump_buf << binded_cdev_info_pair.second.cdev_floor_with_power_link[i]
398                                   << " ";
399                     }
400                     *dump_buf << "]" << std::endl;
401                     *dump_buf << "    Hard limit: [";
402                     for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
403                         *dump_buf << binded_cdev_info_pair.second.limit_info[i] << " ";
404                     }
405                     *dump_buf << "]" << std::endl;
406 
407                     if (!binded_cdev_info_pair.second.power_rail.empty()) {
408                         *dump_buf << "    Binded power rail: "
409                                   << binded_cdev_info_pair.second.power_rail << std::endl;
410                         *dump_buf << "    Power threshold: [";
411                         for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
412                             *dump_buf << binded_cdev_info_pair.second.power_thresholds[i] << " ";
413                         }
414                         *dump_buf << "]" << std::endl;
415                         *dump_buf << "    Release logic: ";
416                         switch (binded_cdev_info_pair.second.release_logic) {
417                             case ReleaseLogic::INCREASE:
418                                 *dump_buf << "INCREASE";
419                                 break;
420                             case ReleaseLogic::DECREASE:
421                                 *dump_buf << "DECREASE";
422                                 break;
423                             case ReleaseLogic::STEPWISE:
424                                 *dump_buf << "STEPWISE";
425                                 break;
426                             case ReleaseLogic::RELEASE_TO_FLOOR:
427                                 *dump_buf << "RELEASE_TO_FLOOR";
428                                 break;
429                             default:
430                                 *dump_buf << "NONE";
431                                 break;
432                         }
433                         *dump_buf << std::endl;
434                         *dump_buf << "    high_power_check: " << std::boolalpha
435                                   << binded_cdev_info_pair.second.high_power_check << std::endl;
436                         *dump_buf << "    throttling_with_power_link: " << std::boolalpha
437                                   << binded_cdev_info_pair.second.throttling_with_power_link
438                                   << std::endl;
439                     }
440                 }
441             }
442         }
443     }
444 }
445 
dumpThrottlingRequestStatus(std::ostringstream * dump_buf)446 void Thermal::dumpThrottlingRequestStatus(std::ostringstream *dump_buf) {
447     const auto &sensor_status_map = thermal_helper_.GetSensorStatusMap();
448     const auto &cdev_status_map = thermal_helper_.GetCdevStatusMap();
449     const auto &release_map = thermal_helper_.GetThrottlingReleaseMap();
450     *dump_buf << "Throttling Request Status " << std::endl;
451     for (const auto &cdev_status_pair : cdev_status_map) {
452         *dump_buf << " Name: " << cdev_status_pair.first << std::endl;
453         for (const auto &request_pair : cdev_status_pair.second) {
454             *dump_buf << "  Request Sensor: " << request_pair.first << std::endl;
455             *dump_buf << "   Request Throttling State: " << request_pair.second << std::endl;
456             if (sensor_status_map.at(request_pair.first).pid_request_map.size() &&
457                 sensor_status_map.at(request_pair.first)
458                         .pid_request_map.count(cdev_status_pair.first)) {
459                 *dump_buf << "   PID Request State: "
460                           << sensor_status_map.at(request_pair.first)
461                                      .pid_request_map.at(cdev_status_pair.first)
462                           << std::endl;
463             }
464             if (sensor_status_map.at(request_pair.first).hard_limit_request_map.size() &&
465                 sensor_status_map.at(request_pair.first)
466                         .hard_limit_request_map.count(cdev_status_pair.first)) {
467                 *dump_buf << "   Hard Limit Request State: "
468                           << sensor_status_map.at(request_pair.first)
469                                      .hard_limit_request_map.at(cdev_status_pair.first)
470                           << std::endl;
471             }
472             if (release_map.count(request_pair.first) &&
473                 release_map.at(request_pair.first).count(cdev_status_pair.first)) {
474                 const auto &cdev_release_info =
475                         release_map.at(request_pair.first).at(cdev_status_pair.first);
476                 *dump_buf << "   Release Step: " << cdev_release_info.release_step << std::endl;
477             }
478         }
479     }
480 }
481 
dumpPowerRailInfo(std::ostringstream * dump_buf)482 void Thermal::dumpPowerRailInfo(std::ostringstream *dump_buf) {
483     const auto &power_rail_info_map = thermal_helper_.GetPowerRailInfoMap();
484     const auto &power_status_map = thermal_helper_.GetPowerStatusMap();
485 
486     *dump_buf << "Power Rail Info " << std::endl;
487     for (const auto &power_rail_pair : power_rail_info_map) {
488         *dump_buf << " Power Rail: " << power_rail_pair.first << std::endl;
489         *dump_buf << "  Power Sample Count: " << power_rail_pair.second.power_sample_count
490                   << std::endl;
491         *dump_buf << "  Power Sample Delay: " << power_rail_pair.second.power_sample_delay.count()
492                   << std::endl;
493         for (const auto &power_status_pair : power_status_map) {
494             if (power_status_pair.second.count(power_rail_pair.first)) {
495                 auto power_history =
496                         power_status_pair.second.at(power_rail_pair.first).power_history;
497                 *dump_buf << "  Request Sensor: " << power_status_pair.first << std::endl;
498                 *dump_buf
499                         << "   Last Updated AVG Power: "
500                         << power_status_pair.second.at(power_rail_pair.first).last_updated_avg_power
501                         << " mW" << std::endl;
502                 if (power_rail_pair.second.virtual_power_rail_info != nullptr) {
503                     *dump_buf << "   Formula=";
504                     switch (power_rail_pair.second.virtual_power_rail_info->formula) {
505                         case FormulaOption::COUNT_THRESHOLD:
506                             *dump_buf << "COUNT_THRESHOLD";
507                             break;
508                         case FormulaOption::WEIGHTED_AVG:
509                             *dump_buf << "WEIGHTED_AVG";
510                             break;
511                         case FormulaOption::MAXIMUM:
512                             *dump_buf << "MAXIMUM";
513                             break;
514                         case FormulaOption::MINIMUM:
515                             *dump_buf << "MINIMUM";
516                             break;
517                         default:
518                             *dump_buf << "NONE";
519                             break;
520                     }
521                     *dump_buf << std::endl;
522                 }
523                 for (size_t i = 0; i < power_history.size(); ++i) {
524                     if (power_rail_pair.second.virtual_power_rail_info != nullptr) {
525                         *dump_buf << "   Linked power rail "
526                                   << power_rail_pair.second.virtual_power_rail_info
527                                              ->linked_power_rails[i]
528                                   << std::endl;
529                         *dump_buf << "    Coefficient="
530                                   << power_rail_pair.second.virtual_power_rail_info->coefficients[i]
531                                   << std::endl;
532                         *dump_buf << "    Power Samples: ";
533                     } else {
534                         *dump_buf << "   Power Samples: ";
535                     }
536                     while (power_history[i].size() > 0) {
537                         const auto power_sample = power_history[i].front();
538                         power_history[i].pop();
539                         *dump_buf << "(T=" << power_sample.duration
540                                   << ", uWs=" << power_sample.energy_counter << ") ";
541                     }
542                     *dump_buf << std::endl;
543                 }
544             }
545         }
546     }
547 }
548 
debug(const hidl_handle & handle,const hidl_vec<hidl_string> &)549 Return<void> Thermal::debug(const hidl_handle &handle, const hidl_vec<hidl_string> &) {
550     if (handle != nullptr && handle->numFds >= 1) {
551         int fd = handle->data[0];
552         std::ostringstream dump_buf;
553 
554         if (!thermal_helper_.isInitializedOk()) {
555             dump_buf << "ThermalHAL not initialized properly." << std::endl;
556         } else {
557             {
558                 hidl_vec<Temperature_1_0> temperatures;
559                 dump_buf << "getTemperatures:" << std::endl;
560                 if (!thermal_helper_.fillTemperatures(&temperatures)) {
561                     dump_buf << "Failed to read thermal sensors." << std::endl;
562                 }
563 
564                 for (const auto &t : temperatures) {
565                     dump_buf << " Type: " << android::hardware::thermal::V1_0::toString(t.type)
566                              << " Name: " << t.name << " CurrentValue: " << t.currentValue
567                              << " ThrottlingThreshold: " << t.throttlingThreshold
568                              << " ShutdownThreshold: " << t.shutdownThreshold
569                              << " VrThrottlingThreshold: " << t.vrThrottlingThreshold << std::endl;
570                 }
571             }
572             {
573                 hidl_vec<CpuUsage> cpu_usages;
574                 dump_buf << "getCpuUsages:" << std::endl;
575                 if (!thermal_helper_.fillCpuUsages(&cpu_usages)) {
576                     dump_buf << "Failed to get CPU usages." << std::endl;
577                 }
578 
579                 for (const auto &usage : cpu_usages) {
580                     dump_buf << " Name: " << usage.name << " Active: " << usage.active
581                              << " Total: " << usage.total << " IsOnline: " << usage.isOnline
582                              << std::endl;
583                 }
584             }
585             {
586                 dump_buf << "getCurrentTemperatures:" << std::endl;
587                 hidl_vec<Temperature_2_0> temperatures;
588                 if (!thermal_helper_.fillCurrentTemperatures(
589                             false, false, TemperatureType_2_0::SKIN, &temperatures)) {
590                     dump_buf << "Failed to getCurrentTemperatures." << std::endl;
591                 }
592 
593                 for (const auto &t : temperatures) {
594                     dump_buf << " Type: " << android::hardware::thermal::V2_0::toString(t.type)
595                              << " Name: " << t.name << " CurrentValue: " << t.value
596                              << " ThrottlingStatus: "
597                              << android::hardware::thermal::V2_0::toString(t.throttlingStatus)
598                              << std::endl;
599                 }
600             }
601             {
602                 dump_buf << "getTemperatureThresholds:" << std::endl;
603                 hidl_vec<TemperatureThreshold> temperatures;
604                 if (!thermal_helper_.fillTemperatureThresholds(false, TemperatureType_2_0::SKIN,
605                                                                &temperatures)) {
606                     dump_buf << "Failed to getTemperatureThresholds." << std::endl;
607                 }
608 
609                 for (const auto &t : temperatures) {
610                     dump_buf << " Type: " << android::hardware::thermal::V2_0::toString(t.type)
611                              << " Name: " << t.name;
612                     dump_buf << " hotThrottlingThreshold: [";
613                     for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
614                         dump_buf << t.hotThrottlingThresholds[i] << " ";
615                     }
616                     dump_buf << "] coldThrottlingThreshold: [";
617                     for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
618                         dump_buf << t.coldThrottlingThresholds[i] << " ";
619                     }
620                     dump_buf << "] vrThrottlingThreshold: " << t.vrThrottlingThreshold;
621                     dump_buf << std::endl;
622                 }
623             }
624             {
625                 dump_buf << "getCurrentCoolingDevices:" << std::endl;
626                 hidl_vec<CoolingDevice_2_0> cooling_devices;
627                 if (!thermal_helper_.fillCurrentCoolingDevices(false, CoolingType::CPU,
628                                                                &cooling_devices)) {
629                     dump_buf << "Failed to getCurrentCoolingDevices." << std::endl;
630                 }
631 
632                 for (const auto &c : cooling_devices) {
633                     dump_buf << " Type: " << android::hardware::thermal::V2_0::toString(c.type)
634                              << " Name: " << c.name << " CurrentValue: " << c.value << std::endl;
635                 }
636             }
637             {
638                 dump_buf << "Callbacks: Total " << callbacks_.size() << std::endl;
639                 for (const auto &c : callbacks_) {
640                     dump_buf << " IsFilter: " << c.is_filter_type
641                              << " Type: " << android::hardware::thermal::V2_0::toString(c.type)
642                              << std::endl;
643                 }
644             }
645             {
646                 dump_buf << "getHysteresis:" << std::endl;
647                 const auto &map = thermal_helper_.GetSensorInfoMap();
648                 for (const auto &name_info_pair : map) {
649                     dump_buf << " Name: " << name_info_pair.first;
650                     dump_buf << " hotHysteresis: [";
651                     for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
652                         dump_buf << name_info_pair.second.hot_hysteresis[i] << " ";
653                     }
654                     dump_buf << "] coldHysteresis: [";
655                     for (size_t i = 0; i < kThrottlingSeverityCount; ++i) {
656                         dump_buf << name_info_pair.second.cold_hysteresis[i] << " ";
657                     }
658                     dump_buf << "]" << std::endl;
659                 }
660             }
661             {
662                 dump_buf << "SendCallback" << std::endl;
663                 dump_buf << "  Enabled List: ";
664                 const auto &map = thermal_helper_.GetSensorInfoMap();
665                 for (const auto &name_info_pair : map) {
666                     if (name_info_pair.second.send_cb) {
667                         dump_buf << name_info_pair.first << " ";
668                     }
669                 }
670                 dump_buf << std::endl;
671             }
672             {
673                 dump_buf << "SendPowerHint" << std::endl;
674                 dump_buf << "  Enabled List: ";
675                 const auto &map = thermal_helper_.GetSensorInfoMap();
676                 for (const auto &name_info_pair : map) {
677                     if (name_info_pair.second.send_powerhint) {
678                         dump_buf << name_info_pair.first << " ";
679                     }
680                 }
681                 dump_buf << std::endl;
682             }
683             dumpVirtualSensorInfo(&dump_buf);
684             dumpThrottlingInfo(&dump_buf);
685             dumpThrottlingRequestStatus(&dump_buf);
686             dumpPowerRailInfo(&dump_buf);
687             {
688                 dump_buf << "AIDL Power Hal exist: " << std::boolalpha
689                          << thermal_helper_.isAidlPowerHalExist() << std::endl;
690                 dump_buf << "AIDL Power Hal connected: " << std::boolalpha
691                          << thermal_helper_.isPowerHalConnected() << std::endl;
692                 dump_buf << "AIDL Power Hal Ext connected: " << std::boolalpha
693                          << thermal_helper_.isPowerHalExtConnected() << std::endl;
694             }
695         }
696         std::string buf = dump_buf.str();
697         if (!android::base::WriteStringToFd(buf, fd)) {
698             PLOG(ERROR) << "Failed to dump state to fd";
699         }
700         fsync(fd);
701     }
702     return Void();
703 }
704 
705 }  // namespace implementation
706 }  // namespace V2_0
707 }  // namespace thermal
708 }  // namespace hardware
709 }  // namespace android
710