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 max_ctime = 0, old_mtime;
224 long long cur_size = 0;
225 const char *trace_path = "/data/misc/anrd/";
228 MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
232 // find anrd's pid if it is running.
233 pid = pid_of_process("/system/xbin/anrd");
236 if (stat(trace_path, &st) == 0) {
237 old_mtime = st.st_mtime;
239 MYLOGE("Failed to find: %s\n", trace_path);
243 // send SIGUSR1 to the anrd to generate a trace.
244 sprintf(buf, "%u", pid);
245 if (run_command("ANRD_DUMP", 1, "kill", "-SIGUSR1", buf, NULL)) {
246 MYLOGE("anrd signal timed out. Please manually collect trace\n");
250 while (retry-- > 0 && old_mtime == st.st_mtime) {
252 stat(trace_path, &st);
255 if (retry < 0 && old_mtime == st.st_mtime) {
256 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
260 // identify the trace file by its creation time.
261 if (!(trace_dir = opendir(trace_path))) {
262 MYLOGE("Can't open trace file under %s\n", trace_path);
264 while ((trace = readdir(trace_dir))) {
265 if (strcmp(trace->d_name, ".") == 0
266 || strcmp(trace->d_name, "..") == 0) {
269 sprintf(path, "%s%s", trace_path, trace->d_name);
270 if (stat(path, &st) == 0) {
271 if (st.st_ctime > max_ctime) {
272 max_ctime = st.st_ctime;
273 sprintf(buf, "%s", trace->d_name);
279 // Wait until the dump completes by checking the size of the trace.
281 sprintf(path, "%s%s", trace_path, buf);
284 if (stat(path, &st) == 0) {
285 if (st.st_size == cur_size) {
287 } else if (st.st_size > cur_size) {
288 cur_size = st.st_size;
293 MYLOGE("Cant stat() %s anymore\n", path);
297 // Add to the zip file.
298 if (!add_zip_entry("anrd_trace.txt", path)) {
299 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
302 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
307 MYLOGE("Can't stats any trace file under %s\n", trace_path);
313 static void dump_systrace() {
315 MYLOGD("Not dumping systrace because zip_writer is not set\n");
318 std::string systrace_path = bugreport_dir + "/systrace-" + suffix + ".txt";
319 if (systrace_path.empty()) {
320 MYLOGE("Not dumping systrace because path is empty\n");
323 const char* path = "/sys/kernel/debug/tracing/tracing_on";
325 if (read_file_as_long(path, &is_tracing)) {
326 return; // error already logged
328 if (is_tracing <= 0) {
329 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
333 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
334 systrace_path.c_str());
335 if (run_command("SYSTRACE", 120, "/system/bin/atrace", "--async_dump", "-o",
336 systrace_path.c_str(), NULL)) {
337 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
338 // TODO: run_command tries to kill the process, but atrace doesn't die peacefully; ideally,
339 // we should call strace to stop itself, but there is no such option yet (just a
340 // --async_stop, which stops and dump
341 // if (run_command("SYSTRACE", 10, "/system/bin/atrace", "--kill", NULL)) {
342 // MYLOGE("could not stop systrace ");
345 if (!add_zip_entry("systrace.txt", systrace_path)) {
346 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
348 if (remove(systrace_path.c_str())) {
349 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
354 static void dump_raft() {
355 if (is_user_build()) {
359 std::string raft_log_path = bugreport_dir + "/raft_log.txt";
360 if (raft_log_path.empty()) {
361 MYLOGD("raft_log_path is empty\n");
366 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
367 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
372 // Write compressed and encoded raft logs to stdout if not zip_writer.
373 run_command("RAFT LOGS", 600, "logcompressor", "-r", RAFT_DIR, NULL);
377 run_command("RAFT LOGS", 600, "logcompressor", "-n", "-r", RAFT_DIR,
378 "-o", raft_log_path.c_str(), NULL);
379 if (!add_zip_entry("raft_log.txt", raft_log_path)) {
380 MYLOGE("Unable to add raft log %s to zip file\n", raft_log_path.c_str());
382 if (remove(raft_log_path.c_str())) {
383 MYLOGE("Error removing raft file %s: %s\n", raft_log_path.c_str(), strerror(errno));
388 static bool skip_not_stat(const char *path) {
389 static const char stat[] = "/stat";
390 size_t len = strlen(path);
391 if (path[len - 1] == '/') { /* Directory? */
394 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
397 static bool skip_none(const char *path) {
401 static const char mmcblk0[] = "/sys/block/mmcblk0/";
402 unsigned long worst_write_perf = 20000; /* in KB/s */
406 // Name units description
407 // ---- ----- -----------
408 // read I/Os requests number of read I/Os processed
409 #define __STAT_READ_IOS 0
410 // read merges requests number of read I/Os merged with in-queue I/O
411 #define __STAT_READ_MERGES 1
412 // read sectors sectors number of sectors read
413 #define __STAT_READ_SECTORS 2
414 // read ticks milliseconds total wait time for read requests
415 #define __STAT_READ_TICKS 3
416 // write I/Os requests number of write I/Os processed
417 #define __STAT_WRITE_IOS 4
418 // write merges requests number of write I/Os merged with in-queue I/O
419 #define __STAT_WRITE_MERGES 5
420 // write sectors sectors number of sectors written
421 #define __STAT_WRITE_SECTORS 6
422 // write ticks milliseconds total wait time for write requests
423 #define __STAT_WRITE_TICKS 7
424 // in_flight requests number of I/Os currently in flight
425 #define __STAT_IN_FLIGHT 8
426 // io_ticks milliseconds total time this block device has been active
427 #define __STAT_IO_TICKS 9
428 // time_in_queue milliseconds total wait time for all requests
429 #define __STAT_IN_QUEUE 10
430 #define __STAT_NUMBER_FIELD 11
432 // read I/Os, write I/Os
433 // =====================
435 // These values increment when an I/O request completes.
437 // read merges, write merges
438 // =========================
440 // These values increment when an I/O request is merged with an
441 // already-queued I/O request.
443 // read sectors, write sectors
444 // ===========================
446 // These values count the number of sectors read from or written to this
447 // block device. The "sectors" in question are the standard UNIX 512-byte
448 // sectors, not any device- or filesystem-specific block size. The
449 // counters are incremented when the I/O completes.
450 #define SECTOR_SIZE 512
452 // read ticks, write ticks
453 // =======================
455 // These values count the number of milliseconds that I/O requests have
456 // waited on this block device. If there are multiple I/O requests waiting,
457 // these values will increase at a rate greater than 1000/second; for
458 // example, if 60 read requests wait for an average of 30 ms, the read_ticks
459 // field will increase by 60*30 = 1800.
464 // This value counts the number of I/O requests that have been issued to
465 // the device driver but have not yet completed. It does not include I/O
466 // requests that are in the queue but not yet issued to the device driver.
471 // This value counts the number of milliseconds during which the device has
472 // had I/O requests queued.
477 // This value counts the number of milliseconds that I/O requests have waited
478 // on this block device. If there are multiple I/O requests waiting, this
479 // value will increase as the product of the number of milliseconds times the
480 // number of requests waiting (see "read ticks" above for an example).
484 static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
485 unsigned long long fields[__STAT_NUMBER_FIELD];
487 char *cp, *buffer = NULL;
489 FILE *fp = fdopen(fd, "rb");
490 getline(&buffer, &i, fp);
496 while ((i > 0) && (buffer[i - 1] == '\n')) {
504 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
505 fields[i] = strtoull(cp, &cp, 10);
506 if (fields[i] != 0) {
510 if (z) { /* never accessed */
515 if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
516 path += sizeof(mmcblk0) - 1;
519 printf("%s: %s\n", path, buffer);
522 if (fields[__STAT_IO_TICKS]) {
523 unsigned long read_perf = 0;
524 unsigned long read_ios = 0;
525 if (fields[__STAT_READ_TICKS]) {
526 unsigned long long divisor = fields[__STAT_READ_TICKS]
527 * fields[__STAT_IO_TICKS];
528 read_perf = ((unsigned long long)SECTOR_SIZE
529 * fields[__STAT_READ_SECTORS]
530 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
532 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
533 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
537 unsigned long write_perf = 0;
538 unsigned long write_ios = 0;
539 if (fields[__STAT_WRITE_TICKS]) {
540 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
541 * fields[__STAT_IO_TICKS];
542 write_perf = ((unsigned long long)SECTOR_SIZE
543 * fields[__STAT_WRITE_SECTORS]
544 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
546 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
547 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
551 unsigned queue = (fields[__STAT_IN_QUEUE]
552 + (fields[__STAT_IO_TICKS] >> 1))
553 / fields[__STAT_IO_TICKS];
555 if (!write_perf && !write_ios) {
556 printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
557 path, read_perf, read_ios, queue);
559 printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
560 path, read_perf, read_ios, write_perf, write_ios, queue);
563 /* bugreport timeout factor adjustment */
564 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
565 worst_write_perf = write_perf;
571 /* Copied policy from system/core/logd/LogBuffer.cpp */
573 #define LOG_BUFFER_SIZE (256 * 1024)
574 #define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
575 #define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
577 static bool valid_size(unsigned long value) {
578 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
582 long pages = sysconf(_SC_PHYS_PAGES);
587 long pagesize = sysconf(_SC_PAGESIZE);
589 pagesize = PAGE_SIZE;
592 // maximum memory impact a somewhat arbitrary ~3%
593 pages = (pages + 31) / 32;
594 unsigned long maximum = pages * pagesize;
596 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
600 return value <= maximum;
603 static unsigned long property_get_size(const char *key) {
605 char *cp, property[PROPERTY_VALUE_MAX];
607 property_get(key, property, "");
608 value = strtoul(property, &cp, 10);
626 if (!valid_size(value)) {
634 static unsigned long logcat_timeout(const char *name) {
635 static const char global_tuneable[] = "persist.logd.size"; // Settings App
636 static const char global_default[] = "ro.logd.size"; // BoardConfig.mk
637 char key[PROP_NAME_MAX];
638 unsigned long property_size, default_size;
640 default_size = property_get_size(global_tuneable);
642 default_size = property_get_size(global_default);
645 snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
646 property_size = property_get_size(key);
648 if (!property_size) {
649 snprintf(key, sizeof(key), "%s.%s", global_default, name);
650 property_size = property_get_size(key);
653 if (!property_size) {
654 property_size = default_size;
657 if (!property_size) {
658 property_size = LOG_BUFFER_SIZE;
661 /* Engineering margin is ten-fold our guess */
662 return 10 * (property_size + worst_write_perf) / worst_write_perf;
665 /* End copy from system/core/logd/LogBuffer.cpp */
667 /* dumps the current system state to stdout */
668 static void print_header(std::string version) {
669 char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
670 char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
671 char network[PROPERTY_VALUE_MAX], date[80];
673 property_get("ro.build.display.id", build, "(unknown)");
674 property_get("ro.build.fingerprint", fingerprint, "(unknown)");
675 property_get("ro.build.type", build_type, "(unknown)");
676 property_get("gsm.version.baseband", radio, "(unknown)");
677 property_get("ro.bootloader", bootloader, "(unknown)");
678 property_get("gsm.operator.alpha", network, "(unknown)");
679 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
681 printf("========================================================\n");
682 printf("== dumpstate: %s\n", date);
683 printf("========================================================\n");
686 printf("Build: %s\n", build);
687 printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */
688 printf("Bootloader: %s\n", bootloader);
689 printf("Radio: %s\n", radio);
690 printf("Network: %s\n", network);
693 dump_file(NULL, "/proc/version");
694 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
695 printf("Bugreport format version: %s\n", version.c_str());
696 printf("Dumpstate info: id=%lu pid=%d\n", id, getpid());
700 // List of file extensions that can cause a zip file attachment to be rejected by some email
701 // service providers.
702 static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
703 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
704 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
705 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
708 bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
710 MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
714 std::string valid_name = entry_name;
716 // Rename extension if necessary.
717 size_t idx = entry_name.rfind(".");
718 if (idx != std::string::npos) {
719 std::string extension = entry_name.substr(idx);
720 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
721 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
722 valid_name = entry_name + ".renamed";
723 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
727 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
728 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
729 int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(),
730 ZipWriter::kCompress, get_mtime(fd, now));
732 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
733 ZipWriter::ErrorCodeString(err));
737 std::vector<uint8_t> buffer(65536);
739 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), sizeof(buffer)));
740 if (bytes_read == 0) {
742 } else if (bytes_read == -1) {
743 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
746 err = zip_writer->WriteBytes(buffer.data(), bytes_read);
748 MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
753 err = zip_writer->FinishEntry();
755 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
762 bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
763 ScopedFd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
764 if (fd.get() == -1) {
765 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
769 return add_zip_entry_from_fd(entry_name, fd.get());
772 /* adds a file to the existing zipped bugreport */
773 static int _add_file_from_fd(const char *title, const char *path, int fd) {
774 return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
777 // TODO: move to util.cpp
778 void add_dir(const char *dir, bool recursive) {
780 MYLOGD("Not adding dir %s because zip_writer is not set\n", dir);
783 MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive);
784 DurationReporter duration_reporter(dir, NULL);
785 dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd);
788 /* adds a text entry entry to the existing zip file. */
789 static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
791 MYLOGD("Not adding text zip entry %s because zip_writer is not set\n", entry_name.c_str());
794 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
795 int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
797 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
798 ZipWriter::ErrorCodeString(err));
802 err = zip_writer->WriteBytes(content.c_str(), content.length());
804 MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
805 ZipWriter::ErrorCodeString(err));
809 err = zip_writer->FinishEntry();
811 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
818 static void dump_iptables() {
819 run_command("IPTABLES", 10, "iptables", "-L", "-nvx", NULL);
820 run_command("IP6TABLES", 10, "ip6tables", "-L", "-nvx", NULL);
821 run_command("IPTABLE NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL);
823 run_command("IPTABLE MANGLE", 10, "iptables", "-t", "mangle", "-L", "-nvx", NULL);
824 run_command("IP6TABLE MANGLE", 10, "ip6tables", "-t", "mangle", "-L", "-nvx", NULL);
825 run_command("IPTABLE RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL);
826 run_command("IP6TABLE RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
829 static void dumpstate(const std::string& screenshot_path, const std::string& version) {
830 DurationReporter duration_reporter("DUMPSTATE");
831 unsigned long timeout;
833 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
834 run_command("UPTIME", 10, "uptime", NULL);
835 dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
836 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
837 dump_file("MEMORY INFO", "/proc/meminfo");
838 run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-H", NULL);
839 run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
840 dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
841 dump_file("VMALLOC INFO", "/proc/vmallocinfo");
842 dump_file("SLAB INFO", "/proc/slabinfo");
843 dump_file("ZONEINFO", "/proc/zoneinfo");
844 dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
845 dump_file("BUDDYINFO", "/proc/buddyinfo");
846 dump_file("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
848 dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
849 dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
850 dump_file("KERNEL SYNC", "/d/sync");
852 run_command("PROCESSES AND THREADS", 10, "ps", "-Z", "-t", "-p", "-P", NULL);
853 run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
855 run_command("PRINTENV", 10, "printenv", NULL);
856 run_command("NETSTAT", 10, "netstat", "-n", NULL);
857 run_command("LSMOD", 10, "lsmod", NULL);
861 run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
862 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
863 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
864 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
866 if (!screenshot_path.empty()) {
867 MYLOGI("taking late screenshot\n");
868 take_screenshot(screenshot_path);
869 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
872 // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
874 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
875 if (timeout < 20000) {
878 run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
882 timeout = logcat_timeout("events");
883 if (timeout < 20000) {
886 run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
891 timeout = logcat_timeout("radio");
892 if (timeout < 20000) {
895 run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
901 run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
903 /* show the traces we collected in main(), if that was done */
904 if (dump_traces_path != NULL) {
905 dump_file("VM TRACES JUST NOW", dump_traces_path);
908 /* only show ANR traces if they're less than 15 minutes old */
910 char anr_traces_path[PATH_MAX];
911 property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
912 if (!anr_traces_path[0]) {
913 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
915 int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
916 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
918 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
920 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
924 /* slow traces for slow operations */
925 if (anr_traces_path[0] != 0) {
926 int tail = strlen(anr_traces_path)-1;
927 while (tail > 0 && anr_traces_path[tail] != '/') {
932 sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
933 if (stat(anr_traces_path, &st)) {
934 // No traces file at this index, done with the files.
937 dump_file("VM TRACES WHEN SLOW", anr_traces_path);
943 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
944 if (tombstone_data[i].fd != -1) {
945 const char *name = tombstone_data[i].name;
946 int fd = tombstone_data[i].fd;
949 if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
950 MYLOGE("Unable to add tombstone %s to zip file\n", name);
953 dump_file_from_fd("TOMBSTONE", name, fd);
956 tombstone_data[i].fd = -1;
960 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
963 dump_file("NETWORK DEV INFO", "/proc/net/dev");
964 dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
965 dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
966 dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
967 dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
969 if (!stat(PSTORE_LAST_KMSG, &st)) {
970 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
971 dump_file("LAST KMSG", PSTORE_LAST_KMSG);
972 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
973 dump_file("LAST KMSG", ALT_PSTORE_LAST_KMSG);
975 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
976 dump_file("LAST KMSG", "/proc/last_kmsg");
979 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
980 run_command("LAST LOGCAT", 10, "logcat", "-L",
987 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
989 run_command("NETWORK INTERFACES", 10, "ip", "link", NULL);
991 run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL);
992 run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL);
994 run_command("IP RULES", 10, "ip", "rule", "show", NULL);
995 run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
999 run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
1000 run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
1001 run_command("MULTICAST ADDRESSES", 10, "ip", "maddr", NULL);
1002 run_command("WIFI NETWORKS", 20, "wpa_cli", "IFNAME=wlan0", "list_networks", NULL);
1004 #ifdef FWDUMP_bcmdhd
1005 run_command("ND OFFLOAD TABLE", 5,
1006 SU_PATH, "root", WLUTIL, "nd_hostip", NULL);
1008 run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
1009 SU_PATH, "root", WLUTIL, "counters", NULL);
1011 run_command("ND OFFLOAD STATUS (1)", 5,
1012 SU_PATH, "root", WLUTIL, "nd_status", NULL);
1015 dump_file("INTERRUPTS (1)", "/proc/interrupts");
1017 run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "-t", "10", "connectivity", "--diag", NULL);
1019 #ifdef FWDUMP_bcmdhd
1020 run_command("DUMP WIFI STATUS", 20,
1021 SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
1023 run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
1024 SU_PATH, "root", WLUTIL, "counters", NULL);
1026 run_command("ND OFFLOAD STATUS (2)", 5,
1027 SU_PATH, "root", WLUTIL, "nd_status", NULL);
1029 dump_file("INTERRUPTS (2)", "/proc/interrupts");
1033 run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
1034 run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
1036 run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);
1038 run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
1040 printf("------ BACKLIGHTS ------\n");
1041 printf("LCD brightness=");
1042 dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness");
1043 printf("Button brightness=");
1044 dump_file(NULL, "/sys/class/leds/button-backlight/brightness");
1045 printf("Keyboard brightness=");
1046 dump_file(NULL, "/sys/class/leds/keyboard-backlight/brightness");
1047 printf("ALS mode=");
1048 dump_file(NULL, "/sys/class/leds/lcd-backlight/als");
1049 printf("LCD driver registers:\n");
1050 dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
1053 /* Binder state is expensive to look at as it uses a lot of memory. */
1054 dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1055 dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1056 dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1057 dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
1058 dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
1060 printf("========================================================\n");
1061 printf("== Board\n");
1062 printf("========================================================\n");
1067 /* Migrate the ril_dumpstate to a dumpstate_board()? */
1068 char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
1069 property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
1070 if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
1071 if (is_user_build()) {
1072 // su does not exist on user builds, so try running without it.
1073 // This way any implementations of vril-dump that do not require
1074 // root can run on user builds.
1075 run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
1078 run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
1079 SU_PATH, "root", "vril-dump", NULL);
1083 printf("========================================================\n");
1084 printf("== Android Framework Services\n");
1085 printf("========================================================\n");
1087 run_command("DUMPSYS", 60, "dumpsys", "-t", "60", "--skip", "meminfo", "cpuinfo", NULL);
1089 printf("========================================================\n");
1090 printf("== Checkins\n");
1091 printf("========================================================\n");
1093 run_command("CHECKIN BATTERYSTATS", 30, "dumpsys", "-t", "30", "batterystats", "-c", NULL);
1094 run_command("CHECKIN MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "--checkin", NULL);
1095 run_command("CHECKIN NETSTATS", 30, "dumpsys", "-t", "30", "netstats", "--checkin", NULL);
1096 run_command("CHECKIN PROCSTATS", 30, "dumpsys", "-t", "30", "procstats", "-c", NULL);
1097 run_command("CHECKIN USAGESTATS", 30, "dumpsys", "-t", "30", "usagestats", "-c", NULL);
1098 run_command("CHECKIN PACKAGE", 30, "dumpsys", "-t", "30", "package", "--checkin", NULL);
1100 printf("========================================================\n");
1101 printf("== Running Application Activities\n");
1102 printf("========================================================\n");
1104 run_command("APP ACTIVITIES", 30, "dumpsys", "-t", "30", "activity", "all", NULL);
1106 printf("========================================================\n");
1107 printf("== Running Application Services\n");
1108 printf("========================================================\n");
1110 run_command("APP SERVICES", 30, "dumpsys", "-t", "30", "activity", "service", "all", NULL);
1112 printf("========================================================\n");
1113 printf("== Running Application Providers\n");
1114 printf("========================================================\n");
1116 run_command("APP PROVIDERS", 30, "dumpsys", "-t", "30", "activity", "provider", "all", NULL);
1119 printf("========================================================\n");
1120 printf("== Final progress (pid %d): %d/%d (originally %d)\n",
1121 getpid(), progress, weight_total, WEIGHT_TOTAL);
1122 printf("========================================================\n");
1123 printf("== dumpstate: done\n");
1124 printf("========================================================\n");
1127 static void usage() {
1129 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
1130 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1131 " -h: display this help message\n"
1132 " -b: play sound file instead of vibrate, at beginning of job\n"
1133 " -e: play sound file instead of vibrate, at end of job\n"
1134 " -o: write to file (instead of stdout)\n"
1135 " -d: append date to filename (requires -o)\n"
1136 " -p: capture screenshot to filename.png (requires -o)\n"
1137 " -z: generate zipped file (requires -o)\n"
1138 " -s: write output to control socket (for init)\n"
1139 " -S: write file location to control socket (for init; requires -o and -z)"
1140 " -q: disable vibrate\n"
1141 " -B: send broadcast when finished (requires -o)\n"
1142 " -P: send broadcast when started and update system properties on "
1143 "progress (requires -o and -B)\n"
1144 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1145 "shouldn't be used with -P)\n"
1146 " -V: sets the bugreport format version (valid values: %s)\n",
1147 VERSION_DEFAULT.c_str());
1150 static void sigpipe_handler(int n) {
1151 // don't complain to stderr or stdout
1152 _exit(EXIT_FAILURE);
1155 /* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1158 static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
1160 if (!add_zip_entry(bugreport_name, bugreport_path)) {
1161 MYLOGE("Failed to add text entry to .zip file\n");
1164 if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
1165 MYLOGE("Failed to add main_entry.txt to .zip file\n");
1169 int32_t err = zip_writer->Finish();
1171 MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
1175 if (is_user_build()) {
1176 MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
1177 if (remove(bugreport_path.c_str())) {
1178 ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
1181 MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1187 static std::string SHA256_file_hash(std::string filepath) {
1188 ScopedFd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC
1190 if (fd.get() == -1) {
1191 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
1198 std::vector<uint8_t> buffer(65536);
1200 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1201 if (bytes_read == 0) {
1203 } else if (bytes_read == -1) {
1204 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
1208 SHA256_update(&ctx, buffer.data(), bytes_read);
1211 uint8_t hash[SHA256_DIGEST_SIZE];
1212 memcpy(hash, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
1213 char hash_buffer[SHA256_DIGEST_SIZE * 2 + 1];
1214 for(size_t i = 0; i < SHA256_DIGEST_SIZE; i++) {
1215 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
1217 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1218 return std::string(hash_buffer);
1221 int main(int argc, char *argv[]) {
1222 struct sigaction sigact;
1223 int do_add_date = 0;
1224 int do_zip_file = 0;
1226 char* use_outfile = 0;
1228 int use_control_socket = 0;
1230 int do_broadcast = 0;
1231 int do_early_screenshot = 0;
1232 int is_remote_mode = 0;
1233 std::string version = VERSION_DEFAULT;
1239 /* gets the sequential id */
1240 char last_id[PROPERTY_VALUE_MAX];
1241 property_get("dumpstate.last_id", last_id, "0");
1242 id = strtoul(last_id, NULL, 10) + 1;
1243 snprintf(last_id, sizeof(last_id), "%lu", id);
1244 property_set("dumpstate.last_id", last_id);
1245 MYLOGI("dumpstate id: %lu\n", id);
1247 /* clear SIGPIPE handler */
1248 memset(&sigact, 0, sizeof(sigact));
1249 sigact.sa_handler = sigpipe_handler;
1250 sigaction(SIGPIPE, &sigact, NULL);
1252 /* set as high priority, and protect from OOM killer */
1253 setpriority(PRIO_PROCESS, 0, -20);
1255 FILE *oom_adj = fopen("/proc/self/oom_score_adj", "we");
1257 fputs("-1000", oom_adj);
1260 /* fallback to kernels <= 2.6.35 */
1261 oom_adj = fopen("/proc/self/oom_adj", "we");
1263 fputs("-17", oom_adj);
1268 /* parse arguments */
1270 format_args(argc, const_cast<const char **>(argv), &args);
1271 MYLOGD("Dumpstate command line: %s\n", args.c_str());
1273 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
1275 case 'd': do_add_date = 1; break;
1276 case 'z': do_zip_file = 1; break;
1277 case 'o': use_outfile = optarg; break;
1278 case 's': use_socket = 1; break;
1279 case 'S': use_control_socket = 1; break;
1280 case 'v': break; // compatibility no-op
1281 case 'q': do_vibrate = 0; break;
1282 case 'p': do_fb = 1; break;
1283 case 'P': do_update_progress = 1; break;
1284 case 'R': is_remote_mode = 1; break;
1285 case 'B': do_broadcast = 1; break;
1286 case 'V': version = optarg; break;
1287 case '?': printf("\n");
1294 if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) {
1299 if (use_control_socket && !do_zip_file) {
1304 if (do_update_progress && !do_broadcast) {
1309 if (is_remote_mode && (do_update_progress || !do_broadcast || !do_zip_file || !do_add_date)) {
1314 if (version != VERSION_DEFAULT) {
1319 MYLOGI("bugreport format version: %s\n", version.c_str());
1321 do_early_screenshot = do_update_progress;
1323 // If we are going to use a socket, do it as early as possible
1324 // to avoid timeouts from bugreport.
1326 redirect_to_socket(stdout, "dumpstate");
1329 if (use_control_socket) {
1330 MYLOGD("Opening control socket\n");
1331 control_socket_fd = open_socket("dumpstate");
1332 do_update_progress = 1;
1335 /* full path of the temporary file containing the bugreport */
1336 std::string tmp_path;
1338 /* full path of the file containing the dumpstate logs*/
1339 std::string log_path;
1341 /* full path of the systrace file, when enabled */
1342 std::string systrace_path;
1344 /* full path of the temporary file containing the screenshot (when requested) */
1345 std::string screenshot_path;
1347 /* base name (without suffix or extensions) of the bugreport files */
1348 std::string base_name;
1350 /* pointer to the actual path, be it zip or text */
1353 /* pointer to the zipped file */
1354 std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
1356 /* redirect output if needed */
1357 bool is_redirecting = !use_socket && use_outfile;
1359 if (is_redirecting) {
1360 bugreport_dir = dirname(use_outfile);
1361 base_name = basename(use_outfile);
1364 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1369 char build_id[PROPERTY_VALUE_MAX];
1370 property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
1371 base_name = base_name + "-" + build_id;
1373 // TODO: if dumpstate was an object, the paths could be internal variables and then
1374 // we could have a function to calculate the derived values, such as:
1375 // screenshot_path = GetPath(".png");
1376 screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1378 tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
1379 log_path = bugreport_dir + "/dumpstate_log-" + suffix + "-"
1380 + std::to_string(getpid()) + ".txt";
1382 MYLOGD("Bugreport dir: %s\n"
1386 "Temporary path: %s\n"
1387 "Screenshot path: %s\n",
1388 bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(),
1389 log_path.c_str(), tmp_path.c_str(), screenshot_path.c_str());
1392 path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1393 MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
1394 create_parent_dirs(path.c_str());
1395 zip_file.reset(fopen(path.c_str(), "wb"));
1397 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
1400 zip_writer.reset(new ZipWriter(zip_file.get()));
1402 add_text_zip_entry("version.txt", version);
1405 if (do_update_progress) {
1408 std::vector<std::string> am_args = {
1409 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1410 "--es", "android.intent.extra.NAME", suffix,
1411 "--ei", "android.intent.extra.ID", std::to_string(id),
1412 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1413 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1416 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1418 if (use_control_socket) {
1419 dprintf(control_socket_fd, "BEGIN:%s\n", path.c_str());
1424 /* read /proc/cmdline before dropping root */
1425 FILE *cmdline = fopen("/proc/cmdline", "re");
1427 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1431 /* open the vibrator before dropping root */
1432 std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
1434 vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
1436 vibrate(vibrator.get(), 150);
1440 if (do_fb && do_early_screenshot) {
1441 if (screenshot_path.empty()) {
1442 // should not have happened
1443 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
1445 MYLOGI("taking early screenshot\n");
1446 take_screenshot(screenshot_path);
1447 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
1448 if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
1449 MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
1450 screenshot_path.c_str(), strerror(errno));
1456 if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
1457 MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
1461 if (is_redirecting) {
1462 redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
1463 if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
1464 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1465 log_path.c_str(), strerror(errno));
1467 /* TODO: rather than generating a text file now and zipping it later,
1468 it would be more efficient to redirect stdout to the zip entry
1469 directly, but the libziparchive doesn't support that option yet. */
1470 redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
1471 if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
1472 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
1473 tmp_path.c_str(), strerror(errno));
1476 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1477 // In particular, DurationReport objects should be created passing 'title, NULL', so their
1478 // duration is logged into MYLOG instead.
1479 print_header(version);
1481 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1482 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1484 if (!dump_anrd_trace()) {
1488 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1491 // Invoking the following dumpsys calls before dump_traces() to try and
1492 // keep the system stats as close to its initial state as possible.
1493 run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "-a", NULL);
1494 run_command_as_shell("DUMPSYS CPUINFO", 10, "dumpsys", "-t", "10", "cpuinfo", "-a", NULL);
1496 /* collect stack traces from Dalvik and native processes (needs root) */
1497 dump_traces_path = dump_traces();
1499 /* Run some operations that require root. */
1500 get_tombstone_fds(tombstone_data);
1501 add_dir(RECOVERY_DIR, true);
1502 add_dir(RECOVERY_DATA_DIR, true);
1503 add_dir(LOGPERSIST_DATA_DIR, false);
1504 if (!is_user_build()) {
1505 add_dir(PROFILE_DATA_DIR_CUR, true);
1506 add_dir(PROFILE_DATA_DIR_REF, true);
1511 if (!drop_root_user()) {
1515 dumpstate(do_early_screenshot ? "": screenshot_path, version);
1517 /* close output if needed */
1518 if (is_redirecting) {
1522 /* rename or zip the (now complete) .tmp file to its final location */
1525 /* check if user changed the suffix using system properties */
1526 char key[PROPERTY_KEY_MAX];
1527 char value[PROPERTY_VALUE_MAX];
1528 snprintf(key, sizeof(key), "dumpstate.%d.name", getpid());
1529 property_get(key, value, "");
1530 bool change_suffix= false;
1532 /* must whitelist which characters are allowed, otherwise it could cross directories */
1533 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
1534 if (std::regex_match(value, valid_regex)) {
1535 change_suffix = true;
1537 MYLOGE("invalid suffix provided by user: %s\n", value);
1540 if (change_suffix) {
1541 MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), value);
1543 if (!screenshot_path.empty()) {
1544 std::string new_screenshot_path =
1545 bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1546 if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
1547 MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
1548 new_screenshot_path.c_str(), strerror(errno));
1550 screenshot_path = new_screenshot_path;
1555 bool do_text_file = true;
1557 std::string entry_name = base_name + "-" + suffix + ".txt";
1558 MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
1559 if (!finish_zip_file(entry_name, tmp_path, now)) {
1560 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
1561 do_text_file = true;
1563 do_text_file = false;
1564 // Since zip file is already created, it needs to be renamed.
1565 std::string new_path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1566 if (path != new_path) {
1567 MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
1568 if (rename(path.c_str(), new_path.c_str())) {
1569 MYLOGE("rename(%s, %s): %s\n", path.c_str(),
1570 new_path.c_str(), strerror(errno));
1578 path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt";
1579 MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
1580 if (rename(tmp_path.c_str(), path.c_str())) {
1581 MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
1585 if (use_control_socket) {
1587 dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
1588 "for more details\n", log_path.c_str());
1590 dprintf(control_socket_fd, "OK:%s\n", path.c_str());
1595 /* vibrate a few but shortly times to let user know it's finished */
1597 for (int i = 0; i < 3; i++) {
1598 vibrate(vibrator.get(), 75);
1599 usleep((75 + 50) * 1000);
1603 /* tell activity manager we're done */
1605 if (!path.empty()) {
1606 MYLOGI("Final bugreport path: %s\n", path.c_str());
1608 std::vector<std::string> am_args = {
1609 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1610 "--ei", "android.intent.extra.ID", std::to_string(id),
1611 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1612 "--ei", "android.intent.extra.MAX", std::to_string(weight_total),
1613 "--es", "android.intent.extra.BUGREPORT", path,
1614 "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
1618 am_args.push_back("--es");
1619 am_args.push_back("android.intent.extra.SCREENSHOT");
1620 am_args.push_back(screenshot_path);
1622 if (is_remote_mode) {
1623 am_args.push_back("--es");
1624 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1625 am_args.push_back(SHA256_file_hash(path));
1626 send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1628 send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
1631 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
1635 MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
1638 if (is_redirecting) {
1642 if (use_control_socket && control_socket_fd != -1) {
1643 MYLOGD("Closing control socket\n");
1644 close(control_socket_fd);