2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
30 #include <sys/prctl.h>
31 #include <sys/resource.h>
37 #include <android-base/stringprintf.h>
38 #include <android-base/file.h>
39 #include <cutils/properties.h>
41 #include "private/android_filesystem_config.h"
43 #define LOG_TAG "dumpstate"
44 #include <cutils/log.h>
46 #include "dumpstate.h"
48 #include "ziparchive/zip_writer.h"
50 #include "mincrypt/sha256.h"
52 using android::base::StringPrintf;
54 /* read before root is shed */
55 static char cmdline_buf[16384] = "(unknown)";
56 static const char *dump_traces_path = NULL;
58 // TODO: variables below should be part of dumpstate object
59 static unsigned long id;
60 static char build_type[PROPERTY_VALUE_MAX];
62 static std::unique_ptr<ZipWriter> zip_writer;
63 static std::set<std::string> mount_points;
65 int control_socket_fd = -1;
66 /* suffix of the bugreport files - it's typically the date (when invoked with -d),
67 * although it could be changed by the user using a system property */
68 static std::string suffix;
70 #define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
71 #define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
73 #define RAFT_DIR "/data/misc/raft"
74 #define RECOVERY_DIR "/cache/recovery"
75 #define RECOVERY_DATA_DIR "/data/misc/recovery"
76 #define LOGPERSIST_DATA_DIR "/data/misc/logd"
77 #define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
78 #define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
79 #define TOMBSTONE_DIR "/data/tombstones"
80 #define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
81 /* Can accomodate a tombstone number up to 9999. */
82 #define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
83 #define NUM_TOMBSTONES 10
84 #define WLUTIL "/vendor/xbin/wlutil"
87 char name[TOMBSTONE_MAX_LEN];
91 static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
93 const std::string ZIP_ROOT_DIR = "FS";
94 std::string bugreport_dir;
97 * List of supported zip format versions.
99 * See bugreport-format.txt for more info.
101 static std::string VERSION_DEFAULT = "1.0";
103 bool is_user_build() {
104 return 0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1);
107 /* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones,
108 * otherwise gets just those modified in the last half an hour. */
109 static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
110 time_t thirty_minutes_ago = now - 60*30;
111 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
112 snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
113 int fd = TEMP_FAILURE_RETRY(open(data[i].name,
114 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
116 if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
117 (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) {
126 // for_each_pid() callback to get mount info about a process.
127 void do_mountinfo(int pid, const char *name) {
130 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
132 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
133 char linkname[PATH_MAX];
134 ssize_t r = readlink(path, linkname, PATH_MAX);
136 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
141 if (mount_points.find(linkname) == mount_points.end()) {
142 // First time this mount point was found: add it
143 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
144 if (add_zip_entry(ZIP_ROOT_DIR + path, path)) {
145 mount_points.insert(linkname);
147 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
152 void add_mountinfo() {
153 if (!zip_writer) return;
154 const char *title = "MOUNT INFO";
155 mount_points.clear();
156 DurationReporter duration_reporter(title, NULL);
157 for_each_pid(do_mountinfo, NULL);
158 MYLOGD("%s: %d entries added to zip file\n", title, (int) mount_points.size());
161 static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
167 d = opendir(driverpath);
172 while ((de = readdir(d))) {
173 if (de->d_type != DT_LNK) {
176 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
177 dump_file(title, path);
183 // return pid of a userspace process. If not found or error, return 0.
184 static unsigned int pid_of_process(const char* ps_name) {
190 if (!(proc_dir = opendir("/proc"))) {
191 MYLOGE("Can't open /proc\n");
195 while ((ps = readdir(proc_dir))) {
196 if (!(pid = atoi(ps->d_name))) {
199 android::base::ReadFileToString("/proc/"
200 + std::string(ps->d_name) + "/cmdline", &cmdline);
201 if (cmdline.find(ps_name) == std::string::npos) {
212 // dump anrd's trace and add to the zip file.
213 // 1. check if anrd is running on this device.
214 // 2. send a SIGUSR1 to its pid which will dump anrd's trace.
215 // 3. wait until the trace generation completes and add to the zip file.
216 static bool dump_anrd_trace() {
218 char buf[50], path[PATH_MAX];
219 struct dirent *trace;
223 long long cur_size = 0;
224 const char *trace_path = "/data/misc/anrd/";
227 MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
231 // find anrd's pid if it is running.
232 pid = pid_of_process("/system/xbin/anrd");
235 // send SIGUSR1 to the anrd to generate a trace.
236 sprintf(buf, "%u", pid);
237 if (run_command("ANRD_DUMP", 1, "kill", "-SIGUSR1", buf, NULL)) {
238 MYLOGE("anrd signal timed out. Please manually collect trace\n");
242 // identify the trace file by its creation time.
243 if (!(trace_dir = opendir(trace_path))) {
244 MYLOGE("Can't open trace file under %s\n", trace_path);
246 while ((trace = readdir(trace_dir))) {
247 if (strcmp(trace->d_name, ".") == 0
248 || strcmp(trace->d_name, "..") == 0) {
251 sprintf(path, "%s%s", trace_path, trace->d_name);
252 if (stat(path, &st) == 0) {
253 if (st.st_ctime > max_ctime) {
254 max_ctime = st.st_ctime;
255 sprintf(buf, "%s", trace->d_name);
261 // Wait until the dump completes by checking the size of the trace.
263 sprintf(path, "%s%s", trace_path, buf);
266 if (stat(path, &st) == 0) {
267 if (st.st_size == cur_size) {
269 } else if (st.st_size > cur_size) {
270 cur_size = st.st_size;
275 MYLOGE("Cant stat() %s anymore\n", path);
279 // Add to the zip file.
280 if (!add_zip_entry("anrd_trace.txt", path)) {
281 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
284 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
289 MYLOGE("Can't stats any trace file under %s\n", trace_path);
295 static void dump_systrace() {
297 MYLOGD("Not dumping systrace because zip_writer is not set\n");
300 std::string systrace_path = bugreport_dir + "/systrace-" + suffix + ".txt";
301 if (systrace_path.empty()) {
302 MYLOGE("Not dumping systrace because path is empty\n");
305 const char* path = "/sys/kernel/debug/tracing/tracing_on";
307 if (read_file_as_long(path, &is_tracing)) {
308 return; // error already logged
310 if (is_tracing <= 0) {
311 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
315 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
316 systrace_path.c_str());
317 if (run_command("SYSTRACE", 120, "/system/bin/atrace", "--async_dump", "-o",
318 systrace_path.c_str(), NULL)) {
319 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
320 // TODO: run_command tries to kill the process, but atrace doesn't die peacefully; ideally,
321 // we should call strace to stop itself, but there is no such option yet (just a
322 // --async_stop, which stops and dump
323 // if (run_command("SYSTRACE", 10, "/system/bin/atrace", "--kill", NULL)) {
324 // MYLOGE("could not stop systrace ");
327 if (!add_zip_entry("systrace.txt", systrace_path)) {
328 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
330 if (remove(systrace_path.c_str())) {
331 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
336 static void dump_raft() {
337 if (is_user_build()) {
341 std::string raft_log_path = bugreport_dir + "/raft_log.txt";
342 if (raft_log_path.empty()) {
343 MYLOGD("raft_log_path is empty\n");
348 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
349 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
354 // Write compressed and encoded raft logs to stdout if not zip_writer.
355 run_command("RAFT LOGS", 600, "logcompressor", "-r", RAFT_DIR, NULL);
359 run_command("RAFT LOGS", 600, "logcompressor", "-n", "-r", RAFT_DIR,
360 "-o", raft_log_path.c_str(), NULL);
361 if (!add_zip_entry("raft_log.txt", raft_log_path)) {
362 MYLOGE("Unable to add raft log %s to zip file\n", raft_log_path.c_str());
364 if (remove(raft_log_path.c_str())) {
365 MYLOGE("Error removing raft file %s: %s\n", raft_log_path.c_str(), strerror(errno));
370 static bool skip_not_stat(const char *path) {
371 static const char stat[] = "/stat";
372 size_t len = strlen(path);
373 if (path[len - 1] == '/') { /* Directory? */
376 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
379 static bool skip_none(const char *path) {
383 static const char mmcblk0[] = "/sys/block/mmcblk0/";
384 unsigned long worst_write_perf = 20000; /* in KB/s */
388 // Name units description
389 // ---- ----- -----------
390 // read I/Os requests number of read I/Os processed
391 #define __STAT_READ_IOS 0
392 // read merges requests number of read I/Os merged with in-queue I/O
393 #define __STAT_READ_MERGES 1
394 // read sectors sectors number of sectors read
395 #define __STAT_READ_SECTORS 2
396 // read ticks milliseconds total wait time for read requests
397 #define __STAT_READ_TICKS 3
398 // write I/Os requests number of write I/Os processed
399 #define __STAT_WRITE_IOS 4
400 // write merges requests number of write I/Os merged with in-queue I/O
401 #define __STAT_WRITE_MERGES 5
402 // write sectors sectors number of sectors written
403 #define __STAT_WRITE_SECTORS 6
404 // write ticks milliseconds total wait time for write requests
405 #define __STAT_WRITE_TICKS 7
406 // in_flight requests number of I/Os currently in flight
407 #define __STAT_IN_FLIGHT 8
408 // io_ticks milliseconds total time this block device has been active
409 #define __STAT_IO_TICKS 9
410 // time_in_queue milliseconds total wait time for all requests
411 #define __STAT_IN_QUEUE 10
412 #define __STAT_NUMBER_FIELD 11
414 // read I/Os, write I/Os
415 // =====================
417 // These values increment when an I/O request completes.
419 // read merges, write merges
420 // =========================
422 // These values increment when an I/O request is merged with an
423 // already-queued I/O request.
425 // read sectors, write sectors
426 // ===========================
428 // These values count the number of sectors read from or written to this
429 // block device. The "sectors" in question are the standard UNIX 512-byte
430 // sectors, not any device- or filesystem-specific block size. The
431 // counters are incremented when the I/O completes.
432 #define SECTOR_SIZE 512
434 // read ticks, write ticks
435 // =======================
437 // These values count the number of milliseconds that I/O requests have
438 // waited on this block device. If there are multiple I/O requests waiting,
439 // these values will increase at a rate greater than 1000/second; for
440 // example, if 60 read requests wait for an average of 30 ms, the read_ticks
441 // field will increase by 60*30 = 1800.
446 // This value counts the number of I/O requests that have been issued to
447 // the device driver but have not yet completed. It does not include I/O
448 // requests that are in the queue but not yet issued to the device driver.
453 // This value counts the number of milliseconds during which the device has
454 // had I/O requests queued.
459 // This value counts the number of milliseconds that I/O requests have waited
460 // on this block device. If there are multiple I/O requests waiting, this
461 // value will increase as the product of the number of milliseconds times the
462 // number of requests waiting (see "read ticks" above for an example).
466 static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
467 unsigned long long fields[__STAT_NUMBER_FIELD];
469 char *cp, *buffer = NULL;
471 FILE *fp = fdopen(fd, "rb");
472 getline(&buffer, &i, fp);
478 while ((i > 0) && (buffer[i - 1] == '\n')) {
486 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
487 fields[i] = strtoull(cp, &cp, 10);
488 if (fields[i] != 0) {
492 if (z) { /* never accessed */
497 if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
498 path += sizeof(mmcblk0) - 1;
501 printf("%s: %s\n", path, buffer);
504 if (fields[__STAT_IO_TICKS]) {
505 unsigned long read_perf = 0;
506 unsigned long read_ios = 0;
507 if (fields[__STAT_READ_TICKS]) {
508 unsigned long long divisor = fields[__STAT_READ_TICKS]
509 * fields[__STAT_IO_TICKS];
510 read_perf = ((unsigned long long)SECTOR_SIZE
511 * fields[__STAT_READ_SECTORS]
512 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
514 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
515 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
519 unsigned long write_perf = 0;
520 unsigned long write_ios = 0;
521 if (fields[__STAT_WRITE_TICKS]) {
522 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
523 * fields[__STAT_IO_TICKS];
524 write_perf = ((unsigned long long)SECTOR_SIZE
525 * fields[__STAT_WRITE_SECTORS]
526 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
528 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
529 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
533 unsigned queue = (fields[__STAT_IN_QUEUE]
534 + (fields[__STAT_IO_TICKS] >> 1))
535 / fields[__STAT_IO_TICKS];
537 if (!write_perf && !write_ios) {
538 printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
539 path, read_perf, read_ios, queue);
541 printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
542 path, read_perf, read_ios, write_perf, write_ios, queue);
545 /* bugreport timeout factor adjustment */
546 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
547 worst_write_perf = write_perf;
553 /* Copied policy from system/core/logd/LogBuffer.cpp */
555 #define LOG_BUFFER_SIZE (256 * 1024)
556 #define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
557 #define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
559 static bool valid_size(unsigned long value) {
560 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
564 long pages = sysconf(_SC_PHYS_PAGES);
569 long pagesize = sysconf(_SC_PAGESIZE);
571 pagesize = PAGE_SIZE;
574 // maximum memory impact a somewhat arbitrary ~3%
575 pages = (pages + 31) / 32;
576 unsigned long maximum = pages * pagesize;
578 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
582 return value <= maximum;
585 static unsigned long property_get_size(const char *key) {
587 char *cp, property[PROPERTY_VALUE_MAX];
589 property_get(key, property, "");
590 value = strtoul(property, &cp, 10);
608 if (!valid_size(value)) {
616 static unsigned long logcat_timeout(const char *name) {
617 static const char global_tuneable[] = "persist.logd.size"; // Settings App
618 static const char global_default[] = "ro.logd.size"; // BoardConfig.mk
619 char key[PROP_NAME_MAX];
620 unsigned long property_size, default_size;
622 default_size = property_get_size(global_tuneable);
624 default_size = property_get_size(global_default);
627 snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
628 property_size = property_get_size(key);
630 if (!property_size) {
631 snprintf(key, sizeof(key), "%s.%s", global_default, name);
632 property_size = property_get_size(key);
635 if (!property_size) {
636 property_size = default_size;
639 if (!property_size) {
640 property_size = LOG_BUFFER_SIZE;
643 /* Engineering margin is ten-fold our guess */
644 return 10 * (property_size + worst_write_perf) / worst_write_perf;
647 /* End copy from system/core/logd/LogBuffer.cpp */
649 /* dumps the current system state to stdout */
650 static void print_header(std::string version) {
651 char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
652 char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
653 char network[PROPERTY_VALUE_MAX], date[80];
655 property_get("ro.build.display.id", build, "(unknown)");
656 property_get("ro.build.fingerprint", fingerprint, "(unknown)");
657 property_get("ro.build.type", build_type, "(unknown)");
658 property_get("gsm.version.baseband", radio, "(unknown)");
659 property_get("ro.bootloader", bootloader, "(unknown)");
660 property_get("gsm.operator.alpha", network, "(unknown)");
661 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
663 printf("========================================================\n");
664 printf("== dumpstate: %s\n", date);
665 printf("========================================================\n");
668 printf("Build: %s\n", build);
669 printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */
670 printf("Bootloader: %s\n", bootloader);
671 printf("Radio: %s\n", radio);
672 printf("Network: %s\n", network);
675 dump_file(NULL, "/proc/version");
676 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
677 printf("Bugreport format version: %s\n", version.c_str());
678 printf("Dumpstate info: id=%lu pid=%d\n", id, getpid());
682 // List of file extensions that can cause a zip file attachment to be rejected by some email
683 // service providers.
684 static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
685 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
686 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
687 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
690 bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
692 MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
696 std::string valid_name = entry_name;
698 // Rename extension if necessary.
699 size_t idx = entry_name.rfind(".");
700 if (idx != std::string::npos) {
701 std::string extension = entry_name.substr(idx);
702 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
703 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
704 valid_name = entry_name + ".renamed";
705 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
709 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
710 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
711 int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(),
712 ZipWriter::kCompress, get_mtime(fd, now));
714 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
715 ZipWriter::ErrorCodeString(err));
719 std::vector<uint8_t> buffer(65536);
721 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), sizeof(buffer)));
722 if (bytes_read == 0) {
724 } else if (bytes_read == -1) {
725 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
728 err = zip_writer->WriteBytes(buffer.data(), bytes_read);
730 MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
735 err = zip_writer->FinishEntry();
737 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
744 bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
745 ScopedFd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
746 if (fd.get() == -1) {
747 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
751 return add_zip_entry_from_fd(entry_name, fd.get());
754 /* adds a file to the existing zipped bugreport */
755 static int _add_file_from_fd(const char *title, const char *path, int fd) {
756 return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
759 // TODO: move to util.cpp
760 void add_dir(const char *dir, bool recursive) {
762 MYLOGD("Not adding dir %s because zip_writer is not set\n", dir);
765 MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive);
766 DurationReporter duration_reporter(dir, NULL);
767 dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd);
770 /* adds a text entry entry to the existing zip file. */
771 static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
773 MYLOGD("Not adding text zip entry %s because zip_writer is not set\n", entry_name.c_str());
776 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
777 int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
779 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
780 ZipWriter::ErrorCodeString(err));
784 err = zip_writer->WriteBytes(content.c_str(), content.length());
786 MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
787 ZipWriter::ErrorCodeString(err));
791 err = zip_writer->FinishEntry();
793 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
800 static void dump_iptables() {
801 run_command("IPTABLES", 10, "iptables", "-L", "-nvx", NULL);
802 run_command("IP6TABLES", 10, "ip6tables", "-L", "-nvx", NULL);
803 run_command("IPTABLE NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL);
805 run_command("IPTABLE MANGLE", 10, "iptables", "-t", "mangle", "-L", "-nvx", NULL);
806 run_command("IP6TABLE MANGLE", 10, "ip6tables", "-t", "mangle", "-L", "-nvx", NULL);
807 run_command("IPTABLE RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL);
808 run_command("IP6TABLE RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
811 static void dumpstate(const std::string& screenshot_path, const std::string& version) {
812 DurationReporter duration_reporter("DUMPSTATE");
813 unsigned long timeout;
815 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
816 run_command("UPTIME", 10, "uptime", NULL);
817 dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
818 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
819 dump_file("MEMORY INFO", "/proc/meminfo");
820 run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-H", NULL);
821 run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
822 dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
823 dump_file("VMALLOC INFO", "/proc/vmallocinfo");
824 dump_file("SLAB INFO", "/proc/slabinfo");
825 dump_file("ZONEINFO", "/proc/zoneinfo");
826 dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
827 dump_file("BUDDYINFO", "/proc/buddyinfo");
828 dump_file("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
830 dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
831 dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
832 dump_file("KERNEL SYNC", "/d/sync");
834 run_command("PROCESSES AND THREADS", 10, "ps", "-Z", "-t", "-p", "-P", NULL);
835 run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
837 run_command("PRINTENV", 10, "printenv", NULL);
838 run_command("NETSTAT", 10, "netstat", "-n", NULL);
839 run_command("LSMOD", 10, "lsmod", NULL);
843 run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
844 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
845 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
846 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
848 if (!screenshot_path.empty()) {
849 MYLOGI("taking late screenshot\n");
850 take_screenshot(screenshot_path);
851 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
854 // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
856 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
857 if (timeout < 20000) {
860 run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
864 timeout = logcat_timeout("events");
865 if (timeout < 20000) {
868 run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
873 timeout = logcat_timeout("radio");
874 if (timeout < 20000) {
877 run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
883 run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
885 /* show the traces we collected in main(), if that was done */
886 if (dump_traces_path != NULL) {
887 dump_file("VM TRACES JUST NOW", dump_traces_path);
890 /* only show ANR traces if they're less than 15 minutes old */
892 char anr_traces_path[PATH_MAX];
893 property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
894 if (!anr_traces_path[0]) {
895 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
897 int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
898 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
900 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
902 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
906 /* slow traces for slow operations */
907 if (anr_traces_path[0] != 0) {
908 int tail = strlen(anr_traces_path)-1;
909 while (tail > 0 && anr_traces_path[tail] != '/') {
914 sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
915 if (stat(anr_traces_path, &st)) {
916 // No traces file at this index, done with the files.
919 dump_file("VM TRACES WHEN SLOW", anr_traces_path);
925 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
926 if (tombstone_data[i].fd != -1) {
927 const char *name = tombstone_data[i].name;
928 int fd = tombstone_data[i].fd;
931 if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
932 MYLOGE("Unable to add tombstone %s to zip file\n", name);
935 dump_file_from_fd("TOMBSTONE", name, fd);
938 tombstone_data[i].fd = -1;
942 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
945 dump_file("NETWORK DEV INFO", "/proc/net/dev");
946 dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
947 dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
948 dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
949 dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
951 if (!stat(PSTORE_LAST_KMSG, &st)) {
952 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
953 dump_file("LAST KMSG", PSTORE_LAST_KMSG);
954 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
955 dump_file("LAST KMSG", ALT_PSTORE_LAST_KMSG);
957 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
958 dump_file("LAST KMSG", "/proc/last_kmsg");
961 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
962 run_command("LAST LOGCAT", 10, "logcat", "-L",
969 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
971 run_command("NETWORK INTERFACES", 10, "ip", "link", NULL);
973 run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL);
974 run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL);
976 run_command("IP RULES", 10, "ip", "rule", "show", NULL);
977 run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
981 run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
982 run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
983 run_command("MULTICAST ADDRESSES", 10, "ip", "maddr", NULL);
984 run_command("WIFI NETWORKS", 20, "wpa_cli", "IFNAME=wlan0", "list_networks", NULL);
987 run_command("ND OFFLOAD TABLE", 5,
988 SU_PATH, "root", WLUTIL, "nd_hostip", NULL);
990 run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
991 SU_PATH, "root", WLUTIL, "counters", NULL);
993 run_command("ND OFFLOAD STATUS (1)", 5,
994 SU_PATH, "root", WLUTIL, "nd_status", NULL);
997 dump_file("INTERRUPTS (1)", "/proc/interrupts");
999 run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "-t", "10", "connectivity", "--diag", NULL);
1001 #ifdef FWDUMP_bcmdhd
1002 run_command("DUMP WIFI STATUS", 20,
1003 SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
1005 run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
1006 SU_PATH, "root", WLUTIL, "counters", NULL);
1008 run_command("ND OFFLOAD STATUS (2)", 5,
1009 SU_PATH, "root", WLUTIL, "nd_status", NULL);
1011 dump_file("INTERRUPTS (2)", "/proc/interrupts");
1015 run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
1016 run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
1018 run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);
1020 run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
1022 printf("------ BACKLIGHTS ------\n");
1023 printf("LCD brightness=");
1024 dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness");
1025 printf("Button brightness=");
1026 dump_file(NULL, "/sys/class/leds/button-backlight/brightness");
1027 printf("Keyboard brightness=");
1028 dump_file(NULL, "/sys/class/leds/keyboard-backlight/brightness");
1029 printf("ALS mode=");
1030 dump_file(NULL, "/sys/class/leds/lcd-backlight/als");
1031 printf("LCD driver registers:\n");
1032 dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
1035 /* Binder state is expensive to look at as it uses a lot of memory. */
1036 dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1037 dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1038 dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1039 dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
1040 dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
1042 printf("========================================================\n");
1043 printf("== Board\n");
1044 printf("========================================================\n");
1049 /* Migrate the ril_dumpstate to a dumpstate_board()? */
1050 char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
1051 property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
1052 if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
1053 if (is_user_build()) {
1054 // su does not exist on user builds, so try running without it.
1055 // This way any implementations of vril-dump that do not require
1056 // root can run on user builds.
1057 run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
1060 run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
1061 SU_PATH, "root", "vril-dump", NULL);
1065 printf("========================================================\n");
1066 printf("== Android Framework Services\n");
1067 printf("========================================================\n");
1069 run_command("DUMPSYS", 60, "dumpsys", "-t", "60", "--skip", "meminfo", "cpuinfo", NULL);
1071 printf("========================================================\n");
1072 printf("== Checkins\n");
1073 printf("========================================================\n");
1075 run_command("CHECKIN BATTERYSTATS", 30, "dumpsys", "-t", "30", "batterystats", "-c", NULL);
1076 run_command("CHECKIN MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "--checkin", NULL);
1077 run_command("CHECKIN NETSTATS", 30, "dumpsys", "-t", "30", "netstats", "--checkin", NULL);
1078 run_command("CHECKIN PROCSTATS", 30, "dumpsys", "-t", "30", "procstats", "-c", NULL);
1079 run_command("CHECKIN USAGESTATS", 30, "dumpsys", "-t", "30", "usagestats", "-c", NULL);
1080 run_command("CHECKIN PACKAGE", 30, "dumpsys", "-t", "30", "package", "--checkin", NULL);
1082 printf("========================================================\n");
1083 printf("== Running Application Activities\n");
1084 printf("========================================================\n");
1086 run_command("APP ACTIVITIES", 30, "dumpsys", "-t", "30", "activity", "all", NULL);
1088 printf("========================================================\n");
1089 printf("== Running Application Services\n");
1090 printf("========================================================\n");
1092 run_command("APP SERVICES", 30, "dumpsys", "-t", "30", "activity", "service", "all", NULL);
1094 printf("========================================================\n");
1095 printf("== Running Application Providers\n");
1096 printf("========================================================\n");
1098 run_command("APP PROVIDERS", 30, "dumpsys", "-t", "30", "activity", "provider", "all", NULL);
1101 printf("========================================================\n");
1102 printf("== Final progress (pid %d): %d/%d (originally %d)\n",
1103 getpid(), progress, weight_total, WEIGHT_TOTAL);
1104 printf("========================================================\n");
1105 printf("== dumpstate: done\n");
1106 printf("========================================================\n");
1109 static void usage() {
1111 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
1112 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1113 " -h: display this help message\n"
1114 " -b: play sound file instead of vibrate, at beginning of job\n"
1115 " -e: play sound file instead of vibrate, at end of job\n"
1116 " -o: write to file (instead of stdout)\n"
1117 " -d: append date to filename (requires -o)\n"
1118 " -p: capture screenshot to filename.png (requires -o)\n"
1119 " -z: generate zipped file (requires -o)\n"
1120 " -s: write output to control socket (for init)\n"
1121 " -S: write file location to control socket (for init; requires -o and -z)"
1122 " -q: disable vibrate\n"
1123 " -B: send broadcast when finished (requires -o)\n"
1124 " -P: send broadcast when started and update system properties on "
1125 "progress (requires -o and -B)\n"
1126 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1127 "shouldn't be used with -P)\n"
1128 " -V: sets the bugreport format version (valid values: %s)\n",
1129 VERSION_DEFAULT.c_str());
1132 static void sigpipe_handler(int n) {
1133 // don't complain to stderr or stdout
1134 _exit(EXIT_FAILURE);
1137 /* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1140 static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
1142 if (!add_zip_entry(bugreport_name, bugreport_path)) {
1143 MYLOGE("Failed to add text entry to .zip file\n");
1146 if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
1147 MYLOGE("Failed to add main_entry.txt to .zip file\n");
1151 int32_t err = zip_writer->Finish();
1153 MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
1157 if (is_user_build()) {
1158 MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
1159 if (remove(bugreport_path.c_str())) {
1160 ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
1163 MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1169 static std::string SHA256_file_hash(std::string filepath) {
1170 ScopedFd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC
1172 if (fd.get() == -1) {
1173 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
1180 std::vector<uint8_t> buffer(65536);
1182 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1183 if (bytes_read == 0) {
1185 } else if (bytes_read == -1) {
1186 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
1190 SHA256_update(&ctx, buffer.data(), bytes_read);
1193 uint8_t hash[SHA256_DIGEST_SIZE];
1194 memcpy(hash, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
1195 char hash_buffer[SHA256_DIGEST_SIZE * 2 + 1];
1196 for(size_t i = 0; i < SHA256_DIGEST_SIZE; i++) {
1197 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
1199 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1200 return std::string(hash_buffer);
1203 int main(int argc, char *argv[]) {
1204 struct sigaction sigact;
1205 int do_add_date = 0;
1206 int do_zip_file = 0;
1208 char* use_outfile = 0;
1210 int use_control_socket = 0;
1212 int do_broadcast = 0;
1213 int do_early_screenshot = 0;
1214 int is_remote_mode = 0;
1215 std::string version = VERSION_DEFAULT;
1221 /* gets the sequential id */
1222 char last_id[PROPERTY_VALUE_MAX];
1223 property_get("dumpstate.last_id", last_id, "0");
1224 id = strtoul(last_id, NULL, 10) + 1;
1225 snprintf(last_id, sizeof(last_id), "%lu", id);
1226 property_set("dumpstate.last_id", last_id);
1227 MYLOGI("dumpstate id: %lu\n", id);
1229 /* clear SIGPIPE handler */
1230 memset(&sigact, 0, sizeof(sigact));
1231 sigact.sa_handler = sigpipe_handler;
1232 sigaction(SIGPIPE, &sigact, NULL);
1234 /* set as high priority, and protect from OOM killer */
1235 setpriority(PRIO_PROCESS, 0, -20);
1237 FILE *oom_adj = fopen("/proc/self/oom_score_adj", "we");
1239 fputs("-1000", oom_adj);
1242 /* fallback to kernels <= 2.6.35 */
1243 oom_adj = fopen("/proc/self/oom_adj", "we");
1245 fputs("-17", oom_adj);
1250 /* parse arguments */
1252 format_args(argc, const_cast<const char **>(argv), &args);
1253 MYLOGD("Dumpstate command line: %s\n", args.c_str());
1255 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
1257 case 'd': do_add_date = 1; break;
1258 case 'z': do_zip_file = 1; break;
1259 case 'o': use_outfile = optarg; break;
1260 case 's': use_socket = 1; break;
1261 case 'S': use_control_socket = 1; break;
1262 case 'v': break; // compatibility no-op
1263 case 'q': do_vibrate = 0; break;
1264 case 'p': do_fb = 1; break;
1265 case 'P': do_update_progress = 1; break;
1266 case 'R': is_remote_mode = 1; break;
1267 case 'B': do_broadcast = 1; break;
1268 case 'V': version = optarg; break;
1269 case '?': printf("\n");
1276 if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) {
1281 if (use_control_socket && !do_zip_file) {
1286 if (do_update_progress && !do_broadcast) {
1291 if (is_remote_mode && (do_update_progress || !do_broadcast || !do_zip_file || !do_add_date)) {
1296 if (version != VERSION_DEFAULT) {
1301 MYLOGI("bugreport format version: %s\n", version.c_str());
1303 do_early_screenshot = do_update_progress;
1305 // If we are going to use a socket, do it as early as possible
1306 // to avoid timeouts from bugreport.
1308 redirect_to_socket(stdout, "dumpstate");
1311 if (use_control_socket) {
1312 MYLOGD("Opening control socket\n");
1313 control_socket_fd = open_socket("dumpstate");
1314 do_update_progress = 1;
1317 /* full path of the temporary file containing the bugreport */
1318 std::string tmp_path;
1320 /* full path of the file containing the dumpstate logs*/
1321 std::string log_path;
1323 /* full path of the systrace file, when enabled */
1324 std::string systrace_path;
1326 /* full path of the temporary file containing the screenshot (when requested) */
1327 std::string screenshot_path;
1329 /* base name (without suffix or extensions) of the bugreport files */
1330 std::string base_name;
1332 /* pointer to the actual path, be it zip or text */
1335 /* pointer to the zipped file */
1336 std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
1338 /* redirect output if needed */
1339 bool is_redirecting = !use_socket && use_outfile;
1341 if (is_redirecting) {
1342 bugreport_dir = dirname(use_outfile);
1343 base_name = basename(use_outfile);
1346 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1351 char build_id[PROPERTY_VALUE_MAX];
1352 property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
1353 base_name = base_name + "-" + build_id;
1355 // TODO: if dumpstate was an object, the paths could be internal variables and then
1356 // we could have a function to calculate the derived values, such as:
1357 // screenshot_path = GetPath(".png");
1358 screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1360 tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
1361 log_path = bugreport_dir + "/dumpstate_log-" + suffix + "-"
1362 + std::to_string(getpid()) + ".txt";
1364 MYLOGD("Bugreport dir: %s\n"
1368 "Temporary path: %s\n"
1369 "Screenshot path: %s\n",
1370 bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(),
1371 log_path.c_str(), tmp_path.c_str(), screenshot_path.c_str());
1374 path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1375 MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
1376 create_parent_dirs(path.c_str());
1377 zip_file.reset(fopen(path.c_str(), "wb"));
1379 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
1382 zip_writer.reset(new ZipWriter(zip_file.get()));
1384 add_text_zip_entry("version.txt", version);
1387 if (do_update_progress) {
1390 std::vector<std::string> am_args = {
1391 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1392 "--es", "android.intent.extra.NAME", suffix,
1393 "--ei", "android.intent.extra.ID", std::to_string(id),
1394 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1395 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1398 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1400 if (use_control_socket) {
1401 dprintf(control_socket_fd, "BEGIN:%s\n", path.c_str());
1406 /* read /proc/cmdline before dropping root */
1407 FILE *cmdline = fopen("/proc/cmdline", "re");
1409 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1413 /* open the vibrator before dropping root */
1414 std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
1416 vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
1418 vibrate(vibrator.get(), 150);
1422 if (do_fb && do_early_screenshot) {
1423 if (screenshot_path.empty()) {
1424 // should not have happened
1425 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
1427 MYLOGI("taking early screenshot\n");
1428 take_screenshot(screenshot_path);
1429 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
1430 if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
1431 MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
1432 screenshot_path.c_str(), strerror(errno));
1438 if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
1439 MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
1443 if (is_redirecting) {
1444 redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
1445 if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
1446 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1447 log_path.c_str(), strerror(errno));
1449 /* TODO: rather than generating a text file now and zipping it later,
1450 it would be more efficient to redirect stdout to the zip entry
1451 directly, but the libziparchive doesn't support that option yet. */
1452 redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
1453 if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
1454 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
1455 tmp_path.c_str(), strerror(errno));
1458 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1459 // In particular, DurationReport objects should be created passing 'title, NULL', so their
1460 // duration is logged into MYLOG instead.
1461 print_header(version);
1463 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1464 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1466 if (!dump_anrd_trace()) {
1470 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1473 // Invoking the following dumpsys calls before dump_traces() to try and
1474 // keep the system stats as close to its initial state as possible.
1475 run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "-a", NULL);
1476 run_command_as_shell("DUMPSYS CPUINFO", 10, "dumpsys", "-t", "10", "cpuinfo", "-a", NULL);
1478 /* collect stack traces from Dalvik and native processes (needs root) */
1479 dump_traces_path = dump_traces();
1481 /* Run some operations that require root. */
1482 get_tombstone_fds(tombstone_data);
1483 add_dir(RECOVERY_DIR, true);
1484 add_dir(RECOVERY_DATA_DIR, true);
1485 add_dir(LOGPERSIST_DATA_DIR, false);
1486 if (!is_user_build()) {
1487 add_dir(PROFILE_DATA_DIR_CUR, true);
1488 add_dir(PROFILE_DATA_DIR_REF, true);
1493 if (!drop_root_user()) {
1497 dumpstate(do_early_screenshot ? "": screenshot_path, version);
1499 /* close output if needed */
1500 if (is_redirecting) {
1504 /* rename or zip the (now complete) .tmp file to its final location */
1507 /* check if user changed the suffix using system properties */
1508 char key[PROPERTY_KEY_MAX];
1509 char value[PROPERTY_VALUE_MAX];
1510 snprintf(key, sizeof(key), "dumpstate.%d.name", getpid());
1511 property_get(key, value, "");
1512 bool change_suffix= false;
1514 /* must whitelist which characters are allowed, otherwise it could cross directories */
1515 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
1516 if (std::regex_match(value, valid_regex)) {
1517 change_suffix = true;
1519 MYLOGE("invalid suffix provided by user: %s\n", value);
1522 if (change_suffix) {
1523 MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), value);
1525 if (!screenshot_path.empty()) {
1526 std::string new_screenshot_path =
1527 bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1528 if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
1529 MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
1530 new_screenshot_path.c_str(), strerror(errno));
1532 screenshot_path = new_screenshot_path;
1537 bool do_text_file = true;
1539 std::string entry_name = base_name + "-" + suffix + ".txt";
1540 MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
1541 if (!finish_zip_file(entry_name, tmp_path, now)) {
1542 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
1543 do_text_file = true;
1545 do_text_file = false;
1546 // Since zip file is already created, it needs to be renamed.
1547 std::string new_path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1548 if (path != new_path) {
1549 MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
1550 if (rename(path.c_str(), new_path.c_str())) {
1551 MYLOGE("rename(%s, %s): %s\n", path.c_str(),
1552 new_path.c_str(), strerror(errno));
1560 path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt";
1561 MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
1562 if (rename(tmp_path.c_str(), path.c_str())) {
1563 MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
1567 if (use_control_socket) {
1569 dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
1570 "for more details\n", log_path.c_str());
1572 dprintf(control_socket_fd, "OK:%s\n", path.c_str());
1577 /* vibrate a few but shortly times to let user know it's finished */
1579 for (int i = 0; i < 3; i++) {
1580 vibrate(vibrator.get(), 75);
1581 usleep((75 + 50) * 1000);
1585 /* tell activity manager we're done */
1587 if (!path.empty()) {
1588 MYLOGI("Final bugreport path: %s\n", path.c_str());
1590 std::vector<std::string> am_args = {
1591 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1592 "--ei", "android.intent.extra.ID", std::to_string(id),
1593 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1594 "--ei", "android.intent.extra.MAX", std::to_string(weight_total),
1595 "--es", "android.intent.extra.BUGREPORT", path,
1596 "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
1600 am_args.push_back("--es");
1601 am_args.push_back("android.intent.extra.SCREENSHOT");
1602 am_args.push_back(screenshot_path);
1604 if (is_remote_mode) {
1605 am_args.push_back("--es");
1606 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1607 am_args.push_back(SHA256_file_hash(path));
1608 send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1610 send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
1613 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
1617 MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
1620 if (is_redirecting) {
1624 if (use_control_socket && control_socket_fd != -1) {
1625 MYLOGD("Closing control socket\n");
1626 close(control_socket_fd);