OSDN Git Service

Increase YV12BufferPow2 test threshold
[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/stringprintf.h>
38 #include <android-base/file.h>
39 #include <cutils/properties.h>
40
41 #include "private/android_filesystem_config.h"
42
43 #define LOG_TAG "dumpstate"
44 #include <cutils/log.h>
45
46 #include "dumpstate.h"
47 #include "ScopedFd.h"
48 #include "ziparchive/zip_writer.h"
49
50 #include "mincrypt/sha256.h"
51
52 using android::base::StringPrintf;
53
54 /* read before root is shed */
55 static char cmdline_buf[16384] = "(unknown)";
56 static const char *dump_traces_path = NULL;
57
58 // TODO: variables below should be part of dumpstate object
59 static unsigned long id;
60 static char build_type[PROPERTY_VALUE_MAX];
61 static time_t now;
62 static std::unique_ptr<ZipWriter> zip_writer;
63 static std::set<std::string> mount_points;
64 void add_mountinfo();
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;
69
70 #define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
71 #define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
72
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"
85
86 typedef struct {
87   char name[TOMBSTONE_MAX_LEN];
88   int fd;
89 } tombstone_data_t;
90
91 static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
92
93 const std::string ZIP_ROOT_DIR = "FS";
94 std::string bugreport_dir;
95
96 /*
97  * List of supported zip format versions.
98  *
99  * See bugreport-format.txt for more info.
100  */
101 static std::string VERSION_DEFAULT = "1.0";
102
103 bool is_user_build() {
104     return 0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1);
105 }
106
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));
115         struct stat st;
116         if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
117             (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) {
118         data[i].fd = fd;
119         } else {
120         close(fd);
121             data[i].fd = -1;
122         }
123     }
124 }
125
126 // for_each_pid() callback to get mount info about a process.
127 void do_mountinfo(int pid, const char *name) {
128     char path[PATH_MAX];
129
130     // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
131     // are added.
132     snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
133     char linkname[PATH_MAX];
134     ssize_t r = readlink(path, linkname, PATH_MAX);
135     if (r == -1) {
136         MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
137         return;
138     }
139     linkname[r] = '\0';
140
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);
146         } else {
147             MYLOGE("Unable to add mountinfo %s to zip file\n", path);
148         }
149     }
150 }
151
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());
159 }
160
161 static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
162 {
163     DIR *d;
164     struct dirent *de;
165     char path[PATH_MAX];
166
167     d = opendir(driverpath);
168     if (d == NULL) {
169         return;
170     }
171
172     while ((de = readdir(d))) {
173         if (de->d_type != DT_LNK) {
174             continue;
175         }
176         snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
177         dump_file(title, path);
178     }
179
180     closedir(d);
181 }
182
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) {
185     DIR *proc_dir;
186     struct dirent *ps;
187     unsigned int pid;
188     std::string cmdline;
189
190     if (!(proc_dir = opendir("/proc"))) {
191         MYLOGE("Can't open /proc\n");
192         return 0;
193     }
194
195     while ((ps = readdir(proc_dir))) {
196         if (!(pid = atoi(ps->d_name))) {
197             continue;
198         }
199         android::base::ReadFileToString("/proc/"
200                 + std::string(ps->d_name) + "/cmdline", &cmdline);
201         if (cmdline.find(ps_name) == std::string::npos) {
202             continue;
203         } else {
204             closedir(proc_dir);
205             return pid;
206         }
207     }
208     closedir(proc_dir);
209     return 0;
210 }
211
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() {
217     unsigned int pid;
218     char buf[50], path[PATH_MAX];
219     struct dirent *trace;
220     struct stat st;
221     DIR *trace_dir;
222     int retry = 5;
223     long max_ctime = 0, old_mtime;
224     long long cur_size = 0;
225     const char *trace_path = "/data/misc/anrd/";
226
227     if (!zip_writer) {
228         MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
229         return false;
230     }
231
232     // find anrd's pid if it is running.
233     pid = pid_of_process("/system/xbin/anrd");
234
235     if (pid > 0) {
236         if (stat(trace_path, &st) == 0) {
237             old_mtime = st.st_mtime;
238         } else {
239             MYLOGE("Failed to find: %s\n", trace_path);
240             return false;
241         }
242
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");
247             return false;
248         }
249
250         while (retry-- > 0 && old_mtime == st.st_mtime) {
251             sleep(1);
252             stat(trace_path, &st);
253         }
254
255         if (retry < 0 && old_mtime == st.st_mtime) {
256             MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
257             return false;
258         }
259
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);
263         }
264         while ((trace = readdir(trace_dir))) {
265             if (strcmp(trace->d_name, ".") == 0
266                     || strcmp(trace->d_name, "..") == 0) {
267                 continue;
268             }
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);
274                 }
275             }
276         }
277         closedir(trace_dir);
278
279         // Wait until the dump completes by checking the size of the trace.
280         if (max_ctime > 0) {
281             sprintf(path, "%s%s", trace_path, buf);
282             while(true) {
283                 sleep(1);
284                 if (stat(path, &st) == 0) {
285                     if (st.st_size == cur_size) {
286                         break;
287                     } else if (st.st_size > cur_size) {
288                         cur_size = st.st_size;
289                     } else {
290                         return false;
291                     }
292                 } else {
293                     MYLOGE("Cant stat() %s anymore\n", path);
294                     return false;
295                 }
296             }
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);
300             } else {
301                 if (remove(path)) {
302                     MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
303                 }
304                 return true;
305             }
306         } else {
307             MYLOGE("Can't stats any trace file under %s\n", trace_path);
308         }
309     }
310     return false;
311 }
312
313 static void dump_systrace() {
314     if (!zip_writer) {
315         MYLOGD("Not dumping systrace because zip_writer is not set\n");
316         return;
317     }
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");
321         return;
322     }
323     const char* path = "/sys/kernel/debug/tracing/tracing_on";
324     long int is_tracing;
325     if (read_file_as_long(path, &is_tracing)) {
326         return; // error already logged
327     }
328     if (is_tracing <= 0) {
329         MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
330         return;
331     }
332
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 ");
343         //        }
344     }
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());
347     } else {
348         if (remove(systrace_path.c_str())) {
349             MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
350         }
351     }
352 }
353
354 static void dump_raft() {
355     if (is_user_build()) {
356         return;
357     }
358
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");
362         return;
363     }
364
365     struct stat s;
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);
368         return;
369     }
370
371     if (!zip_writer) {
372         // Write compressed and encoded raft logs to stdout if not zip_writer.
373         run_command("RAFT LOGS", 600, "logcompressor", "-r", RAFT_DIR, NULL);
374         return;
375     }
376
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());
381     } else {
382         if (remove(raft_log_path.c_str())) {
383             MYLOGE("Error removing raft file %s: %s\n", raft_log_path.c_str(), strerror(errno));
384         }
385     }
386 }
387
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? */
392         return false;
393     }
394     return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
395 }
396
397 static bool skip_none(const char *path) {
398     return false;
399 }
400
401 static const char mmcblk0[] = "/sys/block/mmcblk0/";
402 unsigned long worst_write_perf = 20000; /* in KB/s */
403
404 //
405 //  stat offsets
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
431 //
432 // read I/Os, write I/Os
433 // =====================
434 //
435 // These values increment when an I/O request completes.
436 //
437 // read merges, write merges
438 // =========================
439 //
440 // These values increment when an I/O request is merged with an
441 // already-queued I/O request.
442 //
443 // read sectors, write sectors
444 // ===========================
445 //
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
451 //
452 // read ticks, write ticks
453 // =======================
454 //
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.
460 //
461 // in_flight
462 // =========
463 //
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.
467 //
468 // io_ticks
469 // ========
470 //
471 // This value counts the number of milliseconds during which the device has
472 // had I/O requests queued.
473 //
474 // time_in_queue
475 // =============
476 //
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).
481 #define S_TO_MS 1000
482 //
483
484 static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
485     unsigned long long fields[__STAT_NUMBER_FIELD];
486     bool z;
487     char *cp, *buffer = NULL;
488     size_t i = 0;
489     FILE *fp = fdopen(fd, "rb");
490     getline(&buffer, &i, fp);
491     fclose(fp);
492     if (!buffer) {
493         return -errno;
494     }
495     i = strlen(buffer);
496     while ((i > 0) && (buffer[i - 1] == '\n')) {
497         buffer[--i] = '\0';
498     }
499     if (!*buffer) {
500         free(buffer);
501         return 0;
502     }
503     z = true;
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) {
507             z = false;
508         }
509     }
510     if (z) { /* never accessed */
511         free(buffer);
512         return 0;
513     }
514
515     if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
516         path += sizeof(mmcblk0) - 1;
517     }
518
519     printf("%s: %s\n", path, buffer);
520     free(buffer);
521
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))
531                                         / divisor;
532             read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
533                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
534                                         / divisor;
535         }
536
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))
545                                         / divisor;
546             write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
547                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
548                                         / divisor;
549         }
550
551         unsigned queue = (fields[__STAT_IN_QUEUE]
552                              + (fields[__STAT_IO_TICKS] >> 1))
553                                  / fields[__STAT_IO_TICKS];
554
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);
558         } else {
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);
561         }
562
563         /* bugreport timeout factor adjustment */
564         if ((write_perf > 1) && (write_perf < worst_write_perf)) {
565             worst_write_perf = write_perf;
566         }
567     }
568     return 0;
569 }
570
571 /* Copied policy from system/core/logd/LogBuffer.cpp */
572
573 #define LOG_BUFFER_SIZE (256 * 1024)
574 #define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
575 #define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
576
577 static bool valid_size(unsigned long value) {
578     if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
579         return false;
580     }
581
582     long pages = sysconf(_SC_PHYS_PAGES);
583     if (pages < 1) {
584         return true;
585     }
586
587     long pagesize = sysconf(_SC_PAGESIZE);
588     if (pagesize <= 1) {
589         pagesize = PAGE_SIZE;
590     }
591
592     // maximum memory impact a somewhat arbitrary ~3%
593     pages = (pages + 31) / 32;
594     unsigned long maximum = pages * pagesize;
595
596     if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
597         return true;
598     }
599
600     return value <= maximum;
601 }
602
603 static unsigned long property_get_size(const char *key) {
604     unsigned long value;
605     char *cp, property[PROPERTY_VALUE_MAX];
606
607     property_get(key, property, "");
608     value = strtoul(property, &cp, 10);
609
610     switch(*cp) {
611     case 'm':
612     case 'M':
613         value *= 1024;
614     /* FALLTHRU */
615     case 'k':
616     case 'K':
617         value *= 1024;
618     /* FALLTHRU */
619     case '\0':
620         break;
621
622     default:
623         value = 0;
624     }
625
626     if (!valid_size(value)) {
627         value = 0;
628     }
629
630     return value;
631 }
632
633 /* timeout in ms */
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;
639
640     default_size = property_get_size(global_tuneable);
641     if (!default_size) {
642         default_size = property_get_size(global_default);
643     }
644
645     snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
646     property_size = property_get_size(key);
647
648     if (!property_size) {
649         snprintf(key, sizeof(key), "%s.%s", global_default, name);
650         property_size = property_get_size(key);
651     }
652
653     if (!property_size) {
654         property_size = default_size;
655     }
656
657     if (!property_size) {
658         property_size = LOG_BUFFER_SIZE;
659     }
660
661     /* Engineering margin is ten-fold our guess */
662     return 10 * (property_size + worst_write_perf) / worst_write_perf;
663 }
664
665 /* End copy from system/core/logd/LogBuffer.cpp */
666
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];
672
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));
680
681     printf("========================================================\n");
682     printf("== dumpstate: %s\n", date);
683     printf("========================================================\n");
684
685     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);
691
692     printf("Kernel: ");
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());
697     printf("\n");
698 }
699
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"
706 };
707
708 bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
709     if (!zip_writer) {
710         MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
711                 entry_name.c_str());
712         return false;
713     }
714     std::string valid_name = entry_name;
715
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());
724         }
725     }
726
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));
731     if (err) {
732         MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
733                 ZipWriter::ErrorCodeString(err));
734         return false;
735     }
736
737     std::vector<uint8_t> buffer(65536);
738     while (1) {
739         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), sizeof(buffer)));
740         if (bytes_read == 0) {
741             break;
742         } else if (bytes_read == -1) {
743             MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
744             return false;
745         }
746         err = zip_writer->WriteBytes(buffer.data(), bytes_read);
747         if (err) {
748             MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
749             return false;
750         }
751     }
752
753     err = zip_writer->FinishEntry();
754     if (err) {
755         MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
756         return false;
757     }
758
759     return true;
760 }
761
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));
766         return false;
767     }
768
769     return add_zip_entry_from_fd(entry_name, fd.get());
770 }
771
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;
775 }
776
777 // TODO: move to util.cpp
778 void add_dir(const char *dir, bool recursive) {
779     if (!zip_writer) {
780         MYLOGD("Not adding dir %s because zip_writer is not set\n", dir);
781         return;
782     }
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);
786 }
787
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) {
790     if (!zip_writer) {
791         MYLOGD("Not adding text zip entry %s because zip_writer is not set\n", entry_name.c_str());
792         return false;
793     }
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);
796     if (err) {
797         MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
798                 ZipWriter::ErrorCodeString(err));
799         return false;
800     }
801
802     err = zip_writer->WriteBytes(content.c_str(), content.length());
803     if (err) {
804         MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
805                 ZipWriter::ErrorCodeString(err));
806         return false;
807     }
808
809     err = zip_writer->FinishEntry();
810     if (err) {
811         MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
812         return false;
813     }
814
815     return true;
816 }
817
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);
822     /* no ip6 nat */
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);
827 }
828
829 static void dumpstate(const std::string& screenshot_path, const std::string& version) {
830     DurationReporter duration_reporter("DUMPSTATE");
831     unsigned long timeout;
832
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");
847
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");
851
852     run_command("PROCESSES AND THREADS", 10, "ps", "-Z", "-t", "-p", "-P", NULL);
853     run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
854
855     run_command("PRINTENV", 10, "printenv", NULL);
856     run_command("NETSTAT", 10, "netstat", "-n", NULL);
857     run_command("LSMOD", 10, "lsmod", NULL);
858
859     do_dmesg();
860
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)");
865
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());
870     }
871
872     // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
873     // calculate timeout
874     timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
875     if (timeout < 20000) {
876         timeout = 20000;
877     }
878     run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
879                                                         "-v", "printable",
880                                                         "-d",
881                                                         "*:v", NULL);
882     timeout = logcat_timeout("events");
883     if (timeout < 20000) {
884         timeout = 20000;
885     }
886     run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
887                                                        "-v", "threadtime",
888                                                        "-v", "printable",
889                                                        "-d",
890                                                        "*:v", NULL);
891     timeout = logcat_timeout("radio");
892     if (timeout < 20000) {
893         timeout = 20000;
894     }
895     run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
896                                                        "-v", "threadtime",
897                                                        "-v", "printable",
898                                                        "-d",
899                                                        "*:v", NULL);
900
901     run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
902
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);
906     }
907
908     /* only show ANR traces if they're less than 15 minutes old */
909     struct stat st;
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");
914     } else {
915       int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
916                                        O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
917       if (fd < 0) {
918           printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
919       } else {
920           dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
921       }
922     }
923
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] != '/') {
928             tail--;
929         }
930         int i = 0;
931         while (1) {
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.
935                 break;
936             }
937             dump_file("VM TRACES WHEN SLOW", anr_traces_path);
938             i++;
939         }
940     }
941
942     int dumped = 0;
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;
947             dumped = 1;
948             if (zip_writer) {
949                 if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
950                     MYLOGE("Unable to add tombstone %s to zip file\n", name);
951                 }
952             } else {
953                 dump_file_from_fd("TOMBSTONE", name, fd);
954             }
955             close(fd);
956             tombstone_data[i].fd = -1;
957         }
958     }
959     if (!dumped) {
960         printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
961     }
962
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");
968
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);
974     } else {
975         /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
976         dump_file("LAST KMSG", "/proc/last_kmsg");
977     }
978
979     /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
980     run_command("LAST LOGCAT", 10, "logcat", "-L",
981                                              "-b", "all",
982                                              "-v", "threadtime",
983                                              "-v", "printable",
984                                              "-d",
985                                              "*:v", NULL);
986
987     /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
988
989     run_command("NETWORK INTERFACES", 10, "ip", "link", NULL);
990
991     run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL);
992     run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL);
993
994     run_command("IP RULES", 10, "ip", "rule", "show", NULL);
995     run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
996
997     dump_route_tables();
998
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);
1003
1004 #ifdef FWDUMP_bcmdhd
1005     run_command("ND OFFLOAD TABLE", 5,
1006             SU_PATH, "root", WLUTIL, "nd_hostip", NULL);
1007
1008     run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
1009             SU_PATH, "root", WLUTIL, "counters", NULL);
1010
1011     run_command("ND OFFLOAD STATUS (1)", 5,
1012             SU_PATH, "root", WLUTIL, "nd_status", NULL);
1013
1014 #endif
1015     dump_file("INTERRUPTS (1)", "/proc/interrupts");
1016
1017     run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "-t", "10", "connectivity", "--diag", NULL);
1018
1019 #ifdef FWDUMP_bcmdhd
1020     run_command("DUMP WIFI STATUS", 20,
1021             SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
1022
1023     run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
1024             SU_PATH, "root", WLUTIL, "counters", NULL);
1025
1026     run_command("ND OFFLOAD STATUS (2)", 5,
1027             SU_PATH, "root", WLUTIL, "nd_status", NULL);
1028 #endif
1029     dump_file("INTERRUPTS (2)", "/proc/interrupts");
1030
1031     print_properties();
1032
1033     run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
1034     run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
1035
1036     run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);
1037
1038     run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
1039
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");
1051     printf("\n");
1052
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");
1059
1060     printf("========================================================\n");
1061     printf("== Board\n");
1062     printf("========================================================\n");
1063
1064     dumpstate_board();
1065     printf("\n");
1066
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),
1076                     "vril-dump", NULL);
1077         } else {
1078             run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
1079                     SU_PATH, "root", "vril-dump", NULL);
1080         }
1081     }
1082
1083     printf("========================================================\n");
1084     printf("== Android Framework Services\n");
1085     printf("========================================================\n");
1086
1087     run_command("DUMPSYS", 60, "dumpsys", "-t", "60", "--skip", "meminfo", "cpuinfo", NULL);
1088
1089     printf("========================================================\n");
1090     printf("== Checkins\n");
1091     printf("========================================================\n");
1092
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);
1099
1100     printf("========================================================\n");
1101     printf("== Running Application Activities\n");
1102     printf("========================================================\n");
1103
1104     run_command("APP ACTIVITIES", 30, "dumpsys", "-t", "30", "activity", "all", NULL);
1105
1106     printf("========================================================\n");
1107     printf("== Running Application Services\n");
1108     printf("========================================================\n");
1109
1110     run_command("APP SERVICES", 30, "dumpsys", "-t", "30", "activity", "service", "all", NULL);
1111
1112     printf("========================================================\n");
1113     printf("== Running Application Providers\n");
1114     printf("========================================================\n");
1115
1116     run_command("APP PROVIDERS", 30, "dumpsys", "-t", "30", "activity", "provider", "all", NULL);
1117
1118
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");
1125 }
1126
1127 static void usage() {
1128   fprintf(stderr,
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());
1148 }
1149
1150 static void sigpipe_handler(int n) {
1151     // don't complain to stderr or stdout
1152     _exit(EXIT_FAILURE);
1153 }
1154
1155 /* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1156    temporary file.
1157  */
1158 static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
1159         time_t now) {
1160     if (!add_zip_entry(bugreport_name, bugreport_path)) {
1161         MYLOGE("Failed to add text entry to .zip file\n");
1162         return false;
1163     }
1164     if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
1165         MYLOGE("Failed to add main_entry.txt to .zip file\n");
1166         return false;
1167     }
1168
1169     int32_t err = zip_writer->Finish();
1170     if (err) {
1171         MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
1172         return false;
1173     }
1174
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));
1179         }
1180     } else {
1181         MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1182     }
1183
1184     return true;
1185 }
1186
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
1189             | O_NOFOLLOW)));
1190     if (fd.get() == -1) {
1191         MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
1192         return NULL;
1193     }
1194
1195     SHA256_CTX ctx;
1196     SHA256_init(&ctx);
1197
1198     std::vector<uint8_t> buffer(65536);
1199     while (1) {
1200         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1201         if (bytes_read == 0) {
1202             break;
1203         } else if (bytes_read == -1) {
1204             MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
1205             return NULL;
1206         }
1207
1208         SHA256_update(&ctx, buffer.data(), bytes_read);
1209     }
1210
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]);
1216     }
1217     hash_buffer[sizeof(hash_buffer) - 1] = 0;
1218     return std::string(hash_buffer);
1219 }
1220
1221 int main(int argc, char *argv[]) {
1222     struct sigaction sigact;
1223     int do_add_date = 0;
1224     int do_zip_file = 0;
1225     int do_vibrate = 1;
1226     char* use_outfile = 0;
1227     int use_socket = 0;
1228     int use_control_socket = 0;
1229     int do_fb = 0;
1230     int do_broadcast = 0;
1231     int do_early_screenshot = 0;
1232     int is_remote_mode = 0;
1233     std::string version = VERSION_DEFAULT;
1234
1235     now = time(NULL);
1236
1237     MYLOGI("begin\n");
1238
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);
1246
1247     /* clear SIGPIPE handler */
1248     memset(&sigact, 0, sizeof(sigact));
1249     sigact.sa_handler = sigpipe_handler;
1250     sigaction(SIGPIPE, &sigact, NULL);
1251
1252     /* set as high priority, and protect from OOM killer */
1253     setpriority(PRIO_PROCESS, 0, -20);
1254
1255     FILE *oom_adj = fopen("/proc/self/oom_score_adj", "we");
1256     if (oom_adj) {
1257         fputs("-1000", oom_adj);
1258         fclose(oom_adj);
1259     } else {
1260         /* fallback to kernels <= 2.6.35 */
1261         oom_adj = fopen("/proc/self/oom_adj", "we");
1262         if (oom_adj) {
1263             fputs("-17", oom_adj);
1264             fclose(oom_adj);
1265         }
1266     }
1267
1268     /* parse arguments */
1269     std::string args;
1270     format_args(argc, const_cast<const char **>(argv), &args);
1271     MYLOGD("Dumpstate command line: %s\n", args.c_str());
1272     int c;
1273     while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
1274         switch (c) {
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");
1288             case 'h':
1289                 usage();
1290                 exit(1);
1291         }
1292     }
1293
1294     if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) {
1295         usage();
1296         exit(1);
1297     }
1298
1299     if (use_control_socket && !do_zip_file) {
1300         usage();
1301         exit(1);
1302     }
1303
1304     if (do_update_progress && !do_broadcast) {
1305         usage();
1306         exit(1);
1307     }
1308
1309     if (is_remote_mode && (do_update_progress || !do_broadcast || !do_zip_file || !do_add_date)) {
1310         usage();
1311         exit(1);
1312     }
1313
1314     if (version != VERSION_DEFAULT) {
1315       usage();
1316       exit(1);
1317     }
1318
1319     MYLOGI("bugreport format version: %s\n", version.c_str());
1320
1321     do_early_screenshot = do_update_progress;
1322
1323     // If we are going to use a socket, do it as early as possible
1324     // to avoid timeouts from bugreport.
1325     if (use_socket) {
1326         redirect_to_socket(stdout, "dumpstate");
1327     }
1328
1329     if (use_control_socket) {
1330         MYLOGD("Opening control socket\n");
1331         control_socket_fd = open_socket("dumpstate");
1332         do_update_progress = 1;
1333     }
1334
1335     /* full path of the temporary file containing the bugreport */
1336     std::string tmp_path;
1337
1338     /* full path of the file containing the dumpstate logs*/
1339     std::string log_path;
1340
1341     /* full path of the systrace file, when enabled */
1342     std::string systrace_path;
1343
1344     /* full path of the temporary file containing the screenshot (when requested) */
1345     std::string screenshot_path;
1346
1347     /* base name (without suffix or extensions) of the bugreport files */
1348     std::string base_name;
1349
1350     /* pointer to the actual path, be it zip or text */
1351     std::string path;
1352
1353     /* pointer to the zipped file */
1354     std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
1355
1356     /* redirect output if needed */
1357     bool is_redirecting = !use_socket && use_outfile;
1358
1359     if (is_redirecting) {
1360         bugreport_dir = dirname(use_outfile);
1361         base_name = basename(use_outfile);
1362         if (do_add_date) {
1363             char date[80];
1364             strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1365             suffix = date;
1366         } else {
1367             suffix = "undated";
1368         }
1369         char build_id[PROPERTY_VALUE_MAX];
1370         property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
1371         base_name = base_name + "-" + build_id;
1372         if (do_fb) {
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";
1377         }
1378         tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
1379         log_path = bugreport_dir + "/dumpstate_log-" + suffix + "-"
1380                 + std::to_string(getpid()) + ".txt";
1381
1382         MYLOGD("Bugreport dir: %s\n"
1383                 "Base name: %s\n"
1384                 "Suffix: %s\n"
1385                 "Log path: %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());
1390
1391         if (do_zip_file) {
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"));
1396             if (!zip_file) {
1397                 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
1398                 do_zip_file = 0;
1399             } else {
1400                 zip_writer.reset(new ZipWriter(zip_file.get()));
1401             }
1402             add_text_zip_entry("version.txt", version);
1403         }
1404
1405         if (do_update_progress) {
1406             if (do_broadcast) {
1407                 // clang-format off
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),
1414                 };
1415                 // clang-format on
1416                 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1417             }
1418             if (use_control_socket) {
1419                 dprintf(control_socket_fd, "BEGIN:%s\n", path.c_str());
1420             }
1421         }
1422     }
1423
1424     /* read /proc/cmdline before dropping root */
1425     FILE *cmdline = fopen("/proc/cmdline", "re");
1426     if (cmdline) {
1427         fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1428         fclose(cmdline);
1429     }
1430
1431     /* open the vibrator before dropping root */
1432     std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
1433     if (do_vibrate) {
1434         vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
1435         if (vibrator) {
1436             vibrate(vibrator.get(), 150);
1437         }
1438     }
1439
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");
1444         } else {
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));
1451             }
1452         }
1453     }
1454
1455     if (do_zip_file) {
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));
1458         }
1459     }
1460
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));
1466         }
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));
1474         }
1475     }
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);
1480
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
1483     // the raw trace.
1484     if (!dump_anrd_trace()) {
1485         dump_systrace();
1486     }
1487
1488     // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1489     dump_raft();
1490
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);
1495
1496     /* collect stack traces from Dalvik and native processes (needs root) */
1497     dump_traces_path = dump_traces();
1498
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);
1507     }
1508     add_mountinfo();
1509     dump_iptables();
1510
1511     if (!drop_root_user()) {
1512         return -1;
1513     }
1514
1515     dumpstate(do_early_screenshot ? "": screenshot_path, version);
1516
1517     /* close output if needed */
1518     if (is_redirecting) {
1519         fclose(stdout);
1520     }
1521
1522     /* rename or zip the (now complete) .tmp file to its final location */
1523     if (use_outfile) {
1524
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;
1531         if (value[0]) {
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;
1536             } else {
1537                 MYLOGE("invalid suffix provided by user: %s\n", value);
1538             }
1539         }
1540         if (change_suffix) {
1541             MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), value);
1542             suffix = 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));
1549                 } else {
1550                     screenshot_path = new_screenshot_path;
1551                 }
1552             }
1553         }
1554
1555         bool do_text_file = true;
1556         if (do_zip_file) {
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;
1562             } else {
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));
1571                     } else {
1572                         path = new_path;
1573                     }
1574                 }
1575             }
1576         }
1577         if (do_text_file) {
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));
1582                 path.clear();
1583             }
1584         }
1585         if (use_control_socket) {
1586             if (do_text_file) {
1587                 dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
1588                         "for more details\n", log_path.c_str());
1589             } else {
1590                 dprintf(control_socket_fd, "OK:%s\n", path.c_str());
1591             }
1592         }
1593     }
1594
1595     /* vibrate a few but shortly times to let user know it's finished */
1596     if (vibrator) {
1597         for (int i = 0; i < 3; i++) {
1598             vibrate(vibrator.get(), 75);
1599             usleep((75 + 50) * 1000);
1600         }
1601     }
1602
1603     /* tell activity manager we're done */
1604     if (do_broadcast) {
1605         if (!path.empty()) {
1606             MYLOGI("Final bugreport path: %s\n", path.c_str());
1607             // clang-format off
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
1615             };
1616             // clang-format on
1617             if (do_fb) {
1618                 am_args.push_back("--es");
1619                 am_args.push_back("android.intent.extra.SCREENSHOT");
1620                 am_args.push_back(screenshot_path);
1621             }
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);
1627             } else {
1628                 send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
1629             }
1630         } else {
1631             MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
1632         }
1633     }
1634
1635     MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
1636     MYLOGI("done\n");
1637
1638     if (is_redirecting) {
1639         fclose(stderr);
1640     }
1641
1642     if (use_control_socket && control_socket_fd != -1) {
1643       MYLOGD("Closing control socket\n");
1644       close(control_socket_fd);
1645     }
1646
1647     return 0;
1648 }