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