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