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