OSDN Git Service

ee481fbabd7dc6e34c36afde960601831bd709c3
[android-x86/frameworks-native.git] / cmds / dumpstate / dumpstate.cpp
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <dirent.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <libgen.h>
21 #include <limits.h>
22 #include <memory>
23 #include <regex>
24 #include <set>
25 #include <stdbool.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string>
29 #include <string.h>
30 #include <sys/prctl.h>
31 #include <sys/resource.h>
32 #include <sys/stat.h>
33 #include <sys/time.h>
34 #include <sys/wait.h>
35 #include <unistd.h>
36
37 #include <android-base/file.h>
38 #include <android-base/stringprintf.h>
39 #include <android-base/strings.h>
40 #include <cutils/properties.h>
41
42 #include "private/android_filesystem_config.h"
43
44 #define LOG_TAG "dumpstate"
45 #include <cutils/log.h>
46
47 #include "dumpstate.h"
48 #include "ScopedFd.h"
49 #include "ziparchive/zip_writer.h"
50
51 #include "mincrypt/sha256.h"
52
53 using android::base::StringPrintf;
54
55 /* read before root is shed */
56 static char cmdline_buf[16384] = "(unknown)";
57 static const char *dump_traces_path = NULL;
58
59 // TODO: variables below should be part of dumpstate object
60 static unsigned long id;
61 static char build_type[PROPERTY_VALUE_MAX];
62 static time_t now;
63 static std::unique_ptr<ZipWriter> zip_writer;
64 static std::set<std::string> mount_points;
65 void add_mountinfo();
66 int control_socket_fd = -1;
67 /* suffix of the bugreport files - it's typically the date (when invoked with -d),
68  * although it could be changed by the user using a system property */
69 static std::string suffix;
70
71 #define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
72 #define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
73
74 #define RAFT_DIR "/data/misc/raft"
75 #define RECOVERY_DIR "/cache/recovery"
76 #define RECOVERY_DATA_DIR "/data/misc/recovery"
77 #define LOGPERSIST_DATA_DIR "/data/misc/logd"
78 #define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
79 #define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
80 #define TOMBSTONE_DIR "/data/tombstones"
81 #define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
82 /* Can accomodate a tombstone number up to 9999. */
83 #define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
84 #define NUM_TOMBSTONES  10
85 #define WLUTIL "/vendor/xbin/wlutil"
86
87 typedef struct {
88   char name[TOMBSTONE_MAX_LEN];
89   int fd;
90 } tombstone_data_t;
91
92 static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
93
94 const std::string ZIP_ROOT_DIR = "FS";
95 std::string bugreport_dir;
96
97 /*
98  * List of supported zip format versions.
99  *
100  * See bugreport-format.txt for more info.
101  */
102 static std::string VERSION_DEFAULT = "1.0";
103
104 bool is_user_build() {
105     return 0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1);
106 }
107
108 /* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones,
109  * otherwise gets just those modified in the last half an hour. */
110 static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
111     time_t thirty_minutes_ago = now - 60*30;
112     for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
113         snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
114         int fd = TEMP_FAILURE_RETRY(open(data[i].name,
115                                          O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
116         struct stat st;
117         if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
118             (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) {
119         data[i].fd = fd;
120         } else {
121         close(fd);
122             data[i].fd = -1;
123         }
124     }
125 }
126
127 // for_each_pid() callback to get mount info about a process.
128 void do_mountinfo(int pid, const char *name) {
129     char path[PATH_MAX];
130
131     // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
132     // are added.
133     snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
134     char linkname[PATH_MAX];
135     ssize_t r = readlink(path, linkname, PATH_MAX);
136     if (r == -1) {
137         MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
138         return;
139     }
140     linkname[r] = '\0';
141
142     if (mount_points.find(linkname) == mount_points.end()) {
143         // First time this mount point was found: add it
144         snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
145         if (add_zip_entry(ZIP_ROOT_DIR + path, path)) {
146             mount_points.insert(linkname);
147         } else {
148             MYLOGE("Unable to add mountinfo %s to zip file\n", path);
149         }
150     }
151 }
152
153 void add_mountinfo() {
154     if (!is_zipping()) return;
155     const char *title = "MOUNT INFO";
156     mount_points.clear();
157     DurationReporter duration_reporter(title, NULL);
158     for_each_pid(do_mountinfo, NULL);
159     MYLOGD("%s: %d entries added to zip file\n", title, (int) mount_points.size());
160 }
161
162 static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
163 {
164     DIR *d;
165     struct dirent *de;
166     char path[PATH_MAX];
167
168     d = opendir(driverpath);
169     if (d == NULL) {
170         return;
171     }
172
173     while ((de = readdir(d))) {
174         if (de->d_type != DT_LNK) {
175             continue;
176         }
177         snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
178         dump_file(title, path);
179     }
180
181     closedir(d);
182 }
183
184 // return pid of a userspace process. If not found or error, return 0.
185 static unsigned int pid_of_process(const char* ps_name) {
186     DIR *proc_dir;
187     struct dirent *ps;
188     unsigned int pid;
189     std::string cmdline;
190
191     if (!(proc_dir = opendir("/proc"))) {
192         MYLOGE("Can't open /proc\n");
193         return 0;
194     }
195
196     while ((ps = readdir(proc_dir))) {
197         if (!(pid = atoi(ps->d_name))) {
198             continue;
199         }
200         android::base::ReadFileToString("/proc/"
201                 + std::string(ps->d_name) + "/cmdline", &cmdline);
202         if (cmdline.find(ps_name) == std::string::npos) {
203             continue;
204         } else {
205             closedir(proc_dir);
206             return pid;
207         }
208     }
209     closedir(proc_dir);
210     return 0;
211 }
212
213 // dump anrd's trace and add to the zip file.
214 // 1. check if anrd is running on this device.
215 // 2. send a SIGUSR1 to its pid which will dump anrd's trace.
216 // 3. wait until the trace generation completes and add to the zip file.
217 static bool dump_anrd_trace() {
218     unsigned int pid;
219     char buf[50], path[PATH_MAX];
220     struct dirent *trace;
221     struct stat st;
222     DIR *trace_dir;
223     int retry = 5;
224     long max_ctime = 0, old_mtime;
225     long long cur_size = 0;
226     const char *trace_path = "/data/misc/anrd/";
227
228     if (!zip_writer) {
229         MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
230         return false;
231     }
232
233     // find anrd's pid if it is running.
234     pid = pid_of_process("/system/xbin/anrd");
235
236     if (pid > 0) {
237         if (stat(trace_path, &st) == 0) {
238             old_mtime = st.st_mtime;
239         } else {
240             MYLOGE("Failed to find: %s\n", trace_path);
241             return false;
242         }
243
244         // send SIGUSR1 to the anrd to generate a trace.
245         sprintf(buf, "%u", pid);
246         if (run_command("ANRD_DUMP", 1, "kill", "-SIGUSR1", buf, NULL)) {
247             MYLOGE("anrd signal timed out. Please manually collect trace\n");
248             return false;
249         }
250
251         while (retry-- > 0 && old_mtime == st.st_mtime) {
252             sleep(1);
253             stat(trace_path, &st);
254         }
255
256         if (retry < 0 && old_mtime == st.st_mtime) {
257             MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
258             return false;
259         }
260
261         // identify the trace file by its creation time.
262         if (!(trace_dir = opendir(trace_path))) {
263             MYLOGE("Can't open trace file under %s\n", trace_path);
264         }
265         while ((trace = readdir(trace_dir))) {
266             if (strcmp(trace->d_name, ".") == 0
267                     || strcmp(trace->d_name, "..") == 0) {
268                 continue;
269             }
270             sprintf(path, "%s%s", trace_path, trace->d_name);
271             if (stat(path, &st) == 0) {
272                 if (st.st_ctime > max_ctime) {
273                     max_ctime = st.st_ctime;
274                     sprintf(buf, "%s", trace->d_name);
275                 }
276             }
277         }
278         closedir(trace_dir);
279
280         // Wait until the dump completes by checking the size of the trace.
281         if (max_ctime > 0) {
282             sprintf(path, "%s%s", trace_path, buf);
283             while(true) {
284                 sleep(1);
285                 if (stat(path, &st) == 0) {
286                     if (st.st_size == cur_size) {
287                         break;
288                     } else if (st.st_size > cur_size) {
289                         cur_size = st.st_size;
290                     } else {
291                         return false;
292                     }
293                 } else {
294                     MYLOGE("Cant stat() %s anymore\n", path);
295                     return false;
296                 }
297             }
298             // Add to the zip file.
299             if (!add_zip_entry("anrd_trace.txt", path)) {
300                 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
301             } else {
302                 if (remove(path)) {
303                     MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
304                 }
305                 return true;
306             }
307         } else {
308             MYLOGE("Can't stats any trace file under %s\n", trace_path);
309         }
310     }
311     return false;
312 }
313
314 static void dump_systrace() {
315     if (!is_zipping()) {
316         MYLOGD("Not dumping systrace because dumpstate is not zipping\n");
317         return;
318     }
319     std::string systrace_path = bugreport_dir + "/systrace-" + suffix + ".txt";
320     if (systrace_path.empty()) {
321         MYLOGE("Not dumping systrace because path is empty\n");
322         return;
323     }
324     const char* path = "/sys/kernel/debug/tracing/tracing_on";
325     long int is_tracing;
326     if (read_file_as_long(path, &is_tracing)) {
327         return; // error already logged
328     }
329     if (is_tracing <= 0) {
330         MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
331         return;
332     }
333
334     MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
335             systrace_path.c_str());
336     if (run_command("SYSTRACE", 120, "/system/bin/atrace", "--async_dump", "-o",
337             systrace_path.c_str(), NULL)) {
338         MYLOGE("systrace timed out, its zip entry will be incomplete\n");
339         // TODO: run_command tries to kill the process, but atrace doesn't die peacefully; ideally,
340         // we should call strace to stop itself, but there is no such option yet (just a
341         // --async_stop, which stops and dump
342         //        if (run_command("SYSTRACE", 10, "/system/bin/atrace", "--kill", NULL)) {
343         //            MYLOGE("could not stop systrace ");
344         //        }
345     }
346     if (!add_zip_entry("systrace.txt", systrace_path)) {
347         MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
348     } else {
349         if (remove(systrace_path.c_str())) {
350             MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
351         }
352     }
353 }
354
355 static void dump_raft() {
356     if (is_user_build()) {
357         return;
358     }
359
360     std::string raft_log_path = bugreport_dir + "/raft_log.txt";
361     if (raft_log_path.empty()) {
362         MYLOGD("raft_log_path is empty\n");
363         return;
364     }
365
366     struct stat s;
367     if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
368         MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
369         return;
370     }
371
372     if (!is_zipping()) {
373         // Write compressed and encoded raft logs to stdout if not zip_writer.
374         run_command("RAFT LOGS", 600, "logcompressor", "-r", RAFT_DIR, NULL);
375         return;
376     }
377
378     run_command("RAFT LOGS", 600, "logcompressor", "-n", "-r", RAFT_DIR,
379             "-o", raft_log_path.c_str(), NULL);
380     if (!add_zip_entry("raft_log.txt", raft_log_path)) {
381         MYLOGE("Unable to add raft log %s to zip file\n", raft_log_path.c_str());
382     } else {
383         if (remove(raft_log_path.c_str())) {
384             MYLOGE("Error removing raft file %s: %s\n", raft_log_path.c_str(), strerror(errno));
385         }
386     }
387 }
388
389 /**
390  * Finds the last modified file in the directory dir whose name starts with file_prefix
391  * Function returns empty string when it does not find a file
392  */
393 static std::string get_last_modified_file_matching_prefix(const std::string& dir,
394                                                           const std::string& file_prefix) {
395     std::unique_ptr<DIR, decltype(&closedir)> d(opendir(dir.c_str()), closedir);
396     if (d == nullptr) {
397         MYLOGD("Error %d opening %s\n", errno, dir.c_str());
398         return "";
399     }
400
401     // Find the newest file matching the file_prefix in dir
402     struct dirent *de;
403     time_t last_modified = 0;
404     std::string last_modified_file = "";
405     struct stat s;
406
407     while ((de = readdir(d.get()))) {
408         std::string file = std::string(de->d_name);
409         if (!file_prefix.empty()) {
410             if (!android::base::StartsWith(file, file_prefix.c_str())) continue;
411         }
412         file = dir + "/" + file;
413         int ret = stat(file.c_str(), &s);
414
415         if ((ret == 0) && (s.st_mtime > last_modified)) {
416             last_modified_file = file;
417             last_modified = s.st_mtime;
418         }
419     }
420
421     return last_modified_file;
422 }
423
424 void dump_modem_logs() {
425     DurationReporter duration_reporter("dump_modem_logs");
426     if (is_user_build()) {
427         return;
428     }
429
430     if (!is_zipping()) {
431         MYLOGD("Not dumping modem logs. dumpstate is not generating a zipping bugreport\n");
432         return;
433     }
434
435     char property[PROPERTY_VALUE_MAX];
436     property_get("ro.radio.log_prefix", property, "");
437     std::string file_prefix = std::string(property);
438     if(file_prefix.empty()) {
439         MYLOGD("No modem log : file_prefix is empty\n");
440         return;
441     }
442
443     MYLOGD("dump_modem_logs: directory is %s and file_prefix is %s\n",
444            bugreport_dir.c_str(), file_prefix.c_str());
445
446     std::string modem_log_file =
447         get_last_modified_file_matching_prefix(bugreport_dir, file_prefix);
448
449     struct stat s;
450     if (modem_log_file.empty() || stat(modem_log_file.c_str(), &s) != 0) {
451         MYLOGD("Modem log %s does not exist\n", modem_log_file.c_str());
452         return;
453     }
454
455     std::string filename = basename(modem_log_file.c_str());
456     if (!add_zip_entry(filename, modem_log_file)) {
457         MYLOGE("Unable to add modem log %s to zip file\n", modem_log_file.c_str());
458     } else {
459         MYLOGD("Modem Log %s is added to zip\n", modem_log_file.c_str());
460         if (remove(modem_log_file.c_str())) {
461             MYLOGE("Error removing modem log %s\n", modem_log_file.c_str());
462         }
463     }
464 }
465
466 static bool skip_not_stat(const char *path) {
467     static const char stat[] = "/stat";
468     size_t len = strlen(path);
469     if (path[len - 1] == '/') { /* Directory? */
470         return false;
471     }
472     return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
473 }
474
475 static bool skip_none(const char *path) {
476     return false;
477 }
478
479 static const char mmcblk0[] = "/sys/block/mmcblk0/";
480 unsigned long worst_write_perf = 20000; /* in KB/s */
481
482 //
483 //  stat offsets
484 // Name            units         description
485 // ----            -----         -----------
486 // read I/Os       requests      number of read I/Os processed
487 #define __STAT_READ_IOS      0
488 // read merges     requests      number of read I/Os merged with in-queue I/O
489 #define __STAT_READ_MERGES   1
490 // read sectors    sectors       number of sectors read
491 #define __STAT_READ_SECTORS  2
492 // read ticks      milliseconds  total wait time for read requests
493 #define __STAT_READ_TICKS    3
494 // write I/Os      requests      number of write I/Os processed
495 #define __STAT_WRITE_IOS     4
496 // write merges    requests      number of write I/Os merged with in-queue I/O
497 #define __STAT_WRITE_MERGES  5
498 // write sectors   sectors       number of sectors written
499 #define __STAT_WRITE_SECTORS 6
500 // write ticks     milliseconds  total wait time for write requests
501 #define __STAT_WRITE_TICKS   7
502 // in_flight       requests      number of I/Os currently in flight
503 #define __STAT_IN_FLIGHT     8
504 // io_ticks        milliseconds  total time this block device has been active
505 #define __STAT_IO_TICKS      9
506 // time_in_queue   milliseconds  total wait time for all requests
507 #define __STAT_IN_QUEUE     10
508 #define __STAT_NUMBER_FIELD 11
509 //
510 // read I/Os, write I/Os
511 // =====================
512 //
513 // These values increment when an I/O request completes.
514 //
515 // read merges, write merges
516 // =========================
517 //
518 // These values increment when an I/O request is merged with an
519 // already-queued I/O request.
520 //
521 // read sectors, write sectors
522 // ===========================
523 //
524 // These values count the number of sectors read from or written to this
525 // block device.  The "sectors" in question are the standard UNIX 512-byte
526 // sectors, not any device- or filesystem-specific block size.  The
527 // counters are incremented when the I/O completes.
528 #define SECTOR_SIZE 512
529 //
530 // read ticks, write ticks
531 // =======================
532 //
533 // These values count the number of milliseconds that I/O requests have
534 // waited on this block device.  If there are multiple I/O requests waiting,
535 // these values will increase at a rate greater than 1000/second; for
536 // example, if 60 read requests wait for an average of 30 ms, the read_ticks
537 // field will increase by 60*30 = 1800.
538 //
539 // in_flight
540 // =========
541 //
542 // This value counts the number of I/O requests that have been issued to
543 // the device driver but have not yet completed.  It does not include I/O
544 // requests that are in the queue but not yet issued to the device driver.
545 //
546 // io_ticks
547 // ========
548 //
549 // This value counts the number of milliseconds during which the device has
550 // had I/O requests queued.
551 //
552 // time_in_queue
553 // =============
554 //
555 // This value counts the number of milliseconds that I/O requests have waited
556 // on this block device.  If there are multiple I/O requests waiting, this
557 // value will increase as the product of the number of milliseconds times the
558 // number of requests waiting (see "read ticks" above for an example).
559 #define S_TO_MS 1000
560 //
561
562 static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
563     unsigned long long fields[__STAT_NUMBER_FIELD];
564     bool z;
565     char *cp, *buffer = NULL;
566     size_t i = 0;
567     FILE *fp = fdopen(fd, "rb");
568     getline(&buffer, &i, fp);
569     fclose(fp);
570     if (!buffer) {
571         return -errno;
572     }
573     i = strlen(buffer);
574     while ((i > 0) && (buffer[i - 1] == '\n')) {
575         buffer[--i] = '\0';
576     }
577     if (!*buffer) {
578         free(buffer);
579         return 0;
580     }
581     z = true;
582     for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
583         fields[i] = strtoull(cp, &cp, 10);
584         if (fields[i] != 0) {
585             z = false;
586         }
587     }
588     if (z) { /* never accessed */
589         free(buffer);
590         return 0;
591     }
592
593     if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
594         path += sizeof(mmcblk0) - 1;
595     }
596
597     printf("%s: %s\n", path, buffer);
598     free(buffer);
599
600     if (fields[__STAT_IO_TICKS]) {
601         unsigned long read_perf = 0;
602         unsigned long read_ios = 0;
603         if (fields[__STAT_READ_TICKS]) {
604             unsigned long long divisor = fields[__STAT_READ_TICKS]
605                                        * fields[__STAT_IO_TICKS];
606             read_perf = ((unsigned long long)SECTOR_SIZE
607                            * fields[__STAT_READ_SECTORS]
608                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
609                                         / divisor;
610             read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
611                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
612                                         / divisor;
613         }
614
615         unsigned long write_perf = 0;
616         unsigned long write_ios = 0;
617         if (fields[__STAT_WRITE_TICKS]) {
618             unsigned long long divisor = fields[__STAT_WRITE_TICKS]
619                                        * fields[__STAT_IO_TICKS];
620             write_perf = ((unsigned long long)SECTOR_SIZE
621                            * fields[__STAT_WRITE_SECTORS]
622                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
623                                         / divisor;
624             write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
625                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
626                                         / divisor;
627         }
628
629         unsigned queue = (fields[__STAT_IN_QUEUE]
630                              + (fields[__STAT_IO_TICKS] >> 1))
631                                  / fields[__STAT_IO_TICKS];
632
633         if (!write_perf && !write_ios) {
634             printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
635                    path, read_perf, read_ios, queue);
636         } else {
637             printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
638                    path, read_perf, read_ios, write_perf, write_ios, queue);
639         }
640
641         /* bugreport timeout factor adjustment */
642         if ((write_perf > 1) && (write_perf < worst_write_perf)) {
643             worst_write_perf = write_perf;
644         }
645     }
646     return 0;
647 }
648
649 /* Copied policy from system/core/logd/LogBuffer.cpp */
650
651 #define LOG_BUFFER_SIZE (256 * 1024)
652 #define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
653 #define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
654
655 static bool valid_size(unsigned long value) {
656     if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
657         return false;
658     }
659
660     long pages = sysconf(_SC_PHYS_PAGES);
661     if (pages < 1) {
662         return true;
663     }
664
665     long pagesize = sysconf(_SC_PAGESIZE);
666     if (pagesize <= 1) {
667         pagesize = PAGE_SIZE;
668     }
669
670     // maximum memory impact a somewhat arbitrary ~3%
671     pages = (pages + 31) / 32;
672     unsigned long maximum = pages * pagesize;
673
674     if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
675         return true;
676     }
677
678     return value <= maximum;
679 }
680
681 static unsigned long property_get_size(const char *key) {
682     unsigned long value;
683     char *cp, property[PROPERTY_VALUE_MAX];
684
685     property_get(key, property, "");
686     value = strtoul(property, &cp, 10);
687
688     switch(*cp) {
689     case 'm':
690     case 'M':
691         value *= 1024;
692     /* FALLTHRU */
693     case 'k':
694     case 'K':
695         value *= 1024;
696     /* FALLTHRU */
697     case '\0':
698         break;
699
700     default:
701         value = 0;
702     }
703
704     if (!valid_size(value)) {
705         value = 0;
706     }
707
708     return value;
709 }
710
711 /* timeout in ms */
712 static unsigned long logcat_timeout(const char *name) {
713     static const char global_tuneable[] = "persist.logd.size"; // Settings App
714     static const char global_default[] = "ro.logd.size";       // BoardConfig.mk
715     char key[PROP_NAME_MAX];
716     unsigned long property_size, default_size;
717
718     default_size = property_get_size(global_tuneable);
719     if (!default_size) {
720         default_size = property_get_size(global_default);
721     }
722
723     snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
724     property_size = property_get_size(key);
725
726     if (!property_size) {
727         snprintf(key, sizeof(key), "%s.%s", global_default, name);
728         property_size = property_get_size(key);
729     }
730
731     if (!property_size) {
732         property_size = default_size;
733     }
734
735     if (!property_size) {
736         property_size = LOG_BUFFER_SIZE;
737     }
738
739     /* Engineering margin is ten-fold our guess */
740     return 10 * (property_size + worst_write_perf) / worst_write_perf;
741 }
742
743 /* End copy from system/core/logd/LogBuffer.cpp */
744
745 /* dumps the current system state to stdout */
746 static void print_header(std::string version) {
747     char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
748     char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
749     char network[PROPERTY_VALUE_MAX], date[80];
750
751     property_get("ro.build.display.id", build, "(unknown)");
752     property_get("ro.build.fingerprint", fingerprint, "(unknown)");
753     property_get("ro.build.type", build_type, "(unknown)");
754     property_get("gsm.version.baseband", radio, "(unknown)");
755     property_get("ro.bootloader", bootloader, "(unknown)");
756     property_get("gsm.operator.alpha", network, "(unknown)");
757     strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
758
759     printf("========================================================\n");
760     printf("== dumpstate: %s\n", date);
761     printf("========================================================\n");
762
763     printf("\n");
764     printf("Build: %s\n", build);
765     printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */
766     printf("Bootloader: %s\n", bootloader);
767     printf("Radio: %s\n", radio);
768     printf("Network: %s\n", network);
769
770     printf("Kernel: ");
771     dump_file(NULL, "/proc/version");
772     printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
773     printf("Bugreport format version: %s\n", version.c_str());
774     printf("Dumpstate info: id=%lu pid=%d\n", id, getpid());
775     printf("\n");
776 }
777
778 // List of file extensions that can cause a zip file attachment to be rejected by some email
779 // service providers.
780 static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
781       ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
782       ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
783       ".shb", ".sys", ".vb",  ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
784 };
785
786 bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
787     if (!is_zipping()) {
788         MYLOGD("Not adding entry %s from fd because dumpstate is not zipping\n",
789                 entry_name.c_str());
790         return false;
791     }
792     std::string valid_name = entry_name;
793
794     // Rename extension if necessary.
795     size_t idx = entry_name.rfind(".");
796     if (idx != std::string::npos) {
797         std::string extension = entry_name.substr(idx);
798         std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
799         if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
800             valid_name = entry_name + ".renamed";
801             MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
802         }
803     }
804
805     // Logging statement  below is useful to time how long each entry takes, but it's too verbose.
806     // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
807     int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(),
808             ZipWriter::kCompress, get_mtime(fd, now));
809     if (err) {
810         MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
811                 ZipWriter::ErrorCodeString(err));
812         return false;
813     }
814
815     std::vector<uint8_t> buffer(65536);
816     while (1) {
817         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), sizeof(buffer)));
818         if (bytes_read == 0) {
819             break;
820         } else if (bytes_read == -1) {
821             MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
822             return false;
823         }
824         err = zip_writer->WriteBytes(buffer.data(), bytes_read);
825         if (err) {
826             MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
827             return false;
828         }
829     }
830
831     err = zip_writer->FinishEntry();
832     if (err) {
833         MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
834         return false;
835     }
836
837     return true;
838 }
839
840 bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
841     ScopedFd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
842     if (fd.get() == -1) {
843         MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
844         return false;
845     }
846
847     return add_zip_entry_from_fd(entry_name, fd.get());
848 }
849
850 /* adds a file to the existing zipped bugreport */
851 static int _add_file_from_fd(const char *title, const char *path, int fd) {
852     return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
853 }
854
855 // TODO: move to util.cpp
856 void add_dir(const char *dir, bool recursive) {
857     if (!is_zipping()) {
858         MYLOGD("Not adding dir %s because dumpstate is not zipping\n", dir);
859         return;
860     }
861     MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive);
862     DurationReporter duration_reporter(dir, NULL);
863     dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd);
864 }
865
866 bool is_zipping() {
867     return zip_writer != nullptr;
868 }
869
870 /* adds a text entry entry to the existing zip file. */
871 static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
872     if (!is_zipping()) {
873         MYLOGD("Not adding text entry %s because dumpstate is not zipping\n", entry_name.c_str());
874         return false;
875     }
876     MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
877     int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
878     if (err) {
879         MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
880                 ZipWriter::ErrorCodeString(err));
881         return false;
882     }
883
884     err = zip_writer->WriteBytes(content.c_str(), content.length());
885     if (err) {
886         MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
887                 ZipWriter::ErrorCodeString(err));
888         return false;
889     }
890
891     err = zip_writer->FinishEntry();
892     if (err) {
893         MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
894         return false;
895     }
896
897     return true;
898 }
899
900 static void dump_iptables() {
901     run_command("IPTABLES", 10, "iptables", "-L", "-nvx", NULL);
902     run_command("IP6TABLES", 10, "ip6tables", "-L", "-nvx", NULL);
903     run_command("IPTABLES NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL);
904     /* no ip6 nat */
905     run_command("IPTABLES MANGLE", 10, "iptables", "-t", "mangle", "-L", "-nvx", NULL);
906     run_command("IP6TABLES MANGLE", 10, "ip6tables", "-t", "mangle", "-L", "-nvx", NULL);
907     run_command("IPTABLES RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL);
908     run_command("IP6TABLES RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
909 }
910
911 static void dumpstate(const std::string& screenshot_path, const std::string& version) {
912     DurationReporter duration_reporter("DUMPSTATE");
913     unsigned long timeout;
914
915     dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
916     run_command("UPTIME", 10, "uptime", NULL);
917     dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
918     dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
919     dump_file("MEMORY INFO", "/proc/meminfo");
920     run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-H", NULL);
921     run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
922     dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
923     dump_file("VMALLOC INFO", "/proc/vmallocinfo");
924     dump_file("SLAB INFO", "/proc/slabinfo");
925     dump_file("ZONEINFO", "/proc/zoneinfo");
926     dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
927     dump_file("BUDDYINFO", "/proc/buddyinfo");
928     dump_file("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
929
930     dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
931     dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
932     dump_file("KERNEL SYNC", "/d/sync");
933
934     run_command("PROCESSES AND THREADS", 10, "ps", "-Z", "-t", "-p", "-P", NULL);
935     run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
936
937     run_command("PRINTENV", 10, "printenv", NULL);
938     run_command("NETSTAT", 10, "netstat", "-n", NULL);
939     run_command("LSMOD", 10, "lsmod", NULL);
940
941     do_dmesg();
942
943     run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
944     for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
945     for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
946     for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
947
948     /* Dump Bluetooth HCI logs */
949     add_dir("/data/misc/bluetooth/logs", true);
950
951     if (!screenshot_path.empty()) {
952         MYLOGI("taking late screenshot\n");
953         take_screenshot(screenshot_path);
954         MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
955     }
956
957     // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
958     // calculate timeout
959     timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
960     if (timeout < 20000) {
961         timeout = 20000;
962     }
963     run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
964                                                         "-v", "printable",
965                                                         "-d",
966                                                         "*:v", NULL);
967     timeout = logcat_timeout("events");
968     if (timeout < 20000) {
969         timeout = 20000;
970     }
971     run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
972                                                        "-v", "threadtime",
973                                                        "-v", "printable",
974                                                        "-d",
975                                                        "*:v", NULL);
976     timeout = logcat_timeout("radio");
977     if (timeout < 20000) {
978         timeout = 20000;
979     }
980     run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
981                                                        "-v", "threadtime",
982                                                        "-v", "printable",
983                                                        "-d",
984                                                        "*:v", NULL);
985
986     run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
987
988     /* show the traces we collected in main(), if that was done */
989     if (dump_traces_path != NULL) {
990         dump_file("VM TRACES JUST NOW", dump_traces_path);
991     }
992
993     /* only show ANR traces if they're less than 15 minutes old */
994     struct stat st;
995     char anr_traces_path[PATH_MAX];
996     property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
997     if (!anr_traces_path[0]) {
998         printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
999     } else {
1000       int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
1001                                        O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
1002       if (fd < 0) {
1003           printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
1004       } else {
1005           dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
1006       }
1007     }
1008
1009     /* slow traces for slow operations */
1010     if (anr_traces_path[0] != 0) {
1011         int tail = strlen(anr_traces_path)-1;
1012         while (tail > 0 && anr_traces_path[tail] != '/') {
1013             tail--;
1014         }
1015         int i = 0;
1016         while (1) {
1017             sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
1018             if (stat(anr_traces_path, &st)) {
1019                 // No traces file at this index, done with the files.
1020                 break;
1021             }
1022             dump_file("VM TRACES WHEN SLOW", anr_traces_path);
1023             i++;
1024         }
1025     }
1026
1027     int dumped = 0;
1028     for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
1029         if (tombstone_data[i].fd != -1) {
1030             const char *name = tombstone_data[i].name;
1031             int fd = tombstone_data[i].fd;
1032             dumped = 1;
1033             if (zip_writer) {
1034                 if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
1035                     MYLOGE("Unable to add tombstone %s to zip file\n", name);
1036                 }
1037             } else {
1038                 dump_file_from_fd("TOMBSTONE", name, fd);
1039             }
1040             close(fd);
1041             tombstone_data[i].fd = -1;
1042         }
1043     }
1044     if (!dumped) {
1045         printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
1046     }
1047
1048     dump_file("NETWORK DEV INFO", "/proc/net/dev");
1049     dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1050     dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1051     dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1052     dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1053
1054     if (!stat(PSTORE_LAST_KMSG, &st)) {
1055         /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
1056         dump_file("LAST KMSG", PSTORE_LAST_KMSG);
1057     } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
1058         dump_file("LAST KMSG", ALT_PSTORE_LAST_KMSG);
1059     } else {
1060         /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
1061         dump_file("LAST KMSG", "/proc/last_kmsg");
1062     }
1063
1064     /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
1065     run_command("LAST LOGCAT", 10, "logcat", "-L",
1066                                              "-b", "all",
1067                                              "-v", "threadtime",
1068                                              "-v", "printable",
1069                                              "-d",
1070                                              "*:v", NULL);
1071
1072     /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1073
1074     run_command("NETWORK INTERFACES", 10, "ip", "link", NULL);
1075
1076     run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL);
1077     run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL);
1078
1079     run_command("IP RULES", 10, "ip", "rule", "show", NULL);
1080     run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
1081
1082     dump_route_tables();
1083
1084     run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
1085     run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
1086     run_command("MULTICAST ADDRESSES", 10, "ip", "maddr", NULL);
1087     run_command("WIFI NETWORKS", 20, "wpa_cli", "IFNAME=wlan0", "list_networks", NULL);
1088
1089 #ifdef FWDUMP_bcmdhd
1090     run_command("ND OFFLOAD TABLE", 5,
1091             SU_PATH, "root", WLUTIL, "nd_hostip", NULL);
1092
1093     run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
1094             SU_PATH, "root", WLUTIL, "counters", NULL);
1095
1096     run_command("ND OFFLOAD STATUS (1)", 5,
1097             SU_PATH, "root", WLUTIL, "nd_status", NULL);
1098
1099 #endif
1100     dump_file("INTERRUPTS (1)", "/proc/interrupts");
1101
1102     run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "-t", "10", "connectivity", "--diag", NULL);
1103
1104 #ifdef FWDUMP_bcmdhd
1105     run_command("DUMP WIFI STATUS", 20,
1106             SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
1107
1108     run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
1109             SU_PATH, "root", WLUTIL, "counters", NULL);
1110
1111     run_command("ND OFFLOAD STATUS (2)", 5,
1112             SU_PATH, "root", WLUTIL, "nd_status", NULL);
1113 #endif
1114     dump_file("INTERRUPTS (2)", "/proc/interrupts");
1115
1116     print_properties();
1117
1118     run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
1119     run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
1120
1121     run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);
1122
1123     run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
1124
1125     printf("------ BACKLIGHTS ------\n");
1126     printf("LCD brightness=");
1127     dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness");
1128     printf("Button brightness=");
1129     dump_file(NULL, "/sys/class/leds/button-backlight/brightness");
1130     printf("Keyboard brightness=");
1131     dump_file(NULL, "/sys/class/leds/keyboard-backlight/brightness");
1132     printf("ALS mode=");
1133     dump_file(NULL, "/sys/class/leds/lcd-backlight/als");
1134     printf("LCD driver registers:\n");
1135     dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
1136     printf("\n");
1137
1138     /* Binder state is expensive to look at as it uses a lot of memory. */
1139     dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1140     dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1141     dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1142     dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
1143     dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
1144
1145     printf("========================================================\n");
1146     printf("== Board\n");
1147     printf("========================================================\n");
1148
1149     dumpstate_board();
1150     printf("\n");
1151
1152     /* Migrate the ril_dumpstate to a dumpstate_board()? */
1153     char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
1154     property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
1155     if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
1156         if (is_user_build()) {
1157             // su does not exist on user builds, so try running without it.
1158             // This way any implementations of vril-dump that do not require
1159             // root can run on user builds.
1160             run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
1161                     "vril-dump", NULL);
1162         } else {
1163             run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
1164                     SU_PATH, "root", "vril-dump", NULL);
1165         }
1166     }
1167
1168     printf("========================================================\n");
1169     printf("== Android Framework Services\n");
1170     printf("========================================================\n");
1171
1172     run_command("DUMPSYS", 60, "dumpsys", "-t", "60", "--skip", "meminfo", "cpuinfo", NULL);
1173
1174     printf("========================================================\n");
1175     printf("== Checkins\n");
1176     printf("========================================================\n");
1177
1178     run_command("CHECKIN BATTERYSTATS", 30, "dumpsys", "-t", "30", "batterystats", "-c", NULL);
1179     run_command("CHECKIN MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "--checkin", NULL);
1180     run_command("CHECKIN NETSTATS", 30, "dumpsys", "-t", "30", "netstats", "--checkin", NULL);
1181     run_command("CHECKIN PROCSTATS", 30, "dumpsys", "-t", "30", "procstats", "-c", NULL);
1182     run_command("CHECKIN USAGESTATS", 30, "dumpsys", "-t", "30", "usagestats", "-c", NULL);
1183     run_command("CHECKIN PACKAGE", 30, "dumpsys", "-t", "30", "package", "--checkin", NULL);
1184
1185     printf("========================================================\n");
1186     printf("== Running Application Activities\n");
1187     printf("========================================================\n");
1188
1189     run_command("APP ACTIVITIES", 30, "dumpsys", "-t", "30", "activity", "all", NULL);
1190
1191     printf("========================================================\n");
1192     printf("== Running Application Services\n");
1193     printf("========================================================\n");
1194
1195     run_command("APP SERVICES", 30, "dumpsys", "-t", "30", "activity", "service", "all", NULL);
1196
1197     printf("========================================================\n");
1198     printf("== Running Application Providers\n");
1199     printf("========================================================\n");
1200
1201     run_command("APP PROVIDERS", 30, "dumpsys", "-t", "30", "activity", "provider", "all", NULL);
1202
1203     // dump_modem_logs adds the modem logs if available to the bugreport.
1204     // Do this at the end to allow for sufficient time for the modem logs to be
1205     // collected.
1206     dump_modem_logs();
1207
1208     printf("========================================================\n");
1209     printf("== Final progress (pid %d): %d/%d (originally %d)\n",
1210             getpid(), progress, weight_total, WEIGHT_TOTAL);
1211     printf("========================================================\n");
1212     printf("== dumpstate: done\n");
1213     printf("========================================================\n");
1214 }
1215
1216 static void usage() {
1217   fprintf(stderr,
1218           "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
1219           "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1220           "  -h: display this help message\n"
1221           "  -b: play sound file instead of vibrate, at beginning of job\n"
1222           "  -e: play sound file instead of vibrate, at end of job\n"
1223           "  -o: write to file (instead of stdout)\n"
1224           "  -d: append date to filename (requires -o)\n"
1225           "  -p: capture screenshot to filename.png (requires -o)\n"
1226           "  -z: generate zipped file (requires -o)\n"
1227           "  -s: write output to control socket (for init)\n"
1228           "  -S: write file location to control socket (for init; requires -o and -z)"
1229           "  -q: disable vibrate\n"
1230           "  -B: send broadcast when finished (requires -o)\n"
1231           "  -P: send broadcast when started and update system properties on "
1232           "progress (requires -o and -B)\n"
1233           "  -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1234           "shouldn't be used with -P)\n"
1235           "  -V: sets the bugreport format version (valid values: %s)\n",
1236           VERSION_DEFAULT.c_str());
1237 }
1238
1239 static void sigpipe_handler(int n) {
1240     // don't complain to stderr or stdout
1241     _exit(EXIT_FAILURE);
1242 }
1243
1244 /* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1245    temporary file.
1246  */
1247 static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
1248         time_t now) {
1249     if (!add_zip_entry(bugreport_name, bugreport_path)) {
1250         MYLOGE("Failed to add text entry to .zip file\n");
1251         return false;
1252     }
1253     if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
1254         MYLOGE("Failed to add main_entry.txt to .zip file\n");
1255         return false;
1256     }
1257
1258     int32_t err = zip_writer->Finish();
1259     if (err) {
1260         MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
1261         return false;
1262     }
1263
1264     if (is_user_build()) {
1265         MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
1266         if (remove(bugreport_path.c_str())) {
1267             ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
1268         }
1269     } else {
1270         MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1271     }
1272
1273     return true;
1274 }
1275
1276 static std::string SHA256_file_hash(std::string filepath) {
1277     ScopedFd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC
1278             | O_NOFOLLOW)));
1279     if (fd.get() == -1) {
1280         MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
1281         return NULL;
1282     }
1283
1284     SHA256_CTX ctx;
1285     SHA256_init(&ctx);
1286
1287     std::vector<uint8_t> buffer(65536);
1288     while (1) {
1289         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1290         if (bytes_read == 0) {
1291             break;
1292         } else if (bytes_read == -1) {
1293             MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
1294             return NULL;
1295         }
1296
1297         SHA256_update(&ctx, buffer.data(), bytes_read);
1298     }
1299
1300     uint8_t hash[SHA256_DIGEST_SIZE];
1301     memcpy(hash, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
1302     char hash_buffer[SHA256_DIGEST_SIZE * 2 + 1];
1303     for(size_t i = 0; i < SHA256_DIGEST_SIZE; i++) {
1304         sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
1305     }
1306     hash_buffer[sizeof(hash_buffer) - 1] = 0;
1307     return std::string(hash_buffer);
1308 }
1309
1310 int main(int argc, char *argv[]) {
1311     struct sigaction sigact;
1312     int do_add_date = 0;
1313     int do_zip_file = 0;
1314     int do_vibrate = 1;
1315     char* use_outfile = 0;
1316     int use_socket = 0;
1317     int use_control_socket = 0;
1318     int do_fb = 0;
1319     int do_broadcast = 0;
1320     int do_early_screenshot = 0;
1321     int is_remote_mode = 0;
1322     std::string version = VERSION_DEFAULT;
1323
1324     now = time(NULL);
1325
1326     MYLOGI("begin\n");
1327
1328     /* gets the sequential id */
1329     char last_id[PROPERTY_VALUE_MAX];
1330     property_get("dumpstate.last_id", last_id, "0");
1331     id = strtoul(last_id, NULL, 10) + 1;
1332     snprintf(last_id, sizeof(last_id), "%lu", id);
1333     property_set("dumpstate.last_id", last_id);
1334     MYLOGI("dumpstate id: %lu\n", id);
1335
1336     /* clear SIGPIPE handler */
1337     memset(&sigact, 0, sizeof(sigact));
1338     sigact.sa_handler = sigpipe_handler;
1339     sigaction(SIGPIPE, &sigact, NULL);
1340
1341     /* set as high priority, and protect from OOM killer */
1342     setpriority(PRIO_PROCESS, 0, -20);
1343
1344     FILE *oom_adj = fopen("/proc/self/oom_score_adj", "we");
1345     if (oom_adj) {
1346         fputs("-1000", oom_adj);
1347         fclose(oom_adj);
1348     } else {
1349         /* fallback to kernels <= 2.6.35 */
1350         oom_adj = fopen("/proc/self/oom_adj", "we");
1351         if (oom_adj) {
1352             fputs("-17", oom_adj);
1353             fclose(oom_adj);
1354         }
1355     }
1356
1357     /* parse arguments */
1358     std::string args;
1359     format_args(argc, const_cast<const char **>(argv), &args);
1360     MYLOGD("Dumpstate command line: %s\n", args.c_str());
1361     int c;
1362     while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
1363         switch (c) {
1364             case 'd': do_add_date = 1;          break;
1365             case 'z': do_zip_file = 1;          break;
1366             case 'o': use_outfile = optarg;     break;
1367             case 's': use_socket = 1;           break;
1368             case 'S': use_control_socket = 1;   break;
1369             case 'v': break;  // compatibility no-op
1370             case 'q': do_vibrate = 0;           break;
1371             case 'p': do_fb = 1;                break;
1372             case 'P': do_update_progress = 1;   break;
1373             case 'R': is_remote_mode = 1;       break;
1374             case 'B': do_broadcast = 1;         break;
1375             case 'V': version = optarg;         break;
1376             case '?': printf("\n");
1377             case 'h':
1378                 usage();
1379                 exit(1);
1380         }
1381     }
1382
1383     if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) {
1384         usage();
1385         exit(1);
1386     }
1387
1388     if (use_control_socket && !do_zip_file) {
1389         usage();
1390         exit(1);
1391     }
1392
1393     if (do_update_progress && !do_broadcast) {
1394         usage();
1395         exit(1);
1396     }
1397
1398     if (is_remote_mode && (do_update_progress || !do_broadcast || !do_zip_file || !do_add_date)) {
1399         usage();
1400         exit(1);
1401     }
1402
1403     if (version != VERSION_DEFAULT) {
1404       usage();
1405       exit(1);
1406     }
1407
1408     MYLOGI("bugreport format version: %s\n", version.c_str());
1409
1410     do_early_screenshot = do_update_progress;
1411
1412     // If we are going to use a socket, do it as early as possible
1413     // to avoid timeouts from bugreport.
1414     if (use_socket) {
1415         redirect_to_socket(stdout, "dumpstate");
1416     }
1417
1418     if (use_control_socket) {
1419         MYLOGD("Opening control socket\n");
1420         control_socket_fd = open_socket("dumpstate");
1421         do_update_progress = 1;
1422     }
1423
1424     /* full path of the temporary file containing the bugreport */
1425     std::string tmp_path;
1426
1427     /* full path of the file containing the dumpstate logs*/
1428     std::string log_path;
1429
1430     /* full path of the systrace file, when enabled */
1431     std::string systrace_path;
1432
1433     /* full path of the temporary file containing the screenshot (when requested) */
1434     std::string screenshot_path;
1435
1436     /* base name (without suffix or extensions) of the bugreport files */
1437     std::string base_name;
1438
1439     /* pointer to the actual path, be it zip or text */
1440     std::string path;
1441
1442     /* pointer to the zipped file */
1443     std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
1444
1445     /* redirect output if needed */
1446     bool is_redirecting = !use_socket && use_outfile;
1447
1448     if (is_redirecting) {
1449         bugreport_dir = dirname(use_outfile);
1450         base_name = basename(use_outfile);
1451         if (do_add_date) {
1452             char date[80];
1453             strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1454             suffix = date;
1455         } else {
1456             suffix = "undated";
1457         }
1458         char build_id[PROPERTY_VALUE_MAX];
1459         property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
1460         base_name = base_name + "-" + build_id;
1461         if (do_fb) {
1462             // TODO: if dumpstate was an object, the paths could be internal variables and then
1463             // we could have a function to calculate the derived values, such as:
1464             //     screenshot_path = GetPath(".png");
1465             screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1466         }
1467         tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
1468         log_path = bugreport_dir + "/dumpstate_log-" + suffix + "-"
1469                 + std::to_string(getpid()) + ".txt";
1470
1471         MYLOGD("Bugreport dir: %s\n"
1472                 "Base name: %s\n"
1473                 "Suffix: %s\n"
1474                 "Log path: %s\n"
1475                 "Temporary path: %s\n"
1476                 "Screenshot path: %s\n",
1477                 bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(),
1478                 log_path.c_str(), tmp_path.c_str(), screenshot_path.c_str());
1479
1480         if (do_zip_file) {
1481             path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1482             MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
1483             create_parent_dirs(path.c_str());
1484             zip_file.reset(fopen(path.c_str(), "wb"));
1485             if (!zip_file) {
1486                 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
1487                 do_zip_file = 0;
1488             } else {
1489                 zip_writer.reset(new ZipWriter(zip_file.get()));
1490             }
1491             add_text_zip_entry("version.txt", version);
1492         }
1493
1494         if (do_update_progress) {
1495             if (do_broadcast) {
1496                 // clang-format off
1497                 std::vector<std::string> am_args = {
1498                      "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1499                      "--es", "android.intent.extra.NAME", suffix,
1500                      "--ei", "android.intent.extra.ID", std::to_string(id),
1501                      "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1502                      "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1503                 };
1504                 // clang-format on
1505                 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1506             }
1507             if (use_control_socket) {
1508                 dprintf(control_socket_fd, "BEGIN:%s\n", path.c_str());
1509             }
1510         }
1511     }
1512
1513     /* read /proc/cmdline before dropping root */
1514     FILE *cmdline = fopen("/proc/cmdline", "re");
1515     if (cmdline) {
1516         fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1517         fclose(cmdline);
1518     }
1519
1520     /* open the vibrator before dropping root */
1521     std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
1522     if (do_vibrate) {
1523         vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
1524         if (vibrator) {
1525             vibrate(vibrator.get(), 150);
1526         }
1527     }
1528
1529     if (do_fb && do_early_screenshot) {
1530         if (screenshot_path.empty()) {
1531             // should not have happened
1532             MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
1533         } else {
1534             MYLOGI("taking early screenshot\n");
1535             take_screenshot(screenshot_path);
1536             MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
1537             if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
1538                 MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
1539                         screenshot_path.c_str(), strerror(errno));
1540             }
1541         }
1542     }
1543
1544     if (do_zip_file) {
1545         if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
1546             MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
1547         }
1548     }
1549
1550     if (is_redirecting) {
1551         redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
1552         if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
1553             MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1554                     log_path.c_str(), strerror(errno));
1555         }
1556         /* TODO: rather than generating a text file now and zipping it later,
1557            it would be more efficient to redirect stdout to the zip entry
1558            directly, but the libziparchive doesn't support that option yet. */
1559         redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
1560         if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
1561             MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
1562                     tmp_path.c_str(), strerror(errno));
1563         }
1564     }
1565     // NOTE: there should be no stdout output until now, otherwise it would break the header.
1566     // In particular, DurationReport objects should be created passing 'title, NULL', so their
1567     // duration is logged into MYLOG instead.
1568     print_header(version);
1569
1570     // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1571     // First try to dump anrd trace if the daemon is running. Otherwise, dump
1572     // the raw trace.
1573     if (!dump_anrd_trace()) {
1574         dump_systrace();
1575     }
1576
1577     // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1578     dump_raft();
1579
1580     // Invoking the following dumpsys calls before dump_traces() to try and
1581     // keep the system stats as close to its initial state as possible.
1582     run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "-a", NULL);
1583     run_command_as_shell("DUMPSYS CPUINFO", 10, "dumpsys", "-t", "10", "cpuinfo", "-a", NULL);
1584
1585     /* collect stack traces from Dalvik and native processes (needs root) */
1586     dump_traces_path = dump_traces();
1587
1588     /* Run some operations that require root. */
1589     get_tombstone_fds(tombstone_data);
1590     add_dir(RECOVERY_DIR, true);
1591     add_dir(RECOVERY_DATA_DIR, true);
1592     add_dir(LOGPERSIST_DATA_DIR, false);
1593     if (!is_user_build()) {
1594         add_dir(PROFILE_DATA_DIR_CUR, true);
1595         add_dir(PROFILE_DATA_DIR_REF, true);
1596     }
1597     add_mountinfo();
1598     dump_iptables();
1599
1600     // Capture any IPSec policies in play.  No keys are exposed here.
1601     run_command("IP XFRM POLICY", 10, "ip", "xfrm", "policy", nullptr);
1602
1603     // Run ss as root so we can see socket marks.
1604     run_command("DETAILED SOCKET STATE", 10, "ss", "-eionptu", NULL);
1605
1606     if (!drop_root_user()) {
1607         return -1;
1608     }
1609
1610     dumpstate(do_early_screenshot ? "": screenshot_path, version);
1611
1612     /* close output if needed */
1613     if (is_redirecting) {
1614         fclose(stdout);
1615     }
1616
1617     /* rename or zip the (now complete) .tmp file to its final location */
1618     if (use_outfile) {
1619
1620         /* check if user changed the suffix using system properties */
1621         char key[PROPERTY_KEY_MAX];
1622         char value[PROPERTY_VALUE_MAX];
1623         snprintf(key, sizeof(key), "dumpstate.%d.name", getpid());
1624         property_get(key, value, "");
1625         bool change_suffix= false;
1626         if (value[0]) {
1627             /* must whitelist which characters are allowed, otherwise it could cross directories */
1628             std::regex valid_regex("^[-_a-zA-Z0-9]+$");
1629             if (std::regex_match(value, valid_regex)) {
1630                 change_suffix = true;
1631             } else {
1632                 MYLOGE("invalid suffix provided by user: %s\n", value);
1633             }
1634         }
1635         if (change_suffix) {
1636             MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), value);
1637             suffix = value;
1638             if (!screenshot_path.empty()) {
1639                 std::string new_screenshot_path =
1640                         bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1641                 if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
1642                     MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
1643                             new_screenshot_path.c_str(), strerror(errno));
1644                 } else {
1645                     screenshot_path = new_screenshot_path;
1646                 }
1647             }
1648         }
1649
1650         bool do_text_file = true;
1651         if (do_zip_file) {
1652             std::string entry_name = base_name + "-" + suffix + ".txt";
1653             MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
1654             if (!finish_zip_file(entry_name, tmp_path, now)) {
1655                 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
1656                 do_text_file = true;
1657             } else {
1658                 do_text_file = false;
1659                 // Since zip file is already created, it needs to be renamed.
1660                 std::string new_path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1661                 if (path != new_path) {
1662                     MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
1663                     if (rename(path.c_str(), new_path.c_str())) {
1664                         MYLOGE("rename(%s, %s): %s\n", path.c_str(),
1665                                 new_path.c_str(), strerror(errno));
1666                     } else {
1667                         path = new_path;
1668                     }
1669                 }
1670             }
1671         }
1672         if (do_text_file) {
1673             path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt";
1674             MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
1675             if (rename(tmp_path.c_str(), path.c_str())) {
1676                 MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
1677                 path.clear();
1678             }
1679         }
1680         if (use_control_socket) {
1681             if (do_text_file) {
1682                 dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
1683                         "for more details\n", log_path.c_str());
1684             } else {
1685                 dprintf(control_socket_fd, "OK:%s\n", path.c_str());
1686             }
1687         }
1688     }
1689
1690     /* vibrate a few but shortly times to let user know it's finished */
1691     if (vibrator) {
1692         for (int i = 0; i < 3; i++) {
1693             vibrate(vibrator.get(), 75);
1694             usleep((75 + 50) * 1000);
1695         }
1696     }
1697
1698     /* tell activity manager we're done */
1699     if (do_broadcast) {
1700         if (!path.empty()) {
1701             MYLOGI("Final bugreport path: %s\n", path.c_str());
1702             // clang-format off
1703             std::vector<std::string> am_args = {
1704                  "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1705                  "--ei", "android.intent.extra.ID", std::to_string(id),
1706                  "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1707                  "--ei", "android.intent.extra.MAX", std::to_string(weight_total),
1708                  "--es", "android.intent.extra.BUGREPORT", path,
1709                  "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
1710             };
1711             // clang-format on
1712             if (do_fb) {
1713                 am_args.push_back("--es");
1714                 am_args.push_back("android.intent.extra.SCREENSHOT");
1715                 am_args.push_back(screenshot_path);
1716             }
1717             if (is_remote_mode) {
1718                 am_args.push_back("--es");
1719                 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1720                 am_args.push_back(SHA256_file_hash(path));
1721                 send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1722             } else {
1723                 send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
1724             }
1725         } else {
1726             MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
1727         }
1728     }
1729
1730     MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
1731     MYLOGI("done\n");
1732
1733     if (is_redirecting) {
1734         fclose(stderr);
1735     }
1736
1737     if (use_control_socket && control_socket_fd != -1) {
1738       MYLOGD("Closing control socket\n");
1739       close(control_socket_fd);
1740     }
1741
1742     return 0;
1743 }