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