本文共 10654 字,大约阅读时间需要 35 分钟。
使用 adb bugreport 可以导出功耗分析所需文件,然后通过 进行更加详细的分析
adb bugreport > Bugreport.zipadb 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 -allls 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解析原始数据进行多维度分析功耗异常