https://www.2cto.com/kf/201607/528696.html
使用 adb bugreport 可以导出功耗分析所需文件,然后通过 https://github.com/google/battery-historian 进行更加详细的分析
adb bugreport > Bugreport.zip
adb bugreport > Bugreport.txt
adb bugreport - return all information from the device that should be included in a bug report.
" bugreport [PATH]\n"
" write bugreport to given PATH [default=bugreport.zip];\n"
" if PATH is a directory, the bug report is saved in that directory.\n"
" devices that don't support zipped bug reports output to stdout.\n"
这里主要想知道 bugreport 的数据从哪里导出
system/core/adb/commandline.cpp
命令行接收事件查看
#include "bugreport.h"
int adb_commandline(int argc, const char** argv) {
...
} else if (!strcmp(argv[0], "bugreport")) {
Bugreport bugreport;
return bugreport.DoIt(argc, argv);
....
system/core/adb/bugreport.cpp
int Bugreport::DoIt(int argc, const char** argv) {
...
return SendShellCommand(bugz_command, false, &bugz_callback);
}
对应系统目录下的可执行文件
/system/bin # ls -al
-rwxr-xr-x 1 root shell 10264 2018-05-31 15:18 bugreport
-rwxr-xr-x 1 root shell 10264 2018-05-31 15:18 bugreportz
frameworks\native\cmds\bugreport\bugreport.cpp
其实bugreport就是 dumpstate,具体文件在手机系统目录 system/bin/dumpstate,dumpstate是可执行文件
Sufadi:/system/bin # ls dumpstate -all
ls dumpstate -all
-rwxr-xr-x 1 root shell 207136 2018-05-31 15:18 dumpstate
// This program will trigger the dumpstate service to start a call to
// dumpstate, then connect to the dumpstate local client to read the
// output. All of the dumpstate output is written to stdout, including
// any errors encountered while reading/writing the output.
int main() {
...
// Start the dumpstate service. 启动 dumpstate service
// 其实bugreport就是 dumpstate
property_set("ctl.start", "dumpstate");
...
while (1) {
...
char buffer[65536];
ssize_t bytes_read = TEMP_FAILURE_RETRY(read(s, buffer, sizeof(buffer)));
do {
bytes_written = TEMP_FAILURE_RETRY(write(STDOUT_FILENO,
buffer + bytes_read - bytes_to_send,
bytes_to_send));
if (bytes_written == -1) {
printf("Failed to write data to stdout: read %zd, trying to send %zd (%s)\n",
bytes_read, bytes_to_send, strerror(errno));
return 1;
}
bytes_to_send -= bytes_written;
} while (bytes_written != 0 && bytes_to_send > 0);
}
close(s);
return 0;
}
frameworks\native\cmds\dumpstate\dumpstate.cpp
static void dumpstate() {
DurationReporter duration_reporter("DUMPSTATE");
dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
RunCommand("UPTIME", {"uptime"});
DumpBlockStatFiles();
dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
DumpFile("MEMORY INFO", "/proc/meminfo");
RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
"pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
DumpFile("SLAB INFO", "/proc/slabinfo");
DumpFile("ZONEINFO", "/proc/zoneinfo");
DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
DumpFile("BUDDYINFO", "/proc/buddyinfo");
DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
DumpFile("KERNEL SYNC", "/d/sync");
RunCommand("PROCESSES AND THREADS",
{"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"});
RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
if (ds.IsZipping()) {
RunCommand(
"HARDWARE HALS",
{"lshal", std::string("--debug=") + kLsHalDebugPath},
CommandOptions::AS_ROOT);
ds.AddZipEntry("lshal-debug.txt", kLsHalDebugPath);
unlink(kLsHalDebugPath.c_str());
} else {
RunCommand(
"HARDWARE HALS", {"lshal", "--debug"}, CommandOptions::AS_ROOT);
}
RunCommand("PRINTENV", {"printenv"});
RunCommand("NETSTAT", {"netstat", "-nW"});
struct stat s;
if (stat("/proc/modules", &s) != 0) {
MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
} else {
RunCommand("LSMOD", {"lsmod"});
}
do_dmesg();
RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
/* Dump Bluetooth HCI logs */
ds.AddDir("/data/misc/bluetooth/logs", true);
if (!ds.do_early_screenshot_) {
MYLOGI("taking late screenshot\n");
ds.TakeScreenshot();
}
DoLogcat();
AddAnrTraceFiles();
// NOTE: tombstones are always added as separate entries in the zip archive
// and are not interspersed with the main report.
const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(),
"TOMBSTONE", true /* add_to_zip */);
if (!tombstones_dumped) {
printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
}
DumpPacketStats();
DoKmsg();
DumpIpAddrAndRules();
dump_route_tables();
RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
CommandOptions::WithTimeout(10).Build());
RunCommand("SYSTEM PROPERTIES", {"getprop"});
RunCommand("VOLD DUMP", {"vdc", "dump"});
RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
RunCommand("STORAGED TASKIOINFO", {"storaged", "-u"}, CommandOptions::WithTimeout(10).Build());
RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
printf("------ BACKLIGHTS ------\n");
printf("LCD brightness=");
DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
printf("Button brightness=");
DumpFile("", "/sys/class/leds/button-backlight/brightness");
printf("Keyboard brightness=");
DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
printf("ALS mode=");
DumpFile("", "/sys/class/leds/lcd-backlight/als");
printf("LCD driver registers:\n");
DumpFile("", "/sys/class/leds/lcd-backlight/registers");
printf("\n");
/* Binder state is expensive to look at as it uses a lot of memory. */
DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
ds.DumpstateBoard();
/* Migrate the ril_dumpstate to a device specific dumpstate? */
int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
if (rilDumpstateTimeout > 0) {
// su does not exist on user builds, so try running without it.
// This way any implementations of vril-dump that do not require
// root can run on user builds.
CommandOptions::CommandOptionsBuilder options =
CommandOptions::WithTimeout(rilDumpstateTimeout);
if (!PropertiesHelper::IsUserBuild()) {
options.AsRoot();
}
RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
}
printf("========================================================\n");
printf("== Android Framework Services\n");
printf("========================================================\n");
RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
10);
printf("========================================================\n");
printf("== Checkins\n");
printf("========================================================\n");
RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
printf("========================================================\n");
printf("== Running Application Activities\n");
printf("========================================================\n");
RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"});
printf("========================================================\n");
printf("== Running Application Services\n");
printf("========================================================\n");
RunDumpsys("APP SERVICES", {"activity", "service", "all"});
printf("========================================================\n");
printf("== Running Application Providers\n");
printf("========================================================\n");
RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
printf("========================================================\n");
printf("== Dropbox crashes\n");
printf("========================================================\n");
RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
printf("========================================================\n");
printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
ds.progress_->GetMax(), ds.progress_->GetInitialMax());
printf("========================================================\n");
printf("== dumpstate: done (id %d)\n", ds.id_);
printf("========================================================\n");
}
上述例如
- 查看电池信息
RunDumpsys(“CHECKIN BATTERYSTATS”, {“batterystats”, “-c”});
从bugreport导出手机数据,通过battery-historian解析原始数据进行多维度分析功耗异常
https://github.com/google/battery-historian