OSDN Git Service

Check and restorecon cache/code_cache directories. am: 397ec26675
[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     }
461 }
462
463 static bool skip_not_stat(const char *path) {
464     static const char stat[] = "/stat";
465     size_t len = strlen(path);
466     if (path[len - 1] == '/') { /* Directory? */
467         return false;
468     }
469     return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
470 }
471
472 static bool skip_none(const char *path) {
473     return false;
474 }
475
476 static const char mmcblk0[] = "/sys/block/mmcblk0/";
477 unsigned long worst_write_perf = 20000; /* in KB/s */
478
479 //
480 //  stat offsets
481 // Name            units         description
482 // ----            -----         -----------
483 // read I/Os       requests      number of read I/Os processed
484 #define __STAT_READ_IOS      0
485 // read merges     requests      number of read I/Os merged with in-queue I/O
486 #define __STAT_READ_MERGES   1
487 // read sectors    sectors       number of sectors read
488 #define __STAT_READ_SECTORS  2
489 // read ticks      milliseconds  total wait time for read requests
490 #define __STAT_READ_TICKS    3
491 // write I/Os      requests      number of write I/Os processed
492 #define __STAT_WRITE_IOS     4
493 // write merges    requests      number of write I/Os merged with in-queue I/O
494 #define __STAT_WRITE_MERGES  5
495 // write sectors   sectors       number of sectors written
496 #define __STAT_WRITE_SECTORS 6
497 // write ticks     milliseconds  total wait time for write requests
498 #define __STAT_WRITE_TICKS   7
499 // in_flight       requests      number of I/Os currently in flight
500 #define __STAT_IN_FLIGHT     8
501 // io_ticks        milliseconds  total time this block device has been active
502 #define __STAT_IO_TICKS      9
503 // time_in_queue   milliseconds  total wait time for all requests
504 #define __STAT_IN_QUEUE     10
505 #define __STAT_NUMBER_FIELD 11
506 //
507 // read I/Os, write I/Os
508 // =====================
509 //
510 // These values increment when an I/O request completes.
511 //
512 // read merges, write merges
513 // =========================
514 //
515 // These values increment when an I/O request is merged with an
516 // already-queued I/O request.
517 //
518 // read sectors, write sectors
519 // ===========================
520 //
521 // These values count the number of sectors read from or written to this
522 // block device.  The "sectors" in question are the standard UNIX 512-byte
523 // sectors, not any device- or filesystem-specific block size.  The
524 // counters are incremented when the I/O completes.
525 #define SECTOR_SIZE 512
526 //
527 // read ticks, write ticks
528 // =======================
529 //
530 // These values count the number of milliseconds that I/O requests have
531 // waited on this block device.  If there are multiple I/O requests waiting,
532 // these values will increase at a rate greater than 1000/second; for
533 // example, if 60 read requests wait for an average of 30 ms, the read_ticks
534 // field will increase by 60*30 = 1800.
535 //
536 // in_flight
537 // =========
538 //
539 // This value counts the number of I/O requests that have been issued to
540 // the device driver but have not yet completed.  It does not include I/O
541 // requests that are in the queue but not yet issued to the device driver.
542 //
543 // io_ticks
544 // ========
545 //
546 // This value counts the number of milliseconds during which the device has
547 // had I/O requests queued.
548 //
549 // time_in_queue
550 // =============
551 //
552 // This value counts the number of milliseconds that I/O requests have waited
553 // on this block device.  If there are multiple I/O requests waiting, this
554 // value will increase as the product of the number of milliseconds times the
555 // number of requests waiting (see "read ticks" above for an example).
556 #define S_TO_MS 1000
557 //
558
559 static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
560     unsigned long long fields[__STAT_NUMBER_FIELD];
561     bool z;
562     char *cp, *buffer = NULL;
563     size_t i = 0;
564     FILE *fp = fdopen(fd, "rb");
565     getline(&buffer, &i, fp);
566     fclose(fp);
567     if (!buffer) {
568         return -errno;
569     }
570     i = strlen(buffer);
571     while ((i > 0) && (buffer[i - 1] == '\n')) {
572         buffer[--i] = '\0';
573     }
574     if (!*buffer) {
575         free(buffer);
576         return 0;
577     }
578     z = true;
579     for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
580         fields[i] = strtoull(cp, &cp, 10);
581         if (fields[i] != 0) {
582             z = false;
583         }
584     }
585     if (z) { /* never accessed */
586         free(buffer);
587         return 0;
588     }
589
590     if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
591         path += sizeof(mmcblk0) - 1;
592     }
593
594     printf("%s: %s\n", path, buffer);
595     free(buffer);
596
597     if (fields[__STAT_IO_TICKS]) {
598         unsigned long read_perf = 0;
599         unsigned long read_ios = 0;
600         if (fields[__STAT_READ_TICKS]) {
601             unsigned long long divisor = fields[__STAT_READ_TICKS]
602                                        * fields[__STAT_IO_TICKS];
603             read_perf = ((unsigned long long)SECTOR_SIZE
604                            * fields[__STAT_READ_SECTORS]
605                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
606                                         / divisor;
607             read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
608                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
609                                         / divisor;
610         }
611
612         unsigned long write_perf = 0;
613         unsigned long write_ios = 0;
614         if (fields[__STAT_WRITE_TICKS]) {
615             unsigned long long divisor = fields[__STAT_WRITE_TICKS]
616                                        * fields[__STAT_IO_TICKS];
617             write_perf = ((unsigned long long)SECTOR_SIZE
618                            * fields[__STAT_WRITE_SECTORS]
619                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
620                                         / divisor;
621             write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
622                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
623                                         / divisor;
624         }
625
626         unsigned queue = (fields[__STAT_IN_QUEUE]
627                              + (fields[__STAT_IO_TICKS] >> 1))
628                                  / fields[__STAT_IO_TICKS];
629
630         if (!write_perf && !write_ios) {
631             printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
632                    path, read_perf, read_ios, queue);
633         } else {
634             printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
635                    path, read_perf, read_ios, write_perf, write_ios, queue);
636         }
637
638         /* bugreport timeout factor adjustment */
639         if ((write_perf > 1) && (write_perf < worst_write_perf)) {
640             worst_write_perf = write_perf;
641         }
642     }
643     return 0;
644 }
645
646 /* Copied policy from system/core/logd/LogBuffer.cpp */
647
648 #define LOG_BUFFER_SIZE (256 * 1024)
649 #define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
650 #define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
651
652 static bool valid_size(unsigned long value) {
653     if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
654         return false;
655     }
656
657     long pages = sysconf(_SC_PHYS_PAGES);
658     if (pages < 1) {
659         return true;
660     }
661
662     long pagesize = sysconf(_SC_PAGESIZE);
663     if (pagesize <= 1) {
664         pagesize = PAGE_SIZE;
665     }
666
667     // maximum memory impact a somewhat arbitrary ~3%
668     pages = (pages + 31) / 32;
669     unsigned long maximum = pages * pagesize;
670
671     if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
672         return true;
673     }
674
675     return value <= maximum;
676 }
677
678 static unsigned long property_get_size(const char *key) {
679     unsigned long value;
680     char *cp, property[PROPERTY_VALUE_MAX];
681
682     property_get(key, property, "");
683     value = strtoul(property, &cp, 10);
684
685     switch(*cp) {
686     case 'm':
687     case 'M':
688         value *= 1024;
689     /* FALLTHRU */
690     case 'k':
691     case 'K':
692         value *= 1024;
693     /* FALLTHRU */
694     case '\0':
695         break;
696
697     default:
698         value = 0;
699     }
700
701     if (!valid_size(value)) {
702         value = 0;
703     }
704
705     return value;
706 }
707
708 /* timeout in ms */
709 static unsigned long logcat_timeout(const char *name) {
710     static const char global_tuneable[] = "persist.logd.size"; // Settings App
711     static const char global_default[] = "ro.logd.size";       // BoardConfig.mk
712     char key[PROP_NAME_MAX];
713     unsigned long property_size, default_size;
714
715     default_size = property_get_size(global_tuneable);
716     if (!default_size) {
717         default_size = property_get_size(global_default);
718     }
719
720     snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
721     property_size = property_get_size(key);
722
723     if (!property_size) {
724         snprintf(key, sizeof(key), "%s.%s", global_default, name);
725         property_size = property_get_size(key);
726     }
727
728     if (!property_size) {
729         property_size = default_size;
730     }
731
732     if (!property_size) {
733         property_size = LOG_BUFFER_SIZE;
734     }
735
736     /* Engineering margin is ten-fold our guess */
737     return 10 * (property_size + worst_write_perf) / worst_write_perf;
738 }
739
740 /* End copy from system/core/logd/LogBuffer.cpp */
741
742 /* dumps the current system state to stdout */
743 static void print_header(std::string version) {
744     char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
745     char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
746     char network[PROPERTY_VALUE_MAX], date[80];
747
748     property_get("ro.build.display.id", build, "(unknown)");
749     property_get("ro.build.fingerprint", fingerprint, "(unknown)");
750     property_get("ro.build.type", build_type, "(unknown)");
751     property_get("gsm.version.baseband", radio, "(unknown)");
752     property_get("ro.bootloader", bootloader, "(unknown)");
753     property_get("gsm.operator.alpha", network, "(unknown)");
754     strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
755
756     printf("========================================================\n");
757     printf("== dumpstate: %s\n", date);
758     printf("========================================================\n");
759
760     printf("\n");
761     printf("Build: %s\n", build);
762     printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */
763     printf("Bootloader: %s\n", bootloader);
764     printf("Radio: %s\n", radio);
765     printf("Network: %s\n", network);
766
767     printf("Kernel: ");
768     dump_file(NULL, "/proc/version");
769     printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
770     printf("Bugreport format version: %s\n", version.c_str());
771     printf("Dumpstate info: id=%lu pid=%d\n", id, getpid());
772     printf("\n");
773 }
774
775 // List of file extensions that can cause a zip file attachment to be rejected by some email
776 // service providers.
777 static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
778       ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
779       ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
780       ".shb", ".sys", ".vb",  ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
781 };
782
783 bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
784     if (!is_zipping()) {
785         MYLOGD("Not adding entry %s from fd because dumpstate is not zipping\n",
786                 entry_name.c_str());
787         return false;
788     }
789     std::string valid_name = entry_name;
790
791     // Rename extension if necessary.
792     size_t idx = entry_name.rfind(".");
793     if (idx != std::string::npos) {
794         std::string extension = entry_name.substr(idx);
795         std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
796         if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
797             valid_name = entry_name + ".renamed";
798             MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
799         }
800     }
801
802     // Logging statement  below is useful to time how long each entry takes, but it's too verbose.
803     // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
804     int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(),
805             ZipWriter::kCompress, get_mtime(fd, now));
806     if (err) {
807         MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
808                 ZipWriter::ErrorCodeString(err));
809         return false;
810     }
811
812     std::vector<uint8_t> buffer(65536);
813     while (1) {
814         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), sizeof(buffer)));
815         if (bytes_read == 0) {
816             break;
817         } else if (bytes_read == -1) {
818             MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
819             return false;
820         }
821         err = zip_writer->WriteBytes(buffer.data(), bytes_read);
822         if (err) {
823             MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
824             return false;
825         }
826     }
827
828     err = zip_writer->FinishEntry();
829     if (err) {
830         MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
831         return false;
832     }
833
834     return true;
835 }
836
837 bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
838     ScopedFd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
839     if (fd.get() == -1) {
840         MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
841         return false;
842     }
843
844     return add_zip_entry_from_fd(entry_name, fd.get());
845 }
846
847 /* adds a file to the existing zipped bugreport */
848 static int _add_file_from_fd(const char *title, const char *path, int fd) {
849     return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
850 }
851
852 // TODO: move to util.cpp
853 void add_dir(const char *dir, bool recursive) {
854     if (!is_zipping()) {
855         MYLOGD("Not adding dir %s because dumpstate is not zipping\n", dir);
856         return;
857     }
858     MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive);
859     DurationReporter duration_reporter(dir, NULL);
860     dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd);
861 }
862
863 bool is_zipping() {
864     return zip_writer != nullptr;
865 }
866
867 /* adds a text entry entry to the existing zip file. */
868 static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
869     if (!is_zipping()) {
870         MYLOGD("Not adding text entry %s because dumpstate is not zipping\n", entry_name.c_str());
871         return false;
872     }
873     MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
874     int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
875     if (err) {
876         MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
877                 ZipWriter::ErrorCodeString(err));
878         return false;
879     }
880
881     err = zip_writer->WriteBytes(content.c_str(), content.length());
882     if (err) {
883         MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
884                 ZipWriter::ErrorCodeString(err));
885         return false;
886     }
887
888     err = zip_writer->FinishEntry();
889     if (err) {
890         MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
891         return false;
892     }
893
894     return true;
895 }
896
897 static void dump_iptables() {
898     run_command("IPTABLES", 10, "iptables", "-L", "-nvx", NULL);
899     run_command("IP6TABLES", 10, "ip6tables", "-L", "-nvx", NULL);
900     run_command("IPTABLES NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL);
901     /* no ip6 nat */
902     run_command("IPTABLES MANGLE", 10, "iptables", "-t", "mangle", "-L", "-nvx", NULL);
903     run_command("IP6TABLES MANGLE", 10, "ip6tables", "-t", "mangle", "-L", "-nvx", NULL);
904     run_command("IPTABLES RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL);
905     run_command("IP6TABLES RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
906 }
907
908 static void dumpstate(const std::string& screenshot_path, const std::string& version) {
909     DurationReporter duration_reporter("DUMPSTATE");
910     unsigned long timeout;
911
912     dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
913     run_command("UPTIME", 10, "uptime", NULL);
914     dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
915     dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
916     dump_file("MEMORY INFO", "/proc/meminfo");
917     run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-H", NULL);
918     run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
919     dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
920     dump_file("VMALLOC INFO", "/proc/vmallocinfo");
921     dump_file("SLAB INFO", "/proc/slabinfo");
922     dump_file("ZONEINFO", "/proc/zoneinfo");
923     dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
924     dump_file("BUDDYINFO", "/proc/buddyinfo");
925     dump_file("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
926
927     dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
928     dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
929     dump_file("KERNEL SYNC", "/d/sync");
930
931     run_command("PROCESSES AND THREADS", 10, "ps", "-Z", "-t", "-p", "-P", NULL);
932     run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
933
934     run_command("PRINTENV", 10, "printenv", NULL);
935     run_command("NETSTAT", 10, "netstat", "-n", NULL);
936     run_command("LSMOD", 10, "lsmod", NULL);
937
938     do_dmesg();
939
940     run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
941     for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
942     for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
943     for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
944
945     if (!screenshot_path.empty()) {
946         MYLOGI("taking late screenshot\n");
947         take_screenshot(screenshot_path);
948         MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
949     }
950
951     // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
952     // calculate timeout
953     timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
954     if (timeout < 20000) {
955         timeout = 20000;
956     }
957     run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
958                                                         "-v", "printable",
959                                                         "-d",
960                                                         "*:v", NULL);
961     timeout = logcat_timeout("events");
962     if (timeout < 20000) {
963         timeout = 20000;
964     }
965     run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
966                                                        "-v", "threadtime",
967                                                        "-v", "printable",
968                                                        "-d",
969                                                        "*:v", NULL);
970     timeout = logcat_timeout("radio");
971     if (timeout < 20000) {
972         timeout = 20000;
973     }
974     run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
975                                                        "-v", "threadtime",
976                                                        "-v", "printable",
977                                                        "-d",
978                                                        "*:v", NULL);
979
980     run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
981
982     /* show the traces we collected in main(), if that was done */
983     if (dump_traces_path != NULL) {
984         dump_file("VM TRACES JUST NOW", dump_traces_path);
985     }
986
987     /* only show ANR traces if they're less than 15 minutes old */
988     struct stat st;
989     char anr_traces_path[PATH_MAX];
990     property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
991     if (!anr_traces_path[0]) {
992         printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
993     } else {
994       int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
995                                        O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
996       if (fd < 0) {
997           printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
998       } else {
999           dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
1000       }
1001     }
1002
1003     /* slow traces for slow operations */
1004     if (anr_traces_path[0] != 0) {
1005         int tail = strlen(anr_traces_path)-1;
1006         while (tail > 0 && anr_traces_path[tail] != '/') {
1007             tail--;
1008         }
1009         int i = 0;
1010         while (1) {
1011             sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
1012             if (stat(anr_traces_path, &st)) {
1013                 // No traces file at this index, done with the files.
1014                 break;
1015             }
1016             dump_file("VM TRACES WHEN SLOW", anr_traces_path);
1017             i++;
1018         }
1019     }
1020
1021     int dumped = 0;
1022     for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
1023         if (tombstone_data[i].fd != -1) {
1024             const char *name = tombstone_data[i].name;
1025             int fd = tombstone_data[i].fd;
1026             dumped = 1;
1027             if (zip_writer) {
1028                 if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
1029                     MYLOGE("Unable to add tombstone %s to zip file\n", name);
1030                 }
1031             } else {
1032                 dump_file_from_fd("TOMBSTONE", name, fd);
1033             }
1034             close(fd);
1035             tombstone_data[i].fd = -1;
1036         }
1037     }
1038     if (!dumped) {
1039         printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
1040     }
1041
1042     dump_file("NETWORK DEV INFO", "/proc/net/dev");
1043     dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1044     dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1045     dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1046     dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1047
1048     if (!stat(PSTORE_LAST_KMSG, &st)) {
1049         /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
1050         dump_file("LAST KMSG", PSTORE_LAST_KMSG);
1051     } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
1052         dump_file("LAST KMSG", ALT_PSTORE_LAST_KMSG);
1053     } else {
1054         /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
1055         dump_file("LAST KMSG", "/proc/last_kmsg");
1056     }
1057
1058     /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
1059     run_command("LAST LOGCAT", 10, "logcat", "-L",
1060                                              "-b", "all",
1061                                              "-v", "threadtime",
1062                                              "-v", "printable",
1063                                              "-d",
1064                                              "*:v", NULL);
1065
1066     /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1067
1068     run_command("NETWORK INTERFACES", 10, "ip", "link", NULL);
1069
1070     run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL);
1071     run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL);
1072
1073     run_command("IP RULES", 10, "ip", "rule", "show", NULL);
1074     run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
1075
1076     dump_route_tables();
1077
1078     run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
1079     run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
1080     run_command("MULTICAST ADDRESSES", 10, "ip", "maddr", NULL);
1081     run_command("WIFI NETWORKS", 20, "wpa_cli", "IFNAME=wlan0", "list_networks", NULL);
1082
1083 #ifdef FWDUMP_bcmdhd
1084     run_command("ND OFFLOAD TABLE", 5,
1085             SU_PATH, "root", WLUTIL, "nd_hostip", NULL);
1086
1087     run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
1088             SU_PATH, "root", WLUTIL, "counters", NULL);
1089
1090     run_command("ND OFFLOAD STATUS (1)", 5,
1091             SU_PATH, "root", WLUTIL, "nd_status", NULL);
1092
1093 #endif
1094     dump_file("INTERRUPTS (1)", "/proc/interrupts");
1095
1096     run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "-t", "10", "connectivity", "--diag", NULL);
1097
1098 #ifdef FWDUMP_bcmdhd
1099     run_command("DUMP WIFI STATUS", 20,
1100             SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
1101
1102     run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
1103             SU_PATH, "root", WLUTIL, "counters", NULL);
1104
1105     run_command("ND OFFLOAD STATUS (2)", 5,
1106             SU_PATH, "root", WLUTIL, "nd_status", NULL);
1107 #endif
1108     dump_file("INTERRUPTS (2)", "/proc/interrupts");
1109
1110     print_properties();
1111
1112     run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
1113     run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
1114
1115     run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);
1116
1117     run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
1118
1119     printf("------ BACKLIGHTS ------\n");
1120     printf("LCD brightness=");
1121     dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness");
1122     printf("Button brightness=");
1123     dump_file(NULL, "/sys/class/leds/button-backlight/brightness");
1124     printf("Keyboard brightness=");
1125     dump_file(NULL, "/sys/class/leds/keyboard-backlight/brightness");
1126     printf("ALS mode=");
1127     dump_file(NULL, "/sys/class/leds/lcd-backlight/als");
1128     printf("LCD driver registers:\n");
1129     dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
1130     printf("\n");
1131
1132     /* Binder state is expensive to look at as it uses a lot of memory. */
1133     dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1134     dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1135     dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1136     dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
1137     dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
1138
1139     printf("========================================================\n");
1140     printf("== Board\n");
1141     printf("========================================================\n");
1142
1143     dumpstate_board();
1144     printf("\n");
1145
1146     /* Migrate the ril_dumpstate to a dumpstate_board()? */
1147     char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
1148     property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
1149     if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
1150         if (is_user_build()) {
1151             // su does not exist on user builds, so try running without it.
1152             // This way any implementations of vril-dump that do not require
1153             // root can run on user builds.
1154             run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
1155                     "vril-dump", NULL);
1156         } else {
1157             run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
1158                     SU_PATH, "root", "vril-dump", NULL);
1159         }
1160     }
1161
1162     printf("========================================================\n");
1163     printf("== Android Framework Services\n");
1164     printf("========================================================\n");
1165
1166     run_command("DUMPSYS", 60, "dumpsys", "-t", "60", "--skip", "meminfo", "cpuinfo", NULL);
1167
1168     printf("========================================================\n");
1169     printf("== Checkins\n");
1170     printf("========================================================\n");
1171
1172     run_command("CHECKIN BATTERYSTATS", 30, "dumpsys", "-t", "30", "batterystats", "-c", NULL);
1173     run_command("CHECKIN MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "--checkin", NULL);
1174     run_command("CHECKIN NETSTATS", 30, "dumpsys", "-t", "30", "netstats", "--checkin", NULL);
1175     run_command("CHECKIN PROCSTATS", 30, "dumpsys", "-t", "30", "procstats", "-c", NULL);
1176     run_command("CHECKIN USAGESTATS", 30, "dumpsys", "-t", "30", "usagestats", "-c", NULL);
1177     run_command("CHECKIN PACKAGE", 30, "dumpsys", "-t", "30", "package", "--checkin", NULL);
1178
1179     printf("========================================================\n");
1180     printf("== Running Application Activities\n");
1181     printf("========================================================\n");
1182
1183     run_command("APP ACTIVITIES", 30, "dumpsys", "-t", "30", "activity", "all", NULL);
1184
1185     printf("========================================================\n");
1186     printf("== Running Application Services\n");
1187     printf("========================================================\n");
1188
1189     run_command("APP SERVICES", 30, "dumpsys", "-t", "30", "activity", "service", "all", NULL);
1190
1191     printf("========================================================\n");
1192     printf("== Running Application Providers\n");
1193     printf("========================================================\n");
1194
1195     run_command("APP PROVIDERS", 30, "dumpsys", "-t", "30", "activity", "provider", "all", NULL);
1196
1197     // dump_modem_logs adds the modem logs if available to the bugreport.
1198     // Do this at the end to allow for sufficient time for the modem logs to be
1199     // collected.
1200     dump_modem_logs();
1201
1202     printf("========================================================\n");
1203     printf("== Final progress (pid %d): %d/%d (originally %d)\n",
1204             getpid(), progress, weight_total, WEIGHT_TOTAL);
1205     printf("========================================================\n");
1206     printf("== dumpstate: done\n");
1207     printf("========================================================\n");
1208 }
1209
1210 static void usage() {
1211   fprintf(stderr,
1212           "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
1213           "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1214           "  -h: display this help message\n"
1215           "  -b: play sound file instead of vibrate, at beginning of job\n"
1216           "  -e: play sound file instead of vibrate, at end of job\n"
1217           "  -o: write to file (instead of stdout)\n"
1218           "  -d: append date to filename (requires -o)\n"
1219           "  -p: capture screenshot to filename.png (requires -o)\n"
1220           "  -z: generate zipped file (requires -o)\n"
1221           "  -s: write output to control socket (for init)\n"
1222           "  -S: write file location to control socket (for init; requires -o and -z)"
1223           "  -q: disable vibrate\n"
1224           "  -B: send broadcast when finished (requires -o)\n"
1225           "  -P: send broadcast when started and update system properties on "
1226           "progress (requires -o and -B)\n"
1227           "  -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1228           "shouldn't be used with -P)\n"
1229           "  -V: sets the bugreport format version (valid values: %s)\n",
1230           VERSION_DEFAULT.c_str());
1231 }
1232
1233 static void sigpipe_handler(int n) {
1234     // don't complain to stderr or stdout
1235     _exit(EXIT_FAILURE);
1236 }
1237
1238 /* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1239    temporary file.
1240  */
1241 static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
1242         time_t now) {
1243     if (!add_zip_entry(bugreport_name, bugreport_path)) {
1244         MYLOGE("Failed to add text entry to .zip file\n");
1245         return false;
1246     }
1247     if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
1248         MYLOGE("Failed to add main_entry.txt to .zip file\n");
1249         return false;
1250     }
1251
1252     int32_t err = zip_writer->Finish();
1253     if (err) {
1254         MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
1255         return false;
1256     }
1257
1258     if (is_user_build()) {
1259         MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
1260         if (remove(bugreport_path.c_str())) {
1261             ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
1262         }
1263     } else {
1264         MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1265     }
1266
1267     return true;
1268 }
1269
1270 static std::string SHA256_file_hash(std::string filepath) {
1271     ScopedFd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC
1272             | O_NOFOLLOW)));
1273     if (fd.get() == -1) {
1274         MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
1275         return NULL;
1276     }
1277
1278     SHA256_CTX ctx;
1279     SHA256_init(&ctx);
1280
1281     std::vector<uint8_t> buffer(65536);
1282     while (1) {
1283         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1284         if (bytes_read == 0) {
1285             break;
1286         } else if (bytes_read == -1) {
1287             MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
1288             return NULL;
1289         }
1290
1291         SHA256_update(&ctx, buffer.data(), bytes_read);
1292     }
1293
1294     uint8_t hash[SHA256_DIGEST_SIZE];
1295     memcpy(hash, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
1296     char hash_buffer[SHA256_DIGEST_SIZE * 2 + 1];
1297     for(size_t i = 0; i < SHA256_DIGEST_SIZE; i++) {
1298         sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
1299     }
1300     hash_buffer[sizeof(hash_buffer) - 1] = 0;
1301     return std::string(hash_buffer);
1302 }
1303
1304 int main(int argc, char *argv[]) {
1305     struct sigaction sigact;
1306     int do_add_date = 0;
1307     int do_zip_file = 0;
1308     int do_vibrate = 1;
1309     char* use_outfile = 0;
1310     int use_socket = 0;
1311     int use_control_socket = 0;
1312     int do_fb = 0;
1313     int do_broadcast = 0;
1314     int do_early_screenshot = 0;
1315     int is_remote_mode = 0;
1316     std::string version = VERSION_DEFAULT;
1317
1318     now = time(NULL);
1319
1320     MYLOGI("begin\n");
1321
1322     /* gets the sequential id */
1323     char last_id[PROPERTY_VALUE_MAX];
1324     property_get("dumpstate.last_id", last_id, "0");
1325     id = strtoul(last_id, NULL, 10) + 1;
1326     snprintf(last_id, sizeof(last_id), "%lu", id);
1327     property_set("dumpstate.last_id", last_id);
1328     MYLOGI("dumpstate id: %lu\n", id);
1329
1330     /* clear SIGPIPE handler */
1331     memset(&sigact, 0, sizeof(sigact));
1332     sigact.sa_handler = sigpipe_handler;
1333     sigaction(SIGPIPE, &sigact, NULL);
1334
1335     /* set as high priority, and protect from OOM killer */
1336     setpriority(PRIO_PROCESS, 0, -20);
1337
1338     FILE *oom_adj = fopen("/proc/self/oom_score_adj", "we");
1339     if (oom_adj) {
1340         fputs("-1000", oom_adj);
1341         fclose(oom_adj);
1342     } else {
1343         /* fallback to kernels <= 2.6.35 */
1344         oom_adj = fopen("/proc/self/oom_adj", "we");
1345         if (oom_adj) {
1346             fputs("-17", oom_adj);
1347             fclose(oom_adj);
1348         }
1349     }
1350
1351     /* parse arguments */
1352     std::string args;
1353     format_args(argc, const_cast<const char **>(argv), &args);
1354     MYLOGD("Dumpstate command line: %s\n", args.c_str());
1355     int c;
1356     while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
1357         switch (c) {
1358             case 'd': do_add_date = 1;          break;
1359             case 'z': do_zip_file = 1;          break;
1360             case 'o': use_outfile = optarg;     break;
1361             case 's': use_socket = 1;           break;
1362             case 'S': use_control_socket = 1;   break;
1363             case 'v': break;  // compatibility no-op
1364             case 'q': do_vibrate = 0;           break;
1365             case 'p': do_fb = 1;                break;
1366             case 'P': do_update_progress = 1;   break;
1367             case 'R': is_remote_mode = 1;       break;
1368             case 'B': do_broadcast = 1;         break;
1369             case 'V': version = optarg;         break;
1370             case '?': printf("\n");
1371             case 'h':
1372                 usage();
1373                 exit(1);
1374         }
1375     }
1376
1377     if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) {
1378         usage();
1379         exit(1);
1380     }
1381
1382     if (use_control_socket && !do_zip_file) {
1383         usage();
1384         exit(1);
1385     }
1386
1387     if (do_update_progress && !do_broadcast) {
1388         usage();
1389         exit(1);
1390     }
1391
1392     if (is_remote_mode && (do_update_progress || !do_broadcast || !do_zip_file || !do_add_date)) {
1393         usage();
1394         exit(1);
1395     }
1396
1397     if (version != VERSION_DEFAULT) {
1398       usage();
1399       exit(1);
1400     }
1401
1402     MYLOGI("bugreport format version: %s\n", version.c_str());
1403
1404     do_early_screenshot = do_update_progress;
1405
1406     // If we are going to use a socket, do it as early as possible
1407     // to avoid timeouts from bugreport.
1408     if (use_socket) {
1409         redirect_to_socket(stdout, "dumpstate");
1410     }
1411
1412     if (use_control_socket) {
1413         MYLOGD("Opening control socket\n");
1414         control_socket_fd = open_socket("dumpstate");
1415         do_update_progress = 1;
1416     }
1417
1418     /* full path of the temporary file containing the bugreport */
1419     std::string tmp_path;
1420
1421     /* full path of the file containing the dumpstate logs*/
1422     std::string log_path;
1423
1424     /* full path of the systrace file, when enabled */
1425     std::string systrace_path;
1426
1427     /* full path of the temporary file containing the screenshot (when requested) */
1428     std::string screenshot_path;
1429
1430     /* base name (without suffix or extensions) of the bugreport files */
1431     std::string base_name;
1432
1433     /* pointer to the actual path, be it zip or text */
1434     std::string path;
1435
1436     /* pointer to the zipped file */
1437     std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
1438
1439     /* redirect output if needed */
1440     bool is_redirecting = !use_socket && use_outfile;
1441
1442     if (is_redirecting) {
1443         bugreport_dir = dirname(use_outfile);
1444         base_name = basename(use_outfile);
1445         if (do_add_date) {
1446             char date[80];
1447             strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1448             suffix = date;
1449         } else {
1450             suffix = "undated";
1451         }
1452         char build_id[PROPERTY_VALUE_MAX];
1453         property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
1454         base_name = base_name + "-" + build_id;
1455         if (do_fb) {
1456             // TODO: if dumpstate was an object, the paths could be internal variables and then
1457             // we could have a function to calculate the derived values, such as:
1458             //     screenshot_path = GetPath(".png");
1459             screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1460         }
1461         tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
1462         log_path = bugreport_dir + "/dumpstate_log-" + suffix + "-"
1463                 + std::to_string(getpid()) + ".txt";
1464
1465         MYLOGD("Bugreport dir: %s\n"
1466                 "Base name: %s\n"
1467                 "Suffix: %s\n"
1468                 "Log path: %s\n"
1469                 "Temporary path: %s\n"
1470                 "Screenshot path: %s\n",
1471                 bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(),
1472                 log_path.c_str(), tmp_path.c_str(), screenshot_path.c_str());
1473
1474         if (do_zip_file) {
1475             path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1476             MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
1477             create_parent_dirs(path.c_str());
1478             zip_file.reset(fopen(path.c_str(), "wb"));
1479             if (!zip_file) {
1480                 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
1481                 do_zip_file = 0;
1482             } else {
1483                 zip_writer.reset(new ZipWriter(zip_file.get()));
1484             }
1485             add_text_zip_entry("version.txt", version);
1486         }
1487
1488         if (do_update_progress) {
1489             if (do_broadcast) {
1490                 // clang-format off
1491                 std::vector<std::string> am_args = {
1492                      "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1493                      "--es", "android.intent.extra.NAME", suffix,
1494                      "--ei", "android.intent.extra.ID", std::to_string(id),
1495                      "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1496                      "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1497                 };
1498                 // clang-format on
1499                 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1500             }
1501             if (use_control_socket) {
1502                 dprintf(control_socket_fd, "BEGIN:%s\n", path.c_str());
1503             }
1504         }
1505     }
1506
1507     /* read /proc/cmdline before dropping root */
1508     FILE *cmdline = fopen("/proc/cmdline", "re");
1509     if (cmdline) {
1510         fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1511         fclose(cmdline);
1512     }
1513
1514     /* open the vibrator before dropping root */
1515     std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
1516     if (do_vibrate) {
1517         vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
1518         if (vibrator) {
1519             vibrate(vibrator.get(), 150);
1520         }
1521     }
1522
1523     if (do_fb && do_early_screenshot) {
1524         if (screenshot_path.empty()) {
1525             // should not have happened
1526             MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
1527         } else {
1528             MYLOGI("taking early screenshot\n");
1529             take_screenshot(screenshot_path);
1530             MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
1531             if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
1532                 MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
1533                         screenshot_path.c_str(), strerror(errno));
1534             }
1535         }
1536     }
1537
1538     if (do_zip_file) {
1539         if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
1540             MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
1541         }
1542     }
1543
1544     if (is_redirecting) {
1545         redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
1546         if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
1547             MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1548                     log_path.c_str(), strerror(errno));
1549         }
1550         /* TODO: rather than generating a text file now and zipping it later,
1551            it would be more efficient to redirect stdout to the zip entry
1552            directly, but the libziparchive doesn't support that option yet. */
1553         redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
1554         if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
1555             MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
1556                     tmp_path.c_str(), strerror(errno));
1557         }
1558     }
1559     // NOTE: there should be no stdout output until now, otherwise it would break the header.
1560     // In particular, DurationReport objects should be created passing 'title, NULL', so their
1561     // duration is logged into MYLOG instead.
1562     print_header(version);
1563
1564     // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1565     // First try to dump anrd trace if the daemon is running. Otherwise, dump
1566     // the raw trace.
1567     if (!dump_anrd_trace()) {
1568         dump_systrace();
1569     }
1570
1571     // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1572     dump_raft();
1573
1574     // Invoking the following dumpsys calls before dump_traces() to try and
1575     // keep the system stats as close to its initial state as possible.
1576     run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "-a", NULL);
1577     run_command_as_shell("DUMPSYS CPUINFO", 10, "dumpsys", "-t", "10", "cpuinfo", "-a", NULL);
1578
1579     /* collect stack traces from Dalvik and native processes (needs root) */
1580     dump_traces_path = dump_traces();
1581
1582     /* Run some operations that require root. */
1583     get_tombstone_fds(tombstone_data);
1584     add_dir(RECOVERY_DIR, true);
1585     add_dir(RECOVERY_DATA_DIR, true);
1586     add_dir(LOGPERSIST_DATA_DIR, false);
1587     if (!is_user_build()) {
1588         add_dir(PROFILE_DATA_DIR_CUR, true);
1589         add_dir(PROFILE_DATA_DIR_REF, true);
1590     }
1591     add_mountinfo();
1592     dump_iptables();
1593
1594     // Capture any IPSec policies in play.  No keys are exposed here.
1595     run_command("IP XFRM POLICY", 10, "ip", "xfrm", "policy", nullptr);
1596
1597     // Run ss as root so we can see socket marks.
1598     run_command("DETAILED SOCKET STATE", 10, "ss", "-eionptu", NULL);
1599
1600     if (!drop_root_user()) {
1601         return -1;
1602     }
1603
1604     dumpstate(do_early_screenshot ? "": screenshot_path, version);
1605
1606     /* close output if needed */
1607     if (is_redirecting) {
1608         fclose(stdout);
1609     }
1610
1611     /* rename or zip the (now complete) .tmp file to its final location */
1612     if (use_outfile) {
1613
1614         /* check if user changed the suffix using system properties */
1615         char key[PROPERTY_KEY_MAX];
1616         char value[PROPERTY_VALUE_MAX];
1617         snprintf(key, sizeof(key), "dumpstate.%d.name", getpid());
1618         property_get(key, value, "");
1619         bool change_suffix= false;
1620         if (value[0]) {
1621             /* must whitelist which characters are allowed, otherwise it could cross directories */
1622             std::regex valid_regex("^[-_a-zA-Z0-9]+$");
1623             if (std::regex_match(value, valid_regex)) {
1624                 change_suffix = true;
1625             } else {
1626                 MYLOGE("invalid suffix provided by user: %s\n", value);
1627             }
1628         }
1629         if (change_suffix) {
1630             MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), value);
1631             suffix = value;
1632             if (!screenshot_path.empty()) {
1633                 std::string new_screenshot_path =
1634                         bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1635                 if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
1636                     MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
1637                             new_screenshot_path.c_str(), strerror(errno));
1638                 } else {
1639                     screenshot_path = new_screenshot_path;
1640                 }
1641             }
1642         }
1643
1644         bool do_text_file = true;
1645         if (do_zip_file) {
1646             std::string entry_name = base_name + "-" + suffix + ".txt";
1647             MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
1648             if (!finish_zip_file(entry_name, tmp_path, now)) {
1649                 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
1650                 do_text_file = true;
1651             } else {
1652                 do_text_file = false;
1653                 // Since zip file is already created, it needs to be renamed.
1654                 std::string new_path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1655                 if (path != new_path) {
1656                     MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
1657                     if (rename(path.c_str(), new_path.c_str())) {
1658                         MYLOGE("rename(%s, %s): %s\n", path.c_str(),
1659                                 new_path.c_str(), strerror(errno));
1660                     } else {
1661                         path = new_path;
1662                     }
1663                 }
1664             }
1665         }
1666         if (do_text_file) {
1667             path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt";
1668             MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
1669             if (rename(tmp_path.c_str(), path.c_str())) {
1670                 MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
1671                 path.clear();
1672             }
1673         }
1674         if (use_control_socket) {
1675             if (do_text_file) {
1676                 dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
1677                         "for more details\n", log_path.c_str());
1678             } else {
1679                 dprintf(control_socket_fd, "OK:%s\n", path.c_str());
1680             }
1681         }
1682     }
1683
1684     /* vibrate a few but shortly times to let user know it's finished */
1685     if (vibrator) {
1686         for (int i = 0; i < 3; i++) {
1687             vibrate(vibrator.get(), 75);
1688             usleep((75 + 50) * 1000);
1689         }
1690     }
1691
1692     /* tell activity manager we're done */
1693     if (do_broadcast) {
1694         if (!path.empty()) {
1695             MYLOGI("Final bugreport path: %s\n", path.c_str());
1696             // clang-format off
1697             std::vector<std::string> am_args = {
1698                  "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1699                  "--ei", "android.intent.extra.ID", std::to_string(id),
1700                  "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1701                  "--ei", "android.intent.extra.MAX", std::to_string(weight_total),
1702                  "--es", "android.intent.extra.BUGREPORT", path,
1703                  "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
1704             };
1705             // clang-format on
1706             if (do_fb) {
1707                 am_args.push_back("--es");
1708                 am_args.push_back("android.intent.extra.SCREENSHOT");
1709                 am_args.push_back(screenshot_path);
1710             }
1711             if (is_remote_mode) {
1712                 am_args.push_back("--es");
1713                 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1714                 am_args.push_back(SHA256_file_hash(path));
1715                 send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1716             } else {
1717                 send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
1718             }
1719         } else {
1720             MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
1721         }
1722     }
1723
1724     MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
1725     MYLOGI("done\n");
1726
1727     if (is_redirecting) {
1728         fclose(stderr);
1729     }
1730
1731     if (use_control_socket && control_socket_fd != -1) {
1732       MYLOGD("Closing control socket\n");
1733       close(control_socket_fd);
1734     }
1735
1736     return 0;
1737 }