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