1 /*
2 * Copyright 2023 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 <cstring>
18 #include <dirent.h>
19 #include <dump/pixel_dump.h>
20 #include <fstream>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <sys/sysinfo.h>
24 #include <sys/wait.h>
25 #include <time.h>
26 #include <unistd.h>
27 #include <vector>
28
29 #include <android-base/file.h>
30 #include <android-base/strings.h>
31 #include "DumpstateUtil.h"
32
33
printTitle(const char * msg)34 void printTitle(const char *msg) {
35 printf("\n------ %s ------\n", msg);
36 }
37
getCommandOutput(const char * cmd,std::string * output)38 int getCommandOutput(const char *cmd, std::string *output) {
39 char buffer[1024];
40 FILE *pipe = popen(cmd, "r");
41 if (!pipe) {
42 return -1;
43 }
44
45 while (fgets(buffer, sizeof buffer, pipe) != NULL) {
46 *output += buffer;
47 }
48 pclose(pipe);
49
50 if (output->back() == '\n')
51 output->pop_back();
52
53 return 0;
54 }
55
isValidFile(const char * file)56 bool isValidFile(const char *file) {
57 FILE *fp = fopen(file, "r");
58 if (fp != NULL) {
59 fclose(fp);
60 return true;
61 }
62 return false;
63 }
64
isValidDir(const char * directory)65 bool isValidDir(const char *directory) {
66 DIR *dir = opendir(directory);
67 if (dir == NULL)
68 return false;
69
70 closedir(dir);
71 return true;
72 }
73
isUserBuild()74 bool isUserBuild() {
75 return ::android::os::dumpstate::PropertiesHelper::IsUserBuild();
76 }
77
getFilesInDir(const char * directory,std::vector<std::string> * files)78 int getFilesInDir(const char *directory, std::vector<std::string> *files) {
79 std::string content;
80 struct dirent *entry;
81
82 DIR *dir = opendir(directory);
83 if (dir == NULL)
84 return -1;
85
86 files->clear();
87 while ((entry = readdir(dir)) != NULL)
88 files->push_back(entry->d_name);
89 closedir(dir);
90
91 sort(files->begin(), files->end());
92 return 0;
93 }
94
dumpPowerStatsTimes()95 void dumpPowerStatsTimes() {
96 const char *title = "Power Stats Times";
97 char rBuff[128];
98 struct timespec rTs;
99 struct sysinfo info;
100 int ret;
101
102 printTitle(title);
103
104 sysinfo(&info);
105
106 const time_t boottime = time(NULL) - info.uptime;
107
108 ret = clock_gettime(CLOCK_REALTIME, &rTs);
109 if (ret)
110 return;
111
112 struct tm *nowTime = std::localtime(&rTs.tv_sec);
113
114 std::strftime(rBuff, sizeof(rBuff), "%m/%d/%Y %H:%M:%S", nowTime);
115 printf("Boot: %s", ctime(&boottime));
116 printf("Now: %s\n", rBuff);
117 }
118
readContentsOfDir(const char * title,const char * directory,const char * strMatch,bool useStrMatch=false,bool printDirectory=false)119 int readContentsOfDir(const char* title, const char* directory, const char* strMatch,
120 bool useStrMatch = false, bool printDirectory = false) {
121 std::vector<std::string> files;
122 std::string content;
123 std::string fileLocation;
124 int ret;
125
126 ret = getFilesInDir(directory, &files);
127 if (ret < 0)
128 return ret;
129
130 printTitle(title);
131 for (auto &file : files) {
132 if (useStrMatch && std::string::npos == std::string(file).find(strMatch)) {
133 continue;
134 }
135
136 fileLocation = std::string(directory) + std::string(file);
137 if (!android::base::ReadFileToString(fileLocation, &content)) {
138 continue;
139 }
140 if (printDirectory) {
141 printf("\n\n%s\n", fileLocation.c_str());
142 }
143 if (content.back() == '\n')
144 content.pop_back();
145 printf("%s\n", content.c_str());
146 }
147 return 0;
148 }
149
dumpAcpmStats()150 void dumpAcpmStats() {
151 const char* acpmDir = "/sys/devices/platform/acpm_stats/";
152 const char* statsSubStr = "_stats";
153 const char* acpmTitle = "ACPM stats";
154 readContentsOfDir(acpmTitle, acpmDir, statsSubStr, true, true);
155 }
156
dumpTcpmPsyUevent()157 void dumpTcpmPsyUevent() {
158 const char* tcpmPsy = "tcpm-source-psy-";
159 DIR *dir = opendir("/sys/class/power_supply/");
160 struct dirent *entry;
161
162 if (dir == NULL)
163 return;
164
165 while ((entry = readdir(dir)) != NULL) {
166 if (std::string::npos != std::string(entry->d_name).find(tcpmPsy)) {
167 std::string fullPath("/sys/class/power_supply/" + (const std::string)entry->d_name +
168 "/uevent");
169 dumpFileContent("Power supply property tcpm", fullPath.c_str());
170 break;
171 }
172 }
173
174 closedir(dir);
175 }
176
dumpPowerSupplyStats()177 void dumpPowerSupplyStats() {
178 const char* dumpList[][2] = {
179 {"CPU PM stats", "/sys/devices/system/cpu/cpupm/cpupm/time_in_state"},
180 {"GENPD summary", "/d/pm_genpd/pm_genpd_summary"},
181 {"Power supply property battery", "/sys/class/power_supply/battery/uevent"},
182 {"Power supply property dc", "/sys/class/power_supply/dc/uevent"},
183 {"Power supply property gcpm", "/sys/class/power_supply/gcpm/uevent"},
184 {"Power supply property gcpm_pps", "/sys/class/power_supply/gcpm_pps/uevent"},
185 {"Power supply property main-charger", "/sys/class/power_supply/main-charger/uevent"},
186 {"Power supply property dc-mains", "/sys/class/power_supply/dc-mains/uevent"},
187 {"Power supply property usb", "/sys/class/power_supply/usb/uevent"},
188 {"Power supply property wireless", "/sys/class/power_supply/wireless/uevent"},
189 };
190
191 for (const auto &row : dumpList) {
192 dumpFileContent(row[0], row[1]);
193 }
194
195 dumpTcpmPsyUevent();
196 }
197
dumpMaxFg()198 void dumpMaxFg() {
199 const char *maxfgLoc = "/sys/class/power_supply/maxfg";
200
201 const char *maxfg [][2] = {
202 {"Power supply property maxfg", "/sys/class/power_supply/maxfg/uevent"},
203 {"maxfg registers", "/sys/class/power_supply/maxfg/registers_dump"},
204 {"m5_state", "/sys/class/power_supply/maxfg/m5_model_state"},
205 {"maxfg logbuffer", "/dev/logbuffer_maxfg"},
206 {"maxfg_monitor logbuffer", "/dev/logbuffer_maxfg_monitor"},
207 };
208
209 std::string content;
210
211 if (isValidDir(maxfgLoc)) {
212 for (const auto &row : maxfg) {
213 dumpFileContent(row[0], row[1]);
214 }
215 }
216 }
217
dumpPowerSupplyDock()218 void dumpPowerSupplyDock() {
219 const char* powerSupplyPropertyDockTitle = "Power supply property dock";
220 const char* powerSupplyPropertyDockFile = "/sys/class/power_supply/dock/uevent";
221 if (isValidFile(powerSupplyPropertyDockFile)) {
222 dumpFileContent(powerSupplyPropertyDockTitle, powerSupplyPropertyDockFile);
223 }
224 }
225
dumpLogBufferTcpm()226 void dumpLogBufferTcpm() {
227 const char* logbufferTcpmTitle = "Logbuffer TCPM";
228 const char* logbufferTcpmFile = "/dev/logbuffer_tcpm";
229 const char* debugTcpmFile = "/sys/kernel/debug/tcpm";
230 const char* tcpmLogTitle = "TCPM logs";
231 const char* tcpmFile = "/sys/kernel/debug/tcpm";
232 const char* tcpmFileAlt = "/sys/kernel/debug/usb/tcpm";
233 int retCode;
234
235 dumpFileContent(logbufferTcpmTitle, logbufferTcpmFile);
236
237 retCode = readContentsOfDir(tcpmLogTitle, isValidFile(debugTcpmFile) ? tcpmFile : tcpmFileAlt,
238 NULL);
239 if (retCode < 0)
240 printTitle(tcpmLogTitle);
241 }
242
dumpTcpc()243 void dumpTcpc() {
244 const char* max77759TcpcHead = "TCPC Device Attributes";
245 const char* directory = "/sys/class/typec/port0/device";
246 const char* max77759Tcpc [] {
247 "auto_discharge",
248 "bc12_enabled",
249 "cc_toggle_enable",
250 "contaminant_detection",
251 "contaminant_detection_status",
252 "frs",
253 "irq_hpd_count",
254 "non_compliant_reasons",
255 "sbu_pullup",
256 "update_sdp_enum_timeout",
257 "usb_limit_accessory_current",
258 "usb_limit_accessory_enable",
259 "usb_limit_sink_current",
260 "usb_limit_sink_enable",
261 "usb_limit_source_enable",
262 };
263
264 std::string content;
265 std::string tcpcRegistersPath(std::string(directory) + "/registers");
266
267 dumpFileContent("TCPC Registers", tcpcRegistersPath.c_str());
268
269 printTitle(max77759TcpcHead);
270
271 for (auto& tcpcVal : max77759Tcpc) {
272 std::string filename = std::string(directory) + "/" + std::string(tcpcVal);
273 printf("%s: ", tcpcVal);
274 android::base::ReadFileToString(filename, &content);
275 if (!content.empty() && (content.back() == '\n' || content.back() == '\r'))
276 content.pop_back();
277 printf("%s\n", content.c_str());
278 }
279 printf("\n");
280 }
281
dumpPdEngine()282 void dumpPdEngine() {
283 const char* pdEngine [][2] {
284 {"Logbuffer TCPC", "/dev/logbuffer_usbpd"},
285 {"PPS-google_cpm logbuffer", "/dev/logbuffer_cpm"},
286 {"PPS-pca9468 logbuffer", "/dev/logbuffer_pca9468"},
287 {"PPS-dc_mains logbuffer", "/dev/logbuffer_dc_mains"},
288 };
289
290 for (const auto &row : pdEngine) {
291 dumpFileContent(row[0], row[1]);
292 }
293 }
294
dumpEusbRepeater()295 void dumpEusbRepeater() {
296 const char* dumpTitle = "registers dump of eUSB repeater";
297 const char* dumpFile = "/d/eusb_repeater/registers";
298
299 if (isValidFile(dumpFile)) {
300 dumpFileContent(dumpTitle, dumpFile);
301 }
302 }
303
dumpWc68()304 void dumpWc68() {
305 const char* wc68Title = "WC68";
306 const char* wc68File = "/dev/logbuffer_wc68";
307
308 if (isValidFile(wc68File)) {
309 dumpFileContent(wc68Title, wc68File);
310 }
311 }
312
dumpBatteryHealth()313 void dumpBatteryHealth() {
314 const char* batteryHealth [][2] {
315 {"Battery Health", "/sys/class/power_supply/battery/health_index_stats"},
316 {"Battery Health SoC Residency", "/sys/class/power_supply/battery/swelling_data"},
317 {"BMS", "/dev/logbuffer_ssoc"},
318 {"TTF", "/dev/logbuffer_ttf"},
319 {"TTF details", "/sys/class/power_supply/battery/ttf_details"},
320 {"TTF stats", "/sys/class/power_supply/battery/ttf_stats"},
321 {"aacr_state", "/sys/class/power_supply/battery/aacr_state"},
322 {"maxq", "/dev/logbuffer_maxq"},
323 {"TEMP/DOCK-DEFEND", "/dev/logbuffer_bd"},
324 };
325
326 for (const auto &row : batteryHealth) {
327 dumpFileContent(row[0], row[1]);
328 }
329 }
330
dumpBatteryDefend()331 void dumpBatteryDefend() {
332 const char* defendConfig [][3] {
333 {"TRICKLE-DEFEND Config",
334 "/sys/devices/platform/google,battery/power_supply/battery/", "bd_"},
335 {"DWELL-DEFEND Config", "/sys/devices/platform/google,charger/", "charge_s"},
336 {"DWELL-DEFEND Time", "/mnt/vendor/persist/battery/", "defender_"},
337 {"TEMP-DEFEND Config", "/sys/devices/platform/google,charger/", "bd_"},
338 };
339
340 std::vector<std::string> files;
341 struct dirent *entry;
342 std::string content;
343 std::string fileLocation;
344
345 for (auto &config : defendConfig) {
346 DIR *dir = opendir(config[1]);
347 if (dir == NULL)
348 continue;
349
350 printTitle(config[0]);
351 while ((entry = readdir(dir)) != NULL) {
352 if (std::string(entry->d_name).find(config[2]) != std::string::npos &&
353 strncmp(config[2], entry->d_name, strlen(config[2])) == 0) {
354 files.push_back(entry->d_name);
355 }
356 }
357 closedir(dir);
358
359 sort(files.begin(), files.end());
360
361 for (auto &file : files) {
362 fileLocation = std::string(config[1]) + std::string(file);
363 if (!android::base::ReadFileToString(fileLocation, &content) || content.empty()) {
364 content = "\n";
365 }
366
367 printf("%s: %s", file.c_str(), content.c_str());
368
369 if (content.back() != '\n')
370 printf("\n");
371 }
372
373 files.clear();
374 }
375 }
376
dumpBatteryCaretaker()377 void dumpBatteryCaretaker() {
378 const char* aacpConfig [][3] {
379 {"AACP Version",
380 "/sys/devices/platform/google,battery/power_supply/battery/", "aacp_"},
381 {"AACR Config",
382 "/sys/devices/platform/google,battery/power_supply/battery/", "aacr_"},
383 {"AAFV Config",
384 "/sys/devices/platform/google,battery/power_supply/battery/", "aafv_"},
385 {"AACT Config",
386 "/sys/devices/platform/google,battery/power_supply/battery/", "aact_"},
387 {"AACC",
388 "/sys/devices/platform/google,battery/power_supply/battery/", "aacc"},
389 };
390
391 std::vector<std::string> files;
392 struct dirent *entry;
393 std::string content;
394 std::string fileLocation;
395
396 for (auto &config : aacpConfig) {
397 DIR *dir = opendir(config[1]);
398 if (dir == NULL)
399 continue;
400
401 printTitle(config[0]);
402 while ((entry = readdir(dir)) != NULL) {
403 if (std::string(entry->d_name).find(config[2]) != std::string::npos &&
404 strncmp(config[2], entry->d_name, strlen(config[2])) == 0) {
405 files.push_back(entry->d_name);
406 }
407 }
408 closedir(dir);
409
410 sort(files.begin(), files.end());
411
412 for (auto &file : files) {
413 fileLocation = std::string(config[1]) + std::string(file);
414 if (!android::base::ReadFileToString(fileLocation, &content) || content.empty()) {
415 content = "\n";
416 }
417
418 printf("%s: %s", file.c_str(), content.c_str());
419
420 if (content.back() != '\n')
421 printf("\n");
422 }
423
424 files.clear();
425 }
426 }
427
printValuesOfDirectory(const char * directory,std::string debugfs,const char * strMatch)428 void printValuesOfDirectory(const char *directory, std::string debugfs, const char *strMatch) {
429 std::vector<std::string> files;
430 auto info = directory;
431 std::string content;
432 struct dirent *entry;
433 DIR *dir = opendir(debugfs.c_str());
434 if (dir == NULL)
435 return;
436
437 printTitle((debugfs + std::string(strMatch) + "/" + std::string(info)).c_str());
438 while ((entry = readdir(dir)) != NULL)
439 if (std::string(entry->d_name).find(strMatch) != std::string::npos)
440 files.push_back(entry->d_name);
441 closedir(dir);
442
443 sort(files.begin(), files.end());
444
445 for (auto &file : files) {
446 std::string fileDirectory = debugfs + file;
447 std::string fileLocation = fileDirectory + "/" + std::string(info);
448 if (!android::base::ReadFileToString(fileLocation, &content)) {
449 content = "\n";
450 }
451
452 printf("%s:\n%s", fileDirectory.c_str(), content.c_str());
453
454 if (content.back() != '\n')
455 printf("\n");
456 }
457 files.clear();
458 }
459
dumpChg()460 void dumpChg() {
461 const std::string pmic_bus = "/sys/devices/platform/10cb0000.hsi2c/i2c-11/11-0066";
462 const char* chg_reg_dump_file = "/sys/class/power_supply/main-charger/device/registers_dump";
463 const std::string chg_name_cmd = "/sys/class/power_supply/main-charger/device/name";
464 const std::string pmic_name_cmd = pmic_bus + "/name";
465 const std::string pmic_reg_dump_file = pmic_bus + "/registers_dump";
466 const std::string reg_dump_str = " registers dump";
467 const char* chgConfig [][2] {
468 {"DC_registers dump", "/sys/class/power_supply/dc-mains/device/registers_dump"},
469 };
470 std::string chg_name;
471 std::string pmic_name;
472
473 printf("\n");
474
475 int ret = android::base::ReadFileToString(chg_name_cmd, &chg_name);
476 if (ret && !chg_name.empty()) {
477 chg_name.erase(chg_name.length() - 1); // remove new line
478 const std::string chg_reg_dump_title = chg_name + reg_dump_str;
479
480 /* CHG reg dump */
481 dumpFileContent(chg_reg_dump_title.c_str(), chg_reg_dump_file);
482 }
483
484 ret = android::base::ReadFileToString(pmic_name_cmd, &pmic_name);
485 if (ret && !pmic_name.empty()) {
486 pmic_name.erase(pmic_name.length() - 1); // remove new line
487 const std::string pmic_reg_dump_title = pmic_name + reg_dump_str;
488
489 /* PMIC reg dump */
490 dumpFileContent(pmic_reg_dump_title.c_str(), pmic_reg_dump_file.c_str());
491 }
492
493 for (auto &config : chgConfig) {
494 dumpFileContent(config[0], config[1]);
495 }
496 }
497
dumpChgUserDebug()498 void dumpChgUserDebug() {
499 const std::string debugfs = "/d/";
500 const char *maxFgDir = "/d/maxfg";
501 const char *maxFgStrMatch = "maxfg";
502 const char *chgTblName = "Charging table dump";
503 const char *chgTblDir = "/d/google_battery/chg_raw_profile";
504
505 const char *maxFgInfo [] {
506 "fg_model",
507 "algo_ver",
508 "model_ok",
509 };
510
511 if (isUserBuild())
512 return;
513
514 dumpFileContent(chgTblName, chgTblDir);
515
516 if (isValidDir(maxFgDir)) {
517 for (auto & directory : maxFgInfo) {
518 printValuesOfDirectory(directory, debugfs, maxFgStrMatch);
519 }
520 }
521 }
522
dumpBatteryEeprom()523 void dumpBatteryEeprom() {
524 const char *title = "Battery EEPROM";
525 const char *files[] {
526 "/sys/devices/platform/10c90000.hsi2c/i2c-9/9-0050/eeprom",
527 };
528 std::string result;
529 std::string xxdCmd;
530
531 printTitle(title);
532 for (auto &file : files) {
533 if (!isValidFile(file))
534 continue;
535
536 xxdCmd = "xxd " + std::string(file);
537
538 int ret = getCommandOutput(xxdCmd.c_str(), &result);
539 if (ret < 0)
540 return;
541
542 printf("%s\n", result.c_str());
543 }
544 }
545
dumpChargerStats()546 void dumpChargerStats() {
547 const char *chgStatsTitle = "Charger Stats";
548 const char *chgStatsLocation = "/sys/class/power_supply/battery/charge_details";
549 const char *chargerStats [][3] {
550 {"Google Charger", "/sys/kernel/debug/google_charger/", "pps_"},
551 {"Google Battery", "/sys/kernel/debug/google_battery/", "ssoc_"},
552 };
553 std::vector<std::string> files;
554 std::string content;
555 struct dirent *entry;
556
557 dumpFileContent(chgStatsTitle, chgStatsLocation);
558
559 if (isUserBuild())
560 return;
561
562 for (auto &stat : chargerStats) {
563 DIR *dir = opendir(stat[1]);
564 if (dir == NULL)
565 return;
566
567 printTitle(stat[0]);
568 while ((entry = readdir(dir)) != NULL)
569 if (std::string(entry->d_name).find(stat[2]) != std::string::npos)
570 files.push_back(entry->d_name);
571 closedir(dir);
572
573 sort(files.begin(), files.end());
574
575 for (auto &file : files) {
576 std::string fileLocation = std::string(stat[1]) + file;
577 if (!android::base::ReadFileToString(fileLocation, &content)) {
578 content = "\n";
579 }
580
581 printf("%s: %s", file.c_str(), content.c_str());
582
583 if (content.back() != '\n')
584 printf("\n");
585 }
586 files.clear();
587 }
588 }
589
dumpWlcLogs()590 void dumpWlcLogs() {
591 const char *dumpWlcList [][2] {
592 {"WLC Logs", "/dev/logbuffer_wireless"},
593 {"WLC VER", "/sys/class/power_supply/wireless/device/version"},
594 {"WLC STATUS", "/sys/class/power_supply/wireless/device/status"},
595 {"WLC FW Version", "/sys/class/power_supply/wireless/device/fw_rev"},
596 {"RTX", "/dev/logbuffer_rtx"},
597 };
598
599 for (auto &row : dumpWlcList) {
600 if (!isValidFile(row[1]))
601 printTitle(row[0]);
602 dumpFileContent(row[0], row[1]);
603 }
604 }
605
dumpGvoteables()606 void dumpGvoteables() {
607 const char *directory = "/sys/kernel/debug/gvotables/";
608 const char *statusName = "/status";
609 const char *title = "gvotables";
610 std::string content;
611 std::vector<std::string> files;
612 int ret;
613
614 if (isUserBuild())
615 return;
616
617 ret = getFilesInDir(directory, &files);
618 if (ret < 0)
619 return;
620
621 printTitle(title);
622 for (auto &file : files) {
623 std::string fileLocation = std::string(directory) + file + std::string(statusName);
624 if (!android::base::ReadFileToString(fileLocation, &content)) {
625 continue;
626 }
627
628 printf("%s: %s", file.c_str(), content.c_str());
629
630 if (content.back() != '\n')
631 printf("\n");
632 }
633 files.clear();
634 }
635
dumpMitigation()636 void dumpMitigation() {
637 const char *mitigationList [][2] {
638 {"LastmealCSV" , "/data/vendor/mitigation/lastmeal.csv"},
639 {"Lastmeal" , "/data/vendor/mitigation/lastmeal.txt"},
640 {"Thismeal" , "/data/vendor/mitigation/thismeal.txt"},
641 };
642
643 /* parsing thismeal.bin */
644 int status;
645 int pid = fork();
646 if (pid < 0) {
647 printf("Fork failed for parsing thismeal.bin.\n");
648 exit(EXIT_FAILURE);
649 } else if (pid == 0) {
650 execl("/vendor/bin/hw/battery_mitigation", "battery_mitigation", "-d", nullptr);
651 exit(EXIT_SUCCESS);
652 }
653 waitpid(pid, &status, 0);
654
655 if (WIFSIGNALED(status)) {
656 printf("Failed to parse thismeal.bin.(killed by: %d)\n", WTERMSIG(status));
657 }
658
659 for (auto &row : mitigationList) {
660 if (!isValidFile(row[1]))
661 printTitle(row[0]);
662 dumpFileContent(row[0], row[1]);
663 }
664 }
665
dumpMitigationStats()666 void dumpMitigationStats() {
667 int ret;
668 const char *directory = "/sys/devices/virtual/pmic/mitigation/last_triggered_count/";
669 const char *capacityDirectory = "/sys/devices/virtual/pmic/mitigation/last_triggered_capacity/";
670 const char *timestampDirectory =
671 "/sys/devices/virtual/pmic/mitigation/last_triggered_timestamp/";
672 const char *voltageDirectory = "/sys/devices/virtual/pmic/mitigation/last_triggered_voltage/";
673 const char *capacitySuffix = "_cap";
674 const char *timeSuffix = "_time";
675 const char *voltageSuffix = "_volt";
676 const char *countSuffix = "_count";
677 const char *title = "Mitigation Stats";
678
679 std::vector<std::string> files;
680 std::string content;
681 std::string fileLocation;
682 std::string source;
683 std::string subModuleName;
684 int count;
685 int soc;
686 int time;
687 int voltage;
688
689 ret = getFilesInDir(directory, &files);
690 if (ret < 0)
691 return;
692
693 printTitle(title);
694 printf("Source\t\tCount\tSOC\tTime\tVoltage\n");
695
696 for (auto &file : files) {
697 fileLocation = std::string(directory) + std::string(file);
698 if (!android::base::ReadFileToString(fileLocation, &content)) {
699 continue;
700 }
701
702 ret = atoi(android::base::Trim(content).c_str());
703 if (ret == -1)
704 continue;
705 count = ret;
706
707 subModuleName = std::string(file);
708 subModuleName.erase(subModuleName.find(countSuffix), strlen(countSuffix));
709
710 fileLocation = std::string(capacityDirectory) + std::string(subModuleName) +
711 std::string(capacitySuffix);
712 if (!android::base::ReadFileToString(fileLocation, &content)) {
713 continue;
714 }
715 ret = atoi(android::base::Trim(content).c_str());
716 if (ret == -1)
717 continue;
718 soc = ret;
719
720 fileLocation = std::string(timestampDirectory) + std::string(subModuleName) +
721 std::string(timeSuffix);
722 if (!android::base::ReadFileToString(fileLocation, &content)) {
723 continue;
724 }
725 ret = atoi(android::base::Trim(content).c_str());
726 if (ret == -1)
727 continue;
728 time = ret;
729
730 fileLocation = std::string(voltageDirectory) + std::string(subModuleName) +
731 std::string(voltageSuffix);
732 if (!android::base::ReadFileToString(fileLocation, &content)) {
733 continue;
734 }
735 ret = atoi(android::base::Trim(content).c_str());
736 if (ret == -1)
737 continue;
738 voltage = ret;
739 printf("%s \t%i\t%i\t%i\t%i\n", subModuleName.c_str(), count, soc, time, voltage);
740 }
741 }
742
dumpMitigationDirs()743 void dumpMitigationDirs() {
744 const int paramCount = 4;
745 const char *titles[] = {
746 "Clock Divider Ratio",
747 "Clock Stats",
748 "Triggered Level",
749 "Instruction",
750 };
751 const char *directories[] = {
752 "/sys/devices/virtual/pmic/mitigation/clock_ratio/",
753 "/sys/devices/virtual/pmic/mitigation/clock_stats/",
754 "/sys/devices/virtual/pmic/mitigation/triggered_lvl/",
755 "/sys/devices/virtual/pmic/mitigation/instruction/",
756 };
757 const char *paramSuffix[] = {"_ratio", "_stats", "_lvl", ""};
758 const char *titleRowVal[] = {
759 "Source\t\tRatio",
760 "Source\t\tStats",
761 "Source\t\tLevel",
762 "",
763 };
764 const int eraseCnt[] = {6, 6, 4, 0};
765 const bool useTitleRow[] = {true, true, true, false};
766
767 std::vector<std::string> files;
768 std::string content;
769 std::string fileLocation;
770 std::string source;
771 std::string subModuleName;
772 std::string readout;
773
774 for (int i = 0; i < paramCount; i++) {
775 printTitle(titles[i]);
776 if (useTitleRow[i]) {
777 printf("%s\n", titleRowVal[i]);
778 }
779
780 getFilesInDir(directories[i], &files);
781
782 for (auto &file : files) {
783 fileLocation = std::string(directories[i]) + std::string(file);
784 if (!android::base::ReadFileToString(fileLocation, &content)) {
785 continue;
786 }
787
788 readout = android::base::Trim(content);
789
790 subModuleName = std::string(file);
791 subModuleName.erase(subModuleName.find(paramSuffix[i]), eraseCnt[i]);
792
793 if (useTitleRow[i]) {
794 printf("%s \t%s\n", subModuleName.c_str(), readout.c_str());
795 } else {
796 printf("%s=%s\n", subModuleName.c_str(), readout.c_str());
797 }
798 }
799 }
800 }
801
dumpIrqDurationCounts()802 void dumpIrqDurationCounts() {
803 const char *title = "IRQ Duration Counts";
804 const char *colNames = "Source\t\t\t\tlt_5ms_cnt\tbt_5ms_to_10ms_cnt\tgt_10ms_cnt\tCode"
805 "\tCurrent Threshold (uA)\tCurrent Reading (uA)\n";
806 const int nonOdpmChannelCnt = 9;
807 const int odpmChCnt = 12;
808
809 enum Duration {
810 LT_5MS,
811 BT_5MS_10MS,
812 GT_10MS,
813 DUR_MAX,
814 };
815 const char *irqDurDirectories[] = {
816 "/sys/devices/virtual/pmic/mitigation/irq_dur_cnt/less_than_5ms_count",
817 "/sys/devices/virtual/pmic/mitigation/irq_dur_cnt/between_5ms_to_10ms_count",
818 "/sys/devices/virtual/pmic/mitigation/irq_dur_cnt/greater_than_10ms_count",
819 };
820
821 enum PowerWarn {
822 MAIN,
823 SUB,
824 PWRWARN_MAX,
825 };
826 const char *pwrwarnDirectories[] = {
827 "/sys/devices/virtual/pmic/mitigation/main_pwrwarn/",
828 "/sys/devices/virtual/pmic/mitigation/sub_pwrwarn/",
829 };
830
831 const char *lpfCurrentDirs[] = {
832 "/sys/devices/platform/acpm_mfd_bus@15500000/i2c-7/7-001f/s2mpg14-meter/"
833 "s2mpg14-odpm/iio:device1/lpf_current",
834 "/sys/devices/platform/acpm_mfd_bus@15510000/i2c-8/8-002f/s2mpg15-meter/"
835 "s2mpg15-odpm/iio:device0/lpf_current",
836 };
837
838 bool titlesInitialized = false;
839
840 std::vector<std::string> channelNames;
841 std::vector<std::string> channelData[DUR_MAX];
842 std::vector<std::string> pwrwarnThreshold[PWRWARN_MAX];
843 std::vector<std::string> pwrwarnCode[PWRWARN_MAX];
844 std::vector<std::string> lpfCurrentVals[PWRWARN_MAX];
845 std::vector<std::string> files;
846
847 std::string content;
848 std::string token;
849 std::string tokenCh;
850 std::string fileLocation;
851
852 for (int i = 0; i < DUR_MAX; i++) {
853 if (!android::base::ReadFileToString(irqDurDirectories[i], &content)) {
854 return;
855 }
856
857 std::istringstream tokenStream(content);
858
859 while (std::getline(tokenStream, token, '\n')) {
860 if (!titlesInitialized) {
861 tokenCh = token;
862 tokenCh.erase(tokenCh.find(':'), tokenCh.length());
863 channelNames.push_back(tokenCh);
864 }
865
866 // there is a space after the ':' which needs to be removed
867 token.erase(0, token.find(':') + 1);
868 channelData[i].push_back(token);
869
870 }
871 if (!titlesInitialized)
872 titlesInitialized = true;
873 }
874
875 for (int i = 0; i < PWRWARN_MAX; i++) {
876 getFilesInDir(pwrwarnDirectories[i], &files);
877
878 for (auto &file : files) {
879 fileLocation = std::string(pwrwarnDirectories[i]) + std::string(file);
880 if (!android::base::ReadFileToString(fileLocation, &content)) {
881 continue;
882 }
883
884 std::string readout;
885
886 readout = android::base::Trim(content);
887
888 std::string readoutThreshold = readout;
889 readoutThreshold.erase(0, readoutThreshold.find('=') + 1);
890
891 std::string readoutCode = readout;
892 readoutCode.erase(readoutCode.find('='), readoutCode.length());
893
894 pwrwarnThreshold[i].push_back(readoutThreshold);
895 pwrwarnCode[i].push_back(readoutCode);
896 }
897 }
898
899 for (int i = 0; i < PWRWARN_MAX; i++) {
900 if (!android::base::ReadFileToString(lpfCurrentDirs[i], &content)) {
901 continue;
902 }
903
904 std::istringstream tokenStream(content);
905
906 bool first = true;
907 while (std::getline(tokenStream, token, '\n')) {
908 token.erase(0, token.find(' '));
909 if (first) {
910 first = false;
911 continue;
912 }
913 lpfCurrentVals[i].push_back(token);
914 }
915 }
916
917 printTitle(title);
918 printf("%s", colNames);
919
920 for (uint i = 0; i < channelNames.size(); i++) {
921 std::string code = "";
922 std::string threshold = "";
923 std::string current = "";
924 std::string ltDataMsg = "";
925 std::string btDataMsg = "";
926 std::string gtDataMsg = "";
927 int pmicSel = 0;
928 int offset = 0;
929 std::string channelNameSuffix = " \t";
930 if (i >= nonOdpmChannelCnt) {
931 offset = nonOdpmChannelCnt;
932 if (i >= (odpmChCnt + nonOdpmChannelCnt)) {
933 pmicSel = 1;
934 offset = odpmChCnt + nonOdpmChannelCnt;
935 }
936 channelNameSuffix = "";
937
938 code = pwrwarnCode[pmicSel][i - offset];
939 threshold = pwrwarnThreshold[pmicSel][i - offset];
940 current = lpfCurrentVals[pmicSel][i - offset];
941 }
942
943 if (i < channelData[0].size())
944 ltDataMsg = channelData[0][i];
945
946 if (i < channelData[1].size())
947 btDataMsg = channelData[1][i];
948
949 if (i < channelData[2].size())
950 gtDataMsg = channelData[2][i];
951
952 std::string adjustedChannelName = channelNames[i] + channelNameSuffix;
953 printf("%s \t%s\t\t%s\t\t\t%s\t\t%s \t%s \t\t%s\n",
954 adjustedChannelName.c_str(),
955 ltDataMsg.c_str(),
956 btDataMsg.c_str(),
957 gtDataMsg.c_str(),
958 code.c_str(),
959 threshold.c_str(),
960 current.c_str());
961 }
962 }
963
dumpCpuIdleHistogramStats()964 void dumpCpuIdleHistogramStats() {
965 const char* cpuIdleHistogramTitle = "CPU Idle Histogram";
966 const char* cpuIdleHistogramFile = "/sys/kernel/metrics/cpuidle_histogram/"
967 "cpuidle_histogram";
968 const char* cpuClusterHistogramTitle = "CPU Cluster Histogram";
969 const char* cpuClusterHistogramFile = "/sys/kernel/metrics/"
970 "cpuidle_histogram/cpucluster_histogram";
971 dumpFileContent(cpuIdleHistogramTitle, cpuIdleHistogramFile);
972 dumpFileContent(cpuClusterHistogramTitle, cpuClusterHistogramFile);
973 }
974
main()975 int main() {
976 dumpPowerStatsTimes();
977 dumpAcpmStats();
978 dumpCpuIdleHistogramStats();
979 dumpPowerSupplyStats();
980 dumpMaxFg();
981 dumpPowerSupplyDock();
982 dumpLogBufferTcpm();
983 dumpTcpc();
984 dumpPdEngine();
985 dumpEusbRepeater();
986 dumpWc68();
987 dumpBatteryHealth();
988 dumpBatteryDefend();
989 dumpBatteryCaretaker();
990 dumpChg();
991 dumpChgUserDebug();
992 dumpBatteryEeprom();
993 dumpChargerStats();
994 dumpWlcLogs();
995 dumpGvoteables();
996 dumpMitigation();
997 dumpMitigationStats();
998 dumpMitigationDirs();
999 dumpIrqDurationCounts();
1000 }
1001
1002