OSDN Git Service

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