diff --git a/dumpstate/Android.bp b/dumpstate/Android.bp index 814e7a0..f8f49cc 100644 --- a/dumpstate/Android.bp +++ b/dumpstate/Android.bp @@ -9,12 +9,21 @@ sh_binary { sub_dir: "dump", } -sh_binary { - name: "dump_power.sh", - src: "dump_power.sh", +cc_binary { + name: "dump_power", + srcs: ["dump_power.cpp"], + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + ], + shared_libs: [ + "libbase", + "libdump", + "libdumpstateutil", + ], vendor: true, - sub_dir: "dump", - init_rc: ["dump_power.rc"], + relative_install_path: "dump", } sh_binary { diff --git a/dumpstate/dump_power.cpp b/dumpstate/dump_power.cpp new file mode 100644 index 0000000..14b9d91 --- /dev/null +++ b/dumpstate/dump_power.cpp @@ -0,0 +1,931 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "DumpstateUtil.h" + + +void printTitle(const char *msg) { + printf("\n------ %s ------\n", msg); +} + +int getCommandOutput(const char *cmd, std::string *output) { + char buffer[1024]; + FILE *pipe = popen(cmd, "r"); + if (!pipe) { + return -1; + } + + while (fgets(buffer, sizeof buffer, pipe) != NULL) { + *output += buffer; + } + pclose(pipe); + + if (output->back() == '\n') + output->pop_back(); + + return 0; +} + +bool isValidFile(const char *file) { + FILE *fp = fopen(file, "r"); + if (fp != NULL) { + fclose(fp); + return true; + } + return false; +} + +bool isValidDir(const char *directory) { + DIR *dir = opendir(directory); + if (dir == NULL) + return false; + + closedir(dir); + return true; +} + +bool isUserBuild() { + return ::android::os::dumpstate::PropertiesHelper::IsUserBuild(); +} + +int getFilesInDir(const char *directory, std::vector *files) { + std::string content; + struct dirent *entry; + + DIR *dir = opendir(directory); + if (dir == NULL) + return -1; + + files->clear(); + while ((entry = readdir(dir)) != NULL) + files->push_back(entry->d_name); + closedir(dir); + + sort(files->begin(), files->end()); + return 0; +} + +void dumpPowerStatsTimes() { + const char *title = "Power Stats Times"; + char rBuff[128]; + struct timespec rTs; + struct sysinfo info; + int ret; + + printTitle(title); + + sysinfo(&info); + + const time_t boottime = time(NULL) - info.uptime; + + ret = clock_gettime(CLOCK_REALTIME, &rTs); + if (ret) + return; + + struct tm *nowTime = std::localtime(&rTs.tv_sec); + + std::strftime(rBuff, sizeof(rBuff), "%m/%d/%Y %H:%M:%S", nowTime); + printf("Boot: %s", ctime(&boottime)); + printf("Now: %s\n", rBuff); +} + +int readContentsOfDir(const char* title, const char* directory, const char* strMatch, + bool useStrMatch = false, bool printDirectory = false) { + std::vector files; + std::string content; + std::string fileLocation; + int ret; + + ret = getFilesInDir(directory, &files); + if (ret < 0) + return ret; + + printTitle(title); + for (auto &file : files) { + if (useStrMatch && std::string::npos == std::string(file).find(strMatch)) { + continue; + } + + fileLocation = std::string(directory) + std::string(file); + if (!android::base::ReadFileToString(fileLocation, &content)) { + continue; + } + if (printDirectory) { + printf("\n\n%s\n", fileLocation.c_str()); + } + if (content.back() == '\n') + content.pop_back(); + printf("%s\n", content.c_str()); + } + return 0; +} + +void dumpAcpmStats() { + const char* acpmDir = "/sys/devices/platform/acpm_stats/"; + const char* statsSubStr = "_stats"; + const char* acpmTitle = "ACPM stats"; + readContentsOfDir(acpmTitle, acpmDir, statsSubStr, true, true); +} + +void dumpPowerSupplyStats() { + const char* dumpList[][2] = { + {"CPU PM stats", "/sys/devices/system/cpu/cpupm/cpupm/time_in_state"}, + {"GENPD summary", "/d/pm_genpd/pm_genpd_summary"}, + {"Power supply property battery", "/sys/class/power_supply/battery/uevent"}, + {"Power supply property dc", "/sys/class/power_supply/dc/uevent"}, + {"Power supply property gcpm", "/sys/class/power_supply/gcpm/uevent"}, + {"Power supply property gcpm_pps", "/sys/class/power_supply/gcpm_pps/uevent"}, + {"Power supply property main-charger", "/sys/class/power_supply/main-charger/uevent"}, + {"Power supply property dc-mains", "/sys/class/power_supply/dc-mains/uevent"}, + {"Power supply property tcpm", "/sys/class/power_supply/tcpm-source-psy-8-0025/uevent"}, + {"Power supply property usb", "/sys/class/power_supply/usb/uevent"}, + {"Power supply property wireless", "/sys/class/power_supply/wireless/uevent"}, + }; + + for (const auto &row : dumpList) { + dumpFileContent(row[0], row[1]); + } +} + +void dumpMaxFg() { + const char *maxfgLoc = "/sys/class/power_supply/maxfg"; + const char *max77779fgDir = "/sys/class/power_supply/max77779fg"; + + const char *maxfg [][2] = { + {"Power supply property maxfg", "/sys/class/power_supply/maxfg/uevent"}, + {"m5_state", "/sys/class/power_supply/maxfg/m5_model_state"}, + {"maxfg logbuffer", "/dev/logbuffer_maxfg"}, + {"maxfg_monitor logbuffer", "/dev/logbuffer_maxfg_monitor"}, + }; + + const char *max77779fgFiles [][2] = { + {"Power supply property max77779fg", "/sys/class/power_supply/max77779fg/uevent"}, + {"m5_state", "/sys/class/power_supply/max77779fg/model_state"}, + {"max77779fg logbuffer", "/dev/logbuffer_max77779fg"}, + {"max77779fg_monitor logbuffer", "/dev/logbuffer_max77779fg_monitor"}, + }; + + const char *maxfgSecondary [][2] = { + {"Power supply property maxfg_base", "/sys/class/power_supply/maxfg_base/uevent"}, + {"Power supply property maxfg_secondary", "/sys/class/power_supply/maxfg_secondary/uevent"}, + {"model_state", "/sys/class/power_supply/maxfg_base/model_state"}, + {"maxfg_base", "/dev/logbuffer_maxfg_base"}, + {"maxfg_secondary", "/dev/logbuffer_maxfg_secondary"}, + {"maxfg_base_monitor logbuffer", "/dev/logbuffer_maxfg_base_monitor"}, + {"maxfg_secondary_monitor logbuffer", "/dev/logbuffer_maxfg_secondary_monitor"}, + }; + + const char *maxfgHistoryName = "Maxim FG History"; + const char *maxfgHistoryDir = "/dev/maxfg_history"; + + std::string content; + + + if (isValidDir(maxfgLoc)) { + for (const auto &row : maxfg) { + dumpFileContent(row[0], row[1]); + } + } else if (isValidDir(max77779fgDir)) { + for (const auto &row : max77779fgFiles) { + dumpFileContent(row[0], row[1]); + } + } else { + for (const auto &row : maxfgSecondary) { + dumpFileContent(row[0], row[1]); + } + } + + if (isValidFile(maxfgHistoryDir)) { + dumpFileContent(maxfgHistoryName, maxfgHistoryDir); + } +} + +void dumpPowerSupplyDock() { + const char* powerSupplyPropertyDockTitle = "Power supply property dock"; + const char* powerSupplyPropertyDockFile = "/sys/class/power_supply/dock/uevent"; + if (isValidFile(powerSupplyPropertyDockFile)) { + dumpFileContent(powerSupplyPropertyDockTitle, powerSupplyPropertyDockFile); + } +} + +void dumpLogBufferTcpm() { + const char* logbufferTcpmTitle = "Logbuffer TCPM"; + const char* logbufferTcpmFile = "/dev/logbuffer_tcpm"; + const char* debugTcpmFile = "/sys/kernel/debug/tcpm"; + const char* tcpmLogTitle = "TCPM logs"; + const char* tcpmFile = "/sys/kernel/debug/tcpm"; + const char* tcpmFileAlt = "/sys/kernel/debug/usb/tcpm"; + int retCode; + + dumpFileContent(logbufferTcpmTitle, logbufferTcpmFile); + + retCode = readContentsOfDir(tcpmLogTitle, isValidFile(debugTcpmFile) ? tcpmFile : tcpmFileAlt, + NULL); + if (retCode < 0) + printTitle(tcpmLogTitle); +} + +void dumpTcpc() { + int ret; + const char* max77759TcpcHead = "TCPC"; + const char* i2cSubDirMatch = "i2c-"; + const char* directory = "/sys/devices/platform/10d60000.hsi2c/"; + const char* max77759Tcpc [][2] { + {"registers:", "/i2c-max77759tcpc/registers"}, + {"frs:", "/i2c-max77759tcpc/frs"}, + {"auto_discharge:", "/i2c-max77759tcpc/auto_discharge"}, + {"bcl2_enabled:", "/i2c-max77759tcpc/bcl2_enabled"}, + {"cc_toggle_enable:", "/i2c-max77759tcpc/cc_toggle_enable"}, + {"containment_detection:", "/i2c-max77759tcpc/containment_detection"}, + {"containment_detection_status:", "/i2c-max77759tcpc/containment_detection_status"}, + }; + + std::vector files; + std::string content; + + printTitle(max77759TcpcHead); + + ret = getFilesInDir(directory, &files); + if (ret < 0) { + for (auto &tcpcVal : max77759Tcpc) + printf("%s\n", tcpcVal[0]); + return; + } + + for (auto &file : files) { + for (auto &tcpcVal : max77759Tcpc) { + printf("%s ", tcpcVal[0]); + if (std::string::npos == std::string(file).find(i2cSubDirMatch)) { + continue; + } + + std::string fileName = directory + file + "/" + std::string(tcpcVal[1]); + + if (!android::base::ReadFileToString(fileName, &content)) { + continue; + } + + printf("%s\n", content.c_str()); + } + } +} + +void dumpPdEngine() { + const char* pdEngine [][2] { + {"PD Engine logbuffer", "/dev/logbuffer_usbpd"}, + {"PPS-google_cpm logbuffer", "/dev/logbuffer_cpm"}, + }; + const char* ppsDcMsg = "PPS-dc logbuffer"; + const char* pca9468dir = "/dev/logbuffer_pca9468"; + const char* ln8411dir = "/dev/logbuffer_ln8411"; + + for (const auto &row : pdEngine) { + dumpFileContent(row[0], row[1]); + } + if (isValidFile(pca9468dir)) { + dumpFileContent(ppsDcMsg, pca9468dir); + } else { + dumpFileContent(ppsDcMsg, ln8411dir); + } +} + +void dumpBatteryHealth() { + const char* batteryHealth [][2] { + {"Battery Health", "/sys/class/power_supply/battery/health_index_stats"}, + {"BMS logbuffer", "/dev/logbuffer_ssoc"}, + {"TTF logbuffer", "/dev/logbuffer_ttf"}, + {"TTF details", "/sys/class/power_supply/battery/ttf_details"}, + {"TTF stats", "/sys/class/power_supply/battery/ttf_stats"}, + {"aacr_state", "/sys/class/power_supply/battery/aacr_state"}, + {"pairing_state", "/sys/class/power_supply/battery/pairing_state"}, + }; + + const char* maxqName = "maxq logbuffer"; + const char* maxqDir = "/dev/logbuffer_maxq"; + const char* tempDockDefendName = "TEMP/DOCK-DEFEND"; + const char* tempDockDefendDir = "/dev/logbuffer_bd"; + + for (const auto &row : batteryHealth) { + dumpFileContent(row[0], row[1]); + } + + if (isValidFile(maxqDir)) + dumpFileContent(maxqName, maxqDir); + + dumpFileContent(tempDockDefendName, tempDockDefendDir); +} + +void dumpBatteryDefend() { + const char* defendConfig [][3] { + {"TRICKLE-DEFEND Config", + "/sys/devices/platform/google,battery/power_supply/battery/", "bd_"}, + {"DWELL-DEFEND Config", "/sys/devices/platform/google,charger/", "charge_s"}, + {"TEMP-DEFEND Config", "/sys/devices/platform/google,charger/", "bd_"}, + }; + + std::vector files; + struct dirent *entry; + std::string content; + std::string fileLocation; + + for (auto &config : defendConfig) { + DIR *dir = opendir(config[1]); + if (dir == NULL) + continue; + + printTitle(config[0]); + while ((entry = readdir(dir)) != NULL) { + if (std::string(entry->d_name).find(config[2]) != std::string::npos && + strncmp(config[2], entry->d_name, strlen(config[2])) == 0) { + files.push_back(entry->d_name); + } + } + closedir(dir); + + sort(files.begin(), files.end()); + + for (auto &file : files) { + fileLocation = std::string(config[1]) + std::string(file); + if (!android::base::ReadFileToString(fileLocation, &content)) { + content = "\n"; + } + + printf("%s: %s", file.c_str(), content.c_str()); + + if (content.back() != '\n') + printf("\n"); + } + + files.clear(); + } +} + +void printValuesOfDirectory(const char *directory, std::string debugfs, const char *strMatch) { + std::vector files; + auto info = directory; + std::string content; + struct dirent *entry; + DIR *dir = opendir(debugfs.c_str()); + if (dir == NULL) + return; + + printTitle((debugfs + std::string(strMatch) + "/" + std::string(info)).c_str()); + while ((entry = readdir(dir)) != NULL) + if (std::string(entry->d_name).find(strMatch) != std::string::npos) + files.push_back(entry->d_name); + closedir(dir); + + sort(files.begin(), files.end()); + + for (auto &file : files) { + std::string fileDirectory = debugfs + file; + std::string fileLocation = fileDirectory + "/" + std::string(info); + if (!android::base::ReadFileToString(fileLocation, &content)) { + content = "\n"; + } + + printf("%s:\n%s", fileDirectory.c_str(), content.c_str()); + + if (content.back() != '\n') + printf("\n"); + } + files.clear(); +} + +void dumpChgUserDebug() { + const char *chgDebugMax77759 [][2] { + {"max77759_chg registers dump", "/d/max77759_chg/registers/"}, + {"max77729_pmic registers dump", "/d/max77729_pmic/registers/"}, + }; + const char *chgDebugMax77779 [][2] { + {"max77779_chg registers dump", "/d/max77779_chg/registers/"}, + {"max77779_pmic registers dump", "/d/max77779_pmic/registers/"}, + }; + + const std::string debugfs = "/d/"; + + const char *maxFgDir = "/d/maxfg"; + const char *maxFgStrMatch = "maxfg"; + const char *maxFg77779StrMatch = "max77779fg"; + const char *baseChgDir = "/d/max77759_chg"; + const char *dcRegName = "DC_registers dump"; + const char *dcRegDir = "/sys/class/power_supply/dc-mains/device/registers_dump"; + const char *chgTblName = "Charging table dump"; + const char *chgTblDir = "/d/google_battery/chg_raw_profile"; + + const char *maxFgInfo [] { + "fg_model", + "algo_ver", + "model_ok", + "registers", + "nv_registers", + }; + + const char *max77779FgInfo [] { + "fg_model", + "algo_ver", + "model_ok", + "registers", + "debug_registers", + }; + + if (isUserBuild()) + return; + + dumpFileContent(dcRegName, dcRegDir); + + if (isValidFile(baseChgDir)) { + for (auto &row : chgDebugMax77759) { + dumpFileContent(row[0], row[1]); + } + } else { + for (auto &row : chgDebugMax77779) { + dumpFileContent(row[0], row[1]); + } + } + + dumpFileContent(chgTblName, chgTblDir); + + if (isValidFile(maxFgDir)) { + for (auto & directory : maxFgInfo) { + printValuesOfDirectory(directory, debugfs, maxFgStrMatch); + } + } else { + for (auto & directory : max77779FgInfo) { + printValuesOfDirectory(directory, debugfs, maxFg77779StrMatch); + } + } +} + +void dumpBatteryEeprom() { + const char *title = "Battery EEPROM"; + const char *files[] { + "/sys/devices/platform/10ca0000.hsi2c/i2c-10/10-0050/eeprom", + "/sys/devices/platform/10c90000.hsi2c/i2c-9/9-0050/eeprom", + }; + std::string result; + std::string xxdCmd; + + printTitle(title); + for (auto &file : files) { + if (!isValidFile(file)) + continue; + + xxdCmd = "xxd " + std::string(file); + + int ret = getCommandOutput(xxdCmd.c_str(), &result); + if (ret < 0) + return; + + printf("%s\n", result.c_str()); + } +} + +void dumpChargerStats() { + const char *chgStatsTitle = "Charger Stats"; + const char *chgStatsLocation = "/sys/class/power_supply/battery/charge_details"; + const char *chargerStats [][3] { + {"Google Charger", "/sys/kernel/debug/google_charger/", "pps_"}, + {"Google Battery", "/sys/kernel/debug/google_battery/", "ssoc_"}, + }; + std::vector files; + std::string content; + struct dirent *entry; + + dumpFileContent(chgStatsTitle, chgStatsLocation); + + if (isUserBuild()) + return; + + for (auto &stat : chargerStats) { + DIR *dir = opendir(stat[1]); + if (dir == NULL) + return; + + printTitle(stat[0]); + while ((entry = readdir(dir)) != NULL) + if (std::string(entry->d_name).find(stat[2]) != std::string::npos) + files.push_back(entry->d_name); + closedir(dir); + + sort(files.begin(), files.end()); + + for (auto &file : files) { + std::string fileLocation = std::string(stat[1]) + file; + if (!android::base::ReadFileToString(fileLocation, &content)) { + content = "\n"; + } + + printf("%s: %s", file.c_str(), content.c_str()); + + if (content.back() != '\n') + printf("\n"); + } + files.clear(); + } +} + +void dumpWlcLogs() { + const char *dumpWlcList [][2] { + {"WLC Logs", "/dev/logbuffer_wireless"}, + {"WLC VER", "/sys/class/power_supply/wireless/device/version"}, + {"WLC STATUS", "/sys/class/power_supply/wireless/device/status"}, + {"WLC FW Version", "/sys/class/power_supply/wireless/device/fw_rev"}, + {"RTX", "/dev/logbuffer_rtx"}, + }; + + for (auto &row : dumpWlcList) { + if (!isValidFile(row[1])) + printTitle(row[0]); + dumpFileContent(row[0], row[1]); + } +} + +void dumpGvoteables() { + const char *directory = "/sys/kernel/debug/gvotables/"; + const char *statusName = "/status"; + const char *title = "gvotables"; + std::string content; + std::vector files; + int ret; + + if (isUserBuild()) + return; + + ret = getFilesInDir(directory, &files); + if (ret < 0) + return; + + printTitle(title); + for (auto &file : files) { + std::string fileLocation = std::string(directory) + file + std::string(statusName); + if (!android::base::ReadFileToString(fileLocation, &content)) { + continue; + } + + printf("%s: %s", file.c_str(), content.c_str()); + + if (content.back() != '\n') + printf("\n"); + } + files.clear(); +} + +void dumpMitigation() { + const char *mitigationList [][2] { + {"Lastmeal" , "/data/vendor/mitigation/lastmeal.txt"}, + {"Thismeal" , "/data/vendor/mitigation/thismeal.txt"}, + }; + + for (auto &row : mitigationList) { + if (!isValidFile(row[1])) + printTitle(row[0]); + dumpFileContent(row[0], row[1]); + } +} + +void dumpMitigationStats() { + int ret; + const char *directory = "/sys/devices/virtual/pmic/mitigation/last_triggered_count/"; + const char *capacityDirectory = "/sys/devices/virtual/pmic/mitigation/last_triggered_capacity/"; + const char *timestampDirectory = + "/sys/devices/virtual/pmic/mitigation/last_triggered_timestamp/"; + const char *voltageDirectory = "/sys/devices/virtual/pmic/mitigation/last_triggered_voltage/"; + const char *capacitySuffix = "_cap"; + const char *timeSuffix = "_time"; + const char *voltageSuffix = "_volt"; + const char *countSuffix = "_count"; + const char *title = "Mitigation Stats"; + + std::vector files; + std::string content; + std::string fileLocation; + std::string source; + std::string subModuleName; + int count; + int soc; + int time; + int voltage; + + ret = getFilesInDir(directory, &files); + if (ret < 0) + return; + + printTitle(title); + printf("Source\t\tCount\tSOC\tTime\tVoltage\n"); + + for (auto &file : files) { + fileLocation = std::string(directory) + std::string(file); + if (!android::base::ReadFileToString(fileLocation, &content)) { + continue; + } + + ret = atoi(android::base::Trim(content).c_str()); + if (ret == -1) + continue; + count = ret; + + subModuleName = std::string(file); + subModuleName.erase(subModuleName.find(countSuffix), strlen(countSuffix)); + + fileLocation = std::string(capacityDirectory) + std::string(subModuleName) + + std::string(capacitySuffix); + if (!android::base::ReadFileToString(fileLocation, &content)) { + continue; + } + ret = atoi(android::base::Trim(content).c_str()); + if (ret == -1) + continue; + soc = ret; + + fileLocation = std::string(timestampDirectory) + std::string(subModuleName) + + std::string(timeSuffix); + if (!android::base::ReadFileToString(fileLocation, &content)) { + continue; + } + ret = atoi(android::base::Trim(content).c_str()); + if (ret == -1) + continue; + time = ret; + + fileLocation = std::string(voltageDirectory) + std::string(subModuleName) + + std::string(voltageSuffix); + if (!android::base::ReadFileToString(fileLocation, &content)) { + continue; + } + ret = atoi(android::base::Trim(content).c_str()); + if (ret == -1) + continue; + voltage = ret; + printf("%s \t%i\t%i\t%i\t%i\n", subModuleName.c_str(), count, soc, time, voltage); + } +} + +void dumpMitigationDirs() { + const int paramCount = 4; + const char *titles[] = { + "Clock Divider Ratio", + "Clock Stats", + "Triggered Level", + "Instruction", + }; + const char *directories[] = { + "/sys/devices/virtual/pmic/mitigation/clock_ratio/", + "/sys/devices/virtual/pmic/mitigation/clock_stats/", + "/sys/devices/virtual/pmic/mitigation/triggered_lvl/", + "/sys/devices/virtual/pmic/mitigation/instruction/", + }; + const char *paramSuffix[] = {"_ratio", "_stats", "_lvl", ""}; + const char *titleRowVal[] = { + "Source\t\tRatio", + "Source\t\tStats", + "Source\t\tLevel", + "", + }; + const int eraseCnt[] = {6, 6, 4, 0}; + const bool useTitleRow[] = {true, true, true, false}; + + std::vector files; + std::string content; + std::string fileLocation; + std::string source; + std::string subModuleName; + std::string readout; + + for (int i = 0; i < paramCount; i++) { + printTitle(titles[i]); + if (useTitleRow[i]) { + printf("%s\n", titleRowVal[i]); + } + + getFilesInDir(directories[i], &files); + + for (auto &file : files) { + fileLocation = std::string(directories[i]) + std::string(file); + if (!android::base::ReadFileToString(fileLocation, &content)) { + continue; + } + + readout = android::base::Trim(content); + + subModuleName = std::string(file); + subModuleName.erase(subModuleName.find(paramSuffix[i]), eraseCnt[i]); + + if (useTitleRow[i]) { + printf("%s \t%s\n", subModuleName.c_str(), readout.c_str()); + } else { + printf("%s=%s\n", subModuleName.c_str(), readout.c_str()); + } + } + } +} + +void dumpIrqDurationCounts() { + const char *title = "IRQ Duration Counts"; + const char *colNames = "Source\t\t\t\tlt_5ms_cnt\tbt_5ms_to_10ms_cnt\tgt_10ms_cnt\tCode" + "\tCurrent Threshold (uA)\tCurrent Reading (uA)\n"; + const int nonOdpmChannelCnt = 12; + const int odpmChCnt = 12; + + enum Duration { + LT_5MS, + BT_5MS_10MS, + GT_10MS, + DUR_MAX, + }; + const char *irqDurDirectories[] = { + "/sys/devices/virtual/pmic/mitigation/irq_dur_cnt/less_than_5ms_count", + "/sys/devices/virtual/pmic/mitigation/irq_dur_cnt/between_5ms_to_10ms_count", + "/sys/devices/virtual/pmic/mitigation/irq_dur_cnt/greater_than_10ms_count", + }; + + enum PowerWarn { + MAIN, + SUB, + PWRWARN_MAX, + }; + const char *pwrwarnDirectories[] = { + "/sys/devices/virtual/pmic/mitigation/main_pwrwarn/", + "/sys/devices/virtual/pmic/mitigation/sub_pwrwarn/", + }; + + const char *lpfCurrentDirs[] = { + "/sys/devices/platform/acpm_mfd_bus@15500000/i2c-7/7-001f/s2mpg14-meter/" + "s2mpg14-odpm/iio:device1/lpf_current", + "/sys/devices/platform/acpm_mfd_bus@15510000/i2c-8/8-002f/s2mpg15-meter/" + "s2mpg15-odpm/iio:device0/lpf_current", + }; + + bool titlesInitialized = false; + + std::vector channelNames; + std::vector channelData[DUR_MAX]; + std::vector pwrwarnThreshold[PWRWARN_MAX]; + std::vector pwrwarnCode[PWRWARN_MAX]; + std::vector lpfCurrentVals[PWRWARN_MAX]; + std::vector files; + + std::string content; + std::string token; + std::string tokenCh; + std::string fileLocation; + + for (int i = 0; i < DUR_MAX; i++) { + if (!android::base::ReadFileToString(irqDurDirectories[i], &content)) { + return; + } + + std::istringstream tokenStream(content); + + while (std::getline(tokenStream, token, '\n')) { + if (!titlesInitialized) { + tokenCh = token; + tokenCh.erase(tokenCh.find(':'), tokenCh.length()); + channelNames.push_back(tokenCh); + } + + // there is a space after the ':' which needs to be removed + token.erase(0, token.find(':') + 1); + channelData[i].push_back(token); + + } + if (!titlesInitialized) + titlesInitialized = true; + } + + for (int i = 0; i < PWRWARN_MAX; i++) { + getFilesInDir(pwrwarnDirectories[i], &files); + + for (auto &file : files) { + fileLocation = std::string(pwrwarnDirectories[i]) + std::string(file); + if (!android::base::ReadFileToString(fileLocation, &content)) { + continue; + } + + std::string readout; + + readout = android::base::Trim(content); + + std::string readoutThreshold = readout; + readoutThreshold.erase(0, readoutThreshold.find('=') + 1); + + std::string readoutCode = readout; + readoutCode.erase(readoutCode.find('='), readoutCode.length()); + + pwrwarnThreshold[i].push_back(readoutThreshold); + pwrwarnCode[i].push_back(readoutCode); + } + } + + for (int i = 0; i < PWRWARN_MAX; i++) { + if (!android::base::ReadFileToString(lpfCurrentDirs[i], &content)) { + continue; + } + + std::istringstream tokenStream(content); + + bool first = true; + while (std::getline(tokenStream, token, '\n')) { + token.erase(0, token.find(' ')); + if (first) { + first = false; + continue; + } + lpfCurrentVals[i].push_back(token); + } + } + + printTitle(title); + printf("%s", colNames); + + for (uint i = 0; i < channelNames.size(); i++) { + std::string code = ""; + std::string threshold = ""; + std::string current = ""; + std::string ltDataMsg = ""; + std::string btDataMsg = ""; + std::string gtDataMsg = ""; + int pmicSel = 0; + int offset = 0; + std::string channelNameSuffix = " \t"; + if (i >= nonOdpmChannelCnt) { + offset = nonOdpmChannelCnt; + if (i >= (odpmChCnt + nonOdpmChannelCnt)) { + pmicSel = 1; + offset = odpmChCnt + nonOdpmChannelCnt; + } + channelNameSuffix = ""; + + code = pwrwarnCode[pmicSel][i - offset]; + threshold = pwrwarnThreshold[pmicSel][i - offset]; + current = lpfCurrentVals[pmicSel][i - offset]; + } + + if (i < channelData[0].size()) + ltDataMsg = channelData[0][i]; + + if (i < channelData[1].size()) + btDataMsg = channelData[1][i]; + + if (i < channelData[2].size()) + gtDataMsg = channelData[2][i]; + + std::string adjustedChannelName = channelNames[i] + channelNameSuffix; + printf("%s \t%s\t\t%s\t\t\t%s\t\t%s \t%s \t\t%s\n", + adjustedChannelName.c_str(), + ltDataMsg.c_str(), + btDataMsg.c_str(), + gtDataMsg.c_str(), + code.c_str(), + threshold.c_str(), + current.c_str()); + } +} + +int main() { + dumpPowerStatsTimes(); + dumpAcpmStats(); + dumpPowerSupplyStats(); + dumpMaxFg(); + dumpPowerSupplyDock(); + dumpLogBufferTcpm(); + dumpTcpc(); + dumpPdEngine(); + dumpBatteryHealth(); + dumpBatteryDefend(); + dumpChgUserDebug(); + dumpBatteryEeprom(); + dumpChargerStats(); + dumpWlcLogs(); + dumpGvoteables(); + dumpMitigation(); + dumpMitigationStats(); + dumpMitigationDirs(); + dumpIrqDurationCounts(); +} + diff --git a/dumpstate/dump_power.sh b/dumpstate/dump_power.sh deleted file mode 100644 index 8509dfa..0000000 --- a/dumpstate/dump_power.sh +++ /dev/null @@ -1,416 +0,0 @@ -#!/vendor/bin/sh -build_type="$(getprop ro.build.type)" - -echo "\n------ Power Stats Times ------" -echo -n "Boot: " && /vendor/bin/uptime -s && echo -n "Now: " && date; - -echo "\n------ ACPM stats ------" -for f in /sys/devices/platform/acpm_stats/*_stats ; do - echo "\n\n$f" - cat $f -done - -echo "\n------ CPU PM stats ------" -cat "/sys/devices/system/cpu/cpupm/cpupm/time_in_state" - -echo "\n------ GENPD summary ------" -cat "/d/pm_genpd/pm_genpd_summary" - -echo "\n------ Power supply property battery ------" -cat "/sys/class/power_supply/battery/uevent" -echo "\n------ Power supply property dc ------" -cat "/sys/class/power_supply/dc/uevent" -echo "\n------ Power supply property gcpm ------" -cat "/sys/class/power_supply/gcpm/uevent" -echo "\n------ Power supply property gcpm_pps ------" -cat "/sys/class/power_supply/gcpm_pps/uevent" -echo "\n------ Power supply property main-charger ------" -cat "/sys/class/power_supply/main-charger/uevent" -echo "\n------ Power supply property dc-mains ------" -cat "/sys/class/power_supply/dc-mains/uevent" -echo "\n------ Power supply property tcpm ------" -cat "/sys/class/power_supply/tcpm-source-psy-8-0025/uevent" -echo "\n------ Power supply property usb ------" -cat "/sys/class/power_supply/usb/uevent" -echo "\n------ Power supply property wireless ------" -cat "/sys/class/power_supply/wireless/uevent" - -if [ -d "/sys/class/power_supply/maxfg" ] -then - echo "\n------ Power supply property maxfg ------" - cat "/sys/class/power_supply/maxfg/uevent" - echo "\n------ m5_state ------" - cat "/sys/class/power_supply/maxfg/m5_model_state" - echo "\n------ maxfg logbuffer------" - cat "/dev/logbuffer_maxfg" - echo "\n------ maxfg_monitor logbuffer------" - cat "/dev/logbuffer_maxfg_monitor" -elif [ -d "/sys/class/power_supply/max77779fg" ] -then - echo "\n------ Power supply property max77779fg ------" - cat "/sys/class/power_supply/max77779fg/uevent" - echo "\n------ m5_state ------" - cat "/sys/class/power_supply/max77779fg/model_state" - echo "\n------ max77779fg logbuffer------" - cat "/dev/logbuffer_max77779fg" - echo "\n------ max77779fg_monitor logbuffer ------" - cat "/dev/logbuffer_max77779fg_monitor" -else - echo "\n------ Power supply property maxfg_base ------" - cat "/sys/class/power_supply/maxfg_base/uevent" - echo "\n------ Power supply property maxfg_secondary ------" - cat "/sys/class/power_supply/maxfg_secondary/uevent" - echo "\n------ model_state ------" - cat "/sys/class/power_supply/maxfg_base/model_state" - echo "\n------ maxfg_base logbuffer------" - cat "/dev/logbuffer_maxfg_base" - echo "\n------ maxfg_secondary logbuffer------" - cat "/dev/logbuffer_maxfg_secondary" - echo "\n------ maxfg_base_monitor logbuffer------" - cat "/dev/logbuffer_maxfg_base_monitor" - echo "\n------ maxfg_secondary_monitor logbuffer------" - cat "/dev/logbuffer_maxfg_secondary_monitor" -fi - -if [ -e "/dev/maxfg_history" ] -then - echo "\n------ Maxim FG History ------" - cat "/dev/maxfg_history" -fi - -if [ -d "/sys/class/power_supply/dock" ] -then - echo "\n------ Power supply property dock ------" - cat "/sys/class/power_supply/dock/uevent" -fi - -if [ -e "/dev/logbuffer_tcpm" ] -then - echo "\n------ Logbuffer TCPM ------" - cat "/dev/logbuffer_tcpm" - if [ -d "/sys/kernel/debug/tcpm" ] - then - echo "\n------ TCPM logs ------" - cat /sys/kernel/debug/tcpm/* - else - echo "\n------ TCPM logs ------" - cat /sys/kernel/debug/usb/tcpm* - fi -fi - -echo "\n------ TCPC ------" -for f in /sys/devices/platform/10d60000.hsi2c/i2c-*/i2c-max77759tcpc -do - echo "registers:" - cat $f/registers - echo "frs:" - cat $f/frs - echo "auto_discharge:" - cat $f/auto_discharge - echo "bc12_enabled:" - cat $f/bc12_enabled - echo "cc_toggle_enable:" - cat $f/cc_toggle_enable - echo "contaminant_detection:" - cat $f/contaminant_detection - echo "contaminant_detection_status:" - cat $f/contaminant_detection_status -done - -echo "\n------ PD Engine logbuffer------" -cat "/dev/logbuffer_usbpd" -echo "\n------ PPS-google_cpm logbuffer------" -cat "/dev/logbuffer_cpm" -echo "\n------ PPS-dc logbuffer------" -if [ -e "/dev/logbuffer_pca9468" ] -then - cat "/dev/logbuffer_pca9468" -else - cat "/dev/logbuffer_ln8411" -fi - -echo "\n------ Battery Health ------" -cat "/sys/class/power_supply/battery/health_index_stats" -echo "\n------ BMS logbuffer------" -cat "/dev/logbuffer_ssoc" -echo "\n------ TTF logbuffer-----" -cat "/dev/logbuffer_ttf" -echo "\n------ TTF details ------" -cat "/sys/class/power_supply/battery/ttf_details" -echo "\n------ TTF stats ------" -cat "/sys/class/power_supply/battery/ttf_stats" -echo "\n------ aacr_state ------" -cat "/sys/class/power_supply/battery/aacr_state" -echo "\n------ pairing_state ------" -cat "/sys/class/power_supply/battery/pairing_state" -if [ -e "/dev/logbuffer_maxq" ] -then - echo "\n------ maxq logbuffer------" - cat "/dev/logbuffer_maxq" -fi -echo "\n------ TEMP/DOCK-DEFEND ------" -cat "/dev/logbuffer_bd" - -echo "\n------ TRICKLE-DEFEND Config ------" -cd /sys/devices/platform/google,battery/power_supply/battery/ -for f in `ls bd_*` -do - echo $f: `cat $f` -done - -echo "\n------ DWELL-DEFEND Config ------" -cd /sys/devices/platform/google,charger/ -for f in `ls charge_s*` -do - echo "$f: `cat $f`" -done - -echo "\n------ TEMP-DEFEND Config ------" -cd /sys/devices/platform/google,charger/ -for f in `ls bd_*` -do - echo "$f: `cat $f`" -done - -if [ $build_type = "userdebug" ] -then - echo "\n------ DC_registers dump ------" - cat "/sys/class/power_supply/dc-mains/device/registers_dump" - if [ -d "/d/max77759_chg" ] - then - echo "\n------ max77759_chg registers dump ------" - cat "/d/max77759_chg/registers" - echo "\n------ max77729_pmic registers dump ------" - cat "/d/max77729_pmic/registers" - else - echo "\n------ max77779_chg registers dump ------" - cat "/d/max77779_chg/registers" - echo "\n------ max77779_pmic registers dump ------" - cat "/d/max77779_pmic/registers" - fi - echo "\n------ Charging table dump ------" - cat "/d/google_battery/chg_raw_profile" - - if [ -d "/d/maxfg" ] - then - for f in /d/maxfg* - do - regs=`cat $f/fg_model` - echo "\n------ $f/fg_model ------:" - echo "$regs" - regs=`cat $f/algo_ver` - echo "\n------ $f/algo_ver ------:" - echo "$regs" - regs=`cat $f/model_ok` - echo "\n------ $f/model_ok ------:" - echo "$regs" - regs=`cat $f/registers` - echo "\n------ $f/registers ------:" - echo "$regs" - regs=`cat $f/nv_registers` - echo "\n------ $f/nv_registers ------:" - echo "$regs" - done - else - for f in /d/max77779fg* - do - regs=`cat $f/fg_model` - echo "\n------ $f/fg_model ------:" - echo "$regs" - regs=`cat $f/model_ok` - echo "\n------ $f/model_ok ------:" - echo "$regs" - regs=`cat $f/registers` - echo "\n------ $f/registers ------:" - echo "$regs" - regs=`cat $f/debug_registers` - echo "\n------ $f/debug_registers ------:" - echo "$regs" - done - fi -fi - -echo "\n------ Battery EEPROM ------" -if [ -e "/sys/devices/platform/10ca0000.hsi2c/i2c-10/10-0050/eeprom" ] -then - xxd /sys/devices/platform/10ca0000.hsi2c/i2c-10/10-0050/eeprom -fi - -if [ -e "/sys/devices/platform/10c90000.hsi2c/i2c-9/9-0050/eeprom" ] -then - xxd /sys/devices/platform/10c90000.hsi2c/i2c-9/9-0050/eeprom -fi - -echo "\n------ Charger Stats ------" -cat "/sys/class/power_supply/battery/charge_details" -if [ $build_type = "userdebug" ] -then - echo "\n------ Google Charger ------" - cd /sys/kernel/debug/google_charger/ - for f in `ls pps_*` - do - echo "$f: `cat $f`" - done - echo "\n------ Google Battery ------" - cd /sys/kernel/debug/google_battery/ - for f in `ls ssoc_*` - do - echo "$f: `cat $f`" - done -fi - -echo "\n------ WLC logs logbuffer------" -cat "/dev/logbuffer_wireless" -echo "\n------ WLC VER ------" -cat "/sys/class/power_supply/wireless/device/version" -echo "\n------ WLC STATUS ------" -cat "/sys/class/power_supply/wireless/device/status" -echo "\n------ WLC FW Version ------" -cat "/sys/class/power_supply/wireless/device/fw_rev" -echo "\n------ RTX logbuffer------" -cat "/dev/logbuffer_rtx" - -if [ $build_type = "userdebug" ] -then - echo "\n------ gvotables ------" - cat /sys/kernel/debug/gvotables/*/status -fi - -echo "\n------ Lastmeal ------" -cat "/data/vendor/mitigation/lastmeal.txt" -echo "\n------ Thismeal ------" -cat "/data/vendor/mitigation/thismeal.txt" -echo "\n------ Mitigation Stats ------" -echo "Source\t\tCount\tSOC\tTime\tVoltage" -for f in `ls /sys/devices/virtual/pmic/mitigation/last_triggered_count/*` -do - count=`cat $f` - a=${f/\/sys\/devices\/virtual\/pmic\/mitigation\/last_triggered_count\//} - b=${f/last_triggered_count/last_triggered_capacity} - c=${f/last_triggered_count/last_triggered_timestamp/} - d=${f/last_triggered_count/last_triggered_voltage/} - cnt=`cat $f` - cap=`cat ${b/count/cap}` - ti=`cat ${c/count/time}` - volt=`cat ${d/count/volt}` - echo "${a/_count/} \t$cnt\t$cap\t$ti\t$volt" -done - -echo "\n------ Clock Divider Ratio ------" -echo \"Source\t\tRatio\" -for f in `ls /sys/devices/virtual/pmic/mitigation/clock_ratio/*` -do ratio=`cat $f` - a=${f/\/sys\/devices\/virtual\/pmic\/mitigation\/clock_ratio\//} - echo "${a/_ratio/} \t$ratio" -done - -echo "\n------ Clock Stats ------" -echo "Source\t\tStats" -for f in `ls /sys/devices/virtual/pmic/mitigation/clock_stats/*` -do - stats=`cat $f` - a=${f/\/sys\/devices\/virtual\/pmic\/mitigation\/clock_stats\//}; - echo "${a/_stats/} \t$stats" -done - -echo "\n------ Triggered Level ------" -echo "Source\t\tLevel" -for f in `ls /sys/devices/virtual/pmic/mitigation/triggered_lvl/*` -do - lvl=`cat $f` - a=${f/\/sys\/devices\/virtual\/pmic\/mitigation\/triggered_lvl\//} - echo "${a/_lvl/} \t$lvl" -done - -echo "\n------ Instruction ------" -for f in `ls /sys/devices/virtual/pmic/mitigation/instruction/*` -do - val=`cat $f` - a=${f/\/sys\/devices\/virtual\/pmic\/mitigation\/instruction\//} - echo "$a=$val" -done - -echo "\n------ IRQ Duration Counts ------" -echo "Source\t\t\t\tlt_5ms_cnt\tbt_5ms_to_10ms_cnt\tgt_10ms_cnt\tCode\tCurrent Threshold (uA)\tCurrent Reading (uA)" - -lt=`cat /sys/devices/virtual/pmic/mitigation/irq_dur_cnt/less_than_5ms_count` -bt=`cat /sys/devices/virtual/pmic/mitigation/irq_dur_cnt/between_5ms_to_10ms_count` -gt=`cat /sys/devices/virtual/pmic/mitigation/irq_dur_cnt/greater_than_10ms_count` -lpf_cur_m=`cat /sys/devices/platform/acpm_mfd_bus@15500000/i2c-0/0-001f/s2mpg14-meter/s2mpg14-odpm/iio:device0/lpf_current` -lpf_cur_s=`cat /sys/devices/platform/acpm_mfd_bus@15510000/i2c-1/1-002f/s2mpg15-meter/s2mpg15-odpm/iio:device1/lpf_current` - -lpf_cur_main=(${lpf_cur_m/\\n/;}) -lpf_cur_sub=(${lpf_cur_s/\\n/;}) - -IFS_PRE=$IFS -IFS=$'\n' -lt_a=($lt) -bt_a=($bt) -gt_a=($gt) -IFS=$IFS_PRE - - -for f in `ls /sys/devices/virtual/pmic/mitigation/main_pwrwarn/*` -do - count=`cat $f` - a=${f/\/sys\/devices\/virtual\/pmic\/mitigation\/main_pwrwarn\//} - s=${a/main_pwrwarn_threshold/} - arr=(${count//=/ }) - code=${arr[0]} - threshold=${arr[1]} - main_array[$s]="$code\t$threshold" -done - -i=1 -main_current=() -for f in "${main_array[@]}" -do - idx=$i - idx2=$idx+1 - main_current+=(${lpf_cur_main[$idx2]}) - i=$i+2 -done - -for f in `ls /sys/devices/virtual/pmic/mitigation/sub_pwrwarn/*` -do - count=`cat $f` - a=${f/\/sys\/devices\/virtual\/pmic\/mitigation\/sub_pwrwarn\//} - s=${a/sub_pwrwarn_threshold/} - arr=(${count//=/ }) - code=${arr[0]}; - threshold=${arr[1]}; - sub_array[$s]="$code\t$threshold" -done -i=1 -sub_current=() -for f in "${sub_array[@]}" -do - idx=$i - idx2=$idx+1 - sub_current+=(${lpf_cur_sub[$idx2]}) - i=$i+2 -done - -rows=${#lt_a[@]} -for i in `seq 0 $rows` -do - n="${lt_a[i]%:*}" - l="${lt_a[i]#*": "}" - b="${bt_a[i]#*": "}" - g="${gt_a[i]#*": "}" - if [ $i -lt 9 ] - then - echo "$n \t\t$l\t\t$b\t\t\t$g" - elif [ $i -ge 9 ] && [ $i -lt 21 ] - then - j=$i-9 - thresh="${main_array[j]}" - current="${main_current[j]}" - echo "$n \t$l\t\t$b\t\t\t$g\t\t$thresh \t\t$current" - else - j=$i-21 - thresh="${sub_array[j]}" - current="${sub_current[j]}" - echo "$n \t$l\t\t$b\t\t\t$g\t\t$thresh \t\t$current" - fi -done diff --git a/dumpstate/item.mk b/dumpstate/item.mk index b6b9e9a..286c84f 100644 --- a/dumpstate/item.mk +++ b/dumpstate/item.mk @@ -1,5 +1,5 @@ PRODUCT_PACKAGES += dump_wlan.sh \ - dump_power.sh + dump_power PRODUCT_PACKAGES_DEBUG += dump_gsa.sh