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