Home | History | Annotate | Download | only in dumpstate
      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 #define LOG_TAG "dumpstate"
     18 
     19 #include <dirent.h>
     20 #include <errno.h>
     21 #include <fcntl.h>
     22 #include <libgen.h>
     23 #include <limits.h>
     24 #include <stdbool.h>
     25 #include <stdio.h>
     26 #include <stdlib.h>
     27 #include <string.h>
     28 #include <sys/prctl.h>
     29 #include <sys/resource.h>
     30 #include <sys/stat.h>
     31 #include <sys/time.h>
     32 #include <sys/wait.h>
     33 #include <unistd.h>
     34 #include <memory>
     35 #include <regex>
     36 #include <set>
     37 #include <string>
     38 #include <vector>
     39 
     40 #include <android-base/file.h>
     41 #include <android-base/properties.h>
     42 #include <android-base/stringprintf.h>
     43 #include <android-base/strings.h>
     44 #include <android-base/unique_fd.h>
     45 #include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
     46 #include <cutils/native_handle.h>
     47 #include <cutils/properties.h>
     48 #include <openssl/sha.h>
     49 #include <private/android_filesystem_config.h>
     50 #include <private/android_logger.h>
     51 
     52 #include "DumpstateInternal.h"
     53 #include "DumpstateService.h"
     54 #include "dumpstate.h"
     55 
     56 using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
     57 
     58 // TODO: remove once moved to namespace
     59 using android::os::dumpstate::CommandOptions;
     60 using android::os::dumpstate::DumpFileToFd;
     61 using android::os::dumpstate::PropertiesHelper;
     62 using android::os::dumpstate::GetPidByName;
     63 
     64 /* read before root is shed */
     65 static char cmdline_buf[16384] = "(unknown)";
     66 static const char *dump_traces_path = NULL;
     67 
     68 // TODO: variables and functions below should be part of dumpstate object
     69 
     70 static std::set<std::string> mount_points;
     71 void add_mountinfo();
     72 
     73 #define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
     74 #define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
     75 #define BLK_DEV_SYS_DIR "/sys/block"
     76 
     77 #define RAFT_DIR "/data/misc/raft"
     78 #define RECOVERY_DIR "/cache/recovery"
     79 #define RECOVERY_DATA_DIR "/data/misc/recovery"
     80 #define LOGPERSIST_DATA_DIR "/data/misc/logd"
     81 #define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
     82 #define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
     83 #define WLUTIL "/vendor/xbin/wlutil"
     84 
     85 // TODO(narayan): Since this information has to be kept in sync
     86 // with tombstoned, we should just put it in a common header.
     87 //
     88 // File: system/core/debuggerd/tombstoned/tombstoned.cpp
     89 static const std::string TOMBSTONE_DIR = "/data/tombstones/";
     90 static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
     91 static const std::string ANR_DIR = "/data/anr/";
     92 static const std::string ANR_FILE_PREFIX = "anr_";
     93 
     94 struct DumpData {
     95     std::string name;
     96     int fd;
     97     time_t mtime;
     98 };
     99 
    100 static bool operator<(const DumpData& d1, const DumpData& d2) {
    101     return d1.mtime > d2.mtime;
    102 }
    103 
    104 static std::unique_ptr<std::vector<DumpData>> tombstone_data;
    105 static std::unique_ptr<std::vector<DumpData>> anr_data;
    106 
    107 // TODO: temporary variables and functions used during C++ refactoring
    108 static Dumpstate& ds = Dumpstate::GetInstance();
    109 static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
    110                       const CommandOptions& options = CommandOptions::DEFAULT) {
    111     return ds.RunCommand(title, fullCommand, options);
    112 }
    113 static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
    114                        const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
    115                        long dumpsysTimeout = 0) {
    116     return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeout);
    117 }
    118 static int DumpFile(const std::string& title, const std::string& path) {
    119     return ds.DumpFile(title, path);
    120 }
    121 
    122 // Relative directory (inside the zip) for all files copied as-is into the bugreport.
    123 static const std::string ZIP_ROOT_DIR = "FS";
    124 
    125 // Must be hardcoded because dumpstate HAL implementation need SELinux access to it
    126 static const std::string kDumpstateBoardPath = "/bugreports/";
    127 static const std::string kDumpstateBoardFiles[] = {
    128     "dumpstate_board.txt",
    129     "dumpstate_board.bin"
    130 };
    131 static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
    132 
    133 static const std::string kLsHalDebugPath = "/bugreports/dumpstate_lshal.txt";
    134 
    135 static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
    136 static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
    137 static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
    138 static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
    139 static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
    140 
    141 static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
    142 
    143 /*
    144  * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
    145  * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
    146  * is set, the vector only contains files that were written in the last 30 minutes.
    147  * If |limit_by_count| is set, the vector only contains the ten latest files.
    148  */
    149 static std::vector<DumpData>* GetDumpFds(const std::string& dir_path,
    150                                          const std::string& file_prefix,
    151                                          bool limit_by_mtime,
    152                                          bool limit_by_count = true) {
    153     const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
    154 
    155     std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>());
    156     std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
    157 
    158     struct dirent* entry = nullptr;
    159     while ((entry = readdir(dump_dir.get()))) {
    160         if (entry->d_type != DT_REG) {
    161             continue;
    162         }
    163 
    164         const std::string base_name(entry->d_name);
    165         if (base_name.find(file_prefix) != 0) {
    166             continue;
    167         }
    168 
    169         const std::string abs_path = dir_path + base_name;
    170         android::base::unique_fd fd(
    171             TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
    172         if (fd == -1) {
    173             MYLOGW("Unable to open dump file: %s %s\n", abs_path.c_str(), strerror(errno));
    174             break;
    175         }
    176 
    177         struct stat st = {};
    178         if (fstat(fd, &st) == -1) {
    179             MYLOGW("Unable to stat dump file: %s %s\n", abs_path.c_str(), strerror(errno));
    180             continue;
    181         }
    182 
    183         if (limit_by_mtime && st.st_mtime >= thirty_minutes_ago) {
    184             MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
    185             continue;
    186         }
    187 
    188         DumpData data = {.name = abs_path, .fd = fd.release(), .mtime = st.st_mtime};
    189 
    190         dump_data->push_back(data);
    191     }
    192 
    193     std::sort(dump_data->begin(), dump_data->end());
    194 
    195     if (limit_by_count && dump_data->size() > 10) {
    196         dump_data->erase(dump_data->begin() + 10, dump_data->end());
    197     }
    198 
    199     return dump_data.release();
    200 }
    201 
    202 static bool AddDumps(const std::vector<DumpData>::const_iterator start,
    203                      const std::vector<DumpData>::const_iterator end,
    204                      const char* type_name, const bool add_to_zip) {
    205     bool dumped = false;
    206     for (auto it = start; it != end; ++it) {
    207         const std::string& name = it->name;
    208         const int fd = it->fd;
    209         dumped = true;
    210         if (ds.IsZipping() && add_to_zip) {
    211             if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) {
    212                 MYLOGE("Unable to add %s %s to zip file\n", name.c_str(), type_name);
    213             }
    214         } else {
    215             dump_file_from_fd(type_name, name.c_str(), fd);
    216         }
    217 
    218         close(fd);
    219     }
    220 
    221     return dumped;
    222 }
    223 
    224 // for_each_pid() callback to get mount info about a process.
    225 void do_mountinfo(int pid, const char* name __attribute__((unused))) {
    226     char path[PATH_MAX];
    227 
    228     // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
    229     // are added.
    230     snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
    231     char linkname[PATH_MAX];
    232     ssize_t r = readlink(path, linkname, PATH_MAX);
    233     if (r == -1) {
    234         MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
    235         return;
    236     }
    237     linkname[r] = '\0';
    238 
    239     if (mount_points.find(linkname) == mount_points.end()) {
    240         // First time this mount point was found: add it
    241         snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
    242         if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
    243             mount_points.insert(linkname);
    244         } else {
    245             MYLOGE("Unable to add mountinfo %s to zip file\n", path);
    246         }
    247     }
    248 }
    249 
    250 void add_mountinfo() {
    251     if (!ds.IsZipping()) return;
    252     std::string title = "MOUNT INFO";
    253     mount_points.clear();
    254     DurationReporter duration_reporter(title, true);
    255     for_each_pid(do_mountinfo, nullptr);
    256     MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
    257 }
    258 
    259 static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
    260 {
    261     DIR *d;
    262     struct dirent *de;
    263     char path[PATH_MAX];
    264 
    265     d = opendir(driverpath);
    266     if (d == NULL) {
    267         return;
    268     }
    269 
    270     while ((de = readdir(d))) {
    271         if (de->d_type != DT_LNK) {
    272             continue;
    273         }
    274         snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
    275         DumpFile(title, path);
    276     }
    277 
    278     closedir(d);
    279 }
    280 
    281 
    282 
    283 // dump anrd's trace and add to the zip file.
    284 // 1. check if anrd is running on this device.
    285 // 2. send a SIGUSR1 to its pid which will dump anrd's trace.
    286 // 3. wait until the trace generation completes and add to the zip file.
    287 static bool dump_anrd_trace() {
    288     unsigned int pid;
    289     char buf[50], path[PATH_MAX];
    290     struct dirent *trace;
    291     struct stat st;
    292     DIR *trace_dir;
    293     int retry = 5;
    294     long max_ctime = 0, old_mtime;
    295     long long cur_size = 0;
    296     const char *trace_path = "/data/misc/anrd/";
    297 
    298     if (!ds.IsZipping()) {
    299         MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
    300         return false;
    301     }
    302 
    303     // find anrd's pid if it is running.
    304     pid = GetPidByName("/system/xbin/anrd");
    305 
    306     if (pid > 0) {
    307         if (stat(trace_path, &st) == 0) {
    308             old_mtime = st.st_mtime;
    309         } else {
    310             MYLOGE("Failed to find: %s\n", trace_path);
    311             return false;
    312         }
    313 
    314         // send SIGUSR1 to the anrd to generate a trace.
    315         sprintf(buf, "%u", pid);
    316         if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
    317                        CommandOptions::WithTimeout(1).Build())) {
    318             MYLOGE("anrd signal timed out. Please manually collect trace\n");
    319             return false;
    320         }
    321 
    322         while (retry-- > 0 && old_mtime == st.st_mtime) {
    323             sleep(1);
    324             stat(trace_path, &st);
    325         }
    326 
    327         if (retry < 0 && old_mtime == st.st_mtime) {
    328             MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
    329             return false;
    330         }
    331 
    332         // identify the trace file by its creation time.
    333         if (!(trace_dir = opendir(trace_path))) {
    334             MYLOGE("Can't open trace file under %s\n", trace_path);
    335         }
    336         while ((trace = readdir(trace_dir))) {
    337             if (strcmp(trace->d_name, ".") == 0
    338                     || strcmp(trace->d_name, "..") == 0) {
    339                 continue;
    340             }
    341             sprintf(path, "%s%s", trace_path, trace->d_name);
    342             if (stat(path, &st) == 0) {
    343                 if (st.st_ctime > max_ctime) {
    344                     max_ctime = st.st_ctime;
    345                     sprintf(buf, "%s", trace->d_name);
    346                 }
    347             }
    348         }
    349         closedir(trace_dir);
    350 
    351         // Wait until the dump completes by checking the size of the trace.
    352         if (max_ctime > 0) {
    353             sprintf(path, "%s%s", trace_path, buf);
    354             while(true) {
    355                 sleep(1);
    356                 if (stat(path, &st) == 0) {
    357                     if (st.st_size == cur_size) {
    358                         break;
    359                     } else if (st.st_size > cur_size) {
    360                         cur_size = st.st_size;
    361                     } else {
    362                         return false;
    363                     }
    364                 } else {
    365                     MYLOGE("Cant stat() %s anymore\n", path);
    366                     return false;
    367                 }
    368             }
    369             // Add to the zip file.
    370             if (!ds.AddZipEntry("anrd_trace.txt", path)) {
    371                 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
    372             } else {
    373                 if (remove(path)) {
    374                     MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
    375                 }
    376                 return true;
    377             }
    378         } else {
    379             MYLOGE("Can't stats any trace file under %s\n", trace_path);
    380         }
    381     }
    382     return false;
    383 }
    384 
    385 static void dump_systrace() {
    386     if (!ds.IsZipping()) {
    387         MYLOGD("Not dumping systrace because it's not a zipped bugreport\n");
    388         return;
    389     }
    390     std::string systrace_path = ds.GetPath("-systrace.txt");
    391     if (systrace_path.empty()) {
    392         MYLOGE("Not dumping systrace because path is empty\n");
    393         return;
    394     }
    395     const char* path = "/sys/kernel/debug/tracing/tracing_on";
    396     long int is_tracing;
    397     if (read_file_as_long(path, &is_tracing)) {
    398         return; // error already logged
    399     }
    400     if (is_tracing <= 0) {
    401         MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
    402         return;
    403     }
    404 
    405     MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
    406             systrace_path.c_str());
    407     if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
    408                    CommandOptions::WithTimeout(120).Build())) {
    409         MYLOGE("systrace timed out, its zip entry will be incomplete\n");
    410         // TODO: RunCommand tries to kill the process, but atrace doesn't die
    411         // peacefully; ideally, we should call strace to stop itself, but there is no such option
    412         // yet (just a --async_stop, which stops and dump
    413         // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
    414         //   MYLOGE("could not stop systrace ");
    415         // }
    416     }
    417     if (!ds.AddZipEntry("systrace.txt", systrace_path)) {
    418         MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
    419     } else {
    420         if (remove(systrace_path.c_str())) {
    421             MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
    422         }
    423     }
    424 }
    425 
    426 static void dump_raft() {
    427     if (PropertiesHelper::IsUserBuild()) {
    428         return;
    429     }
    430 
    431     std::string raft_path = ds.GetPath("-raft_log.txt");
    432     if (raft_path.empty()) {
    433         MYLOGD("raft_path is empty\n");
    434         return;
    435     }
    436 
    437     struct stat s;
    438     if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
    439         MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
    440         return;
    441     }
    442 
    443     CommandOptions options = CommandOptions::WithTimeout(600).Build();
    444     if (!ds.IsZipping()) {
    445         // Write compressed and encoded raft logs to stdout if it's not a zipped bugreport.
    446         RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
    447         return;
    448     }
    449 
    450     RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_path}, options);
    451     if (!ds.AddZipEntry("raft_log.txt", raft_path)) {
    452         MYLOGE("Unable to add raft log %s to zip file\n", raft_path.c_str());
    453     } else {
    454         if (remove(raft_path.c_str())) {
    455             MYLOGE("Error removing raft file %s: %s\n", raft_path.c_str(), strerror(errno));
    456         }
    457     }
    458 }
    459 
    460 static bool skip_not_stat(const char *path) {
    461     static const char stat[] = "/stat";
    462     size_t len = strlen(path);
    463     if (path[len - 1] == '/') { /* Directory? */
    464         return false;
    465     }
    466     return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
    467 }
    468 
    469 static bool skip_none(const char* path __attribute__((unused))) {
    470     return false;
    471 }
    472 
    473 unsigned long worst_write_perf = 20000; /* in KB/s */
    474 
    475 //
    476 //  stat offsets
    477 // Name            units         description
    478 // ----            -----         -----------
    479 // read I/Os       requests      number of read I/Os processed
    480 #define __STAT_READ_IOS      0
    481 // read merges     requests      number of read I/Os merged with in-queue I/O
    482 #define __STAT_READ_MERGES   1
    483 // read sectors    sectors       number of sectors read
    484 #define __STAT_READ_SECTORS  2
    485 // read ticks      milliseconds  total wait time for read requests
    486 #define __STAT_READ_TICKS    3
    487 // write I/Os      requests      number of write I/Os processed
    488 #define __STAT_WRITE_IOS     4
    489 // write merges    requests      number of write I/Os merged with in-queue I/O
    490 #define __STAT_WRITE_MERGES  5
    491 // write sectors   sectors       number of sectors written
    492 #define __STAT_WRITE_SECTORS 6
    493 // write ticks     milliseconds  total wait time for write requests
    494 #define __STAT_WRITE_TICKS   7
    495 // in_flight       requests      number of I/Os currently in flight
    496 #define __STAT_IN_FLIGHT     8
    497 // io_ticks        milliseconds  total time this block device has been active
    498 #define __STAT_IO_TICKS      9
    499 // time_in_queue   milliseconds  total wait time for all requests
    500 #define __STAT_IN_QUEUE     10
    501 #define __STAT_NUMBER_FIELD 11
    502 //
    503 // read I/Os, write I/Os
    504 // =====================
    505 //
    506 // These values increment when an I/O request completes.
    507 //
    508 // read merges, write merges
    509 // =========================
    510 //
    511 // These values increment when an I/O request is merged with an
    512 // already-queued I/O request.
    513 //
    514 // read sectors, write sectors
    515 // ===========================
    516 //
    517 // These values count the number of sectors read from or written to this
    518 // block device.  The "sectors" in question are the standard UNIX 512-byte
    519 // sectors, not any device- or filesystem-specific block size.  The
    520 // counters are incremented when the I/O completes.
    521 #define SECTOR_SIZE 512
    522 //
    523 // read ticks, write ticks
    524 // =======================
    525 //
    526 // These values count the number of milliseconds that I/O requests have
    527 // waited on this block device.  If there are multiple I/O requests waiting,
    528 // these values will increase at a rate greater than 1000/second; for
    529 // example, if 60 read requests wait for an average of 30 ms, the read_ticks
    530 // field will increase by 60*30 = 1800.
    531 //
    532 // in_flight
    533 // =========
    534 //
    535 // This value counts the number of I/O requests that have been issued to
    536 // the device driver but have not yet completed.  It does not include I/O
    537 // requests that are in the queue but not yet issued to the device driver.
    538 //
    539 // io_ticks
    540 // ========
    541 //
    542 // This value counts the number of milliseconds during which the device has
    543 // had I/O requests queued.
    544 //
    545 // time_in_queue
    546 // =============
    547 //
    548 // This value counts the number of milliseconds that I/O requests have waited
    549 // on this block device.  If there are multiple I/O requests waiting, this
    550 // value will increase as the product of the number of milliseconds times the
    551 // number of requests waiting (see "read ticks" above for an example).
    552 #define S_TO_MS 1000
    553 //
    554 
    555 static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
    556     unsigned long long fields[__STAT_NUMBER_FIELD];
    557     bool z;
    558     char *cp, *buffer = NULL;
    559     size_t i = 0;
    560     FILE *fp = fdopen(fd, "rb");
    561     getline(&buffer, &i, fp);
    562     fclose(fp);
    563     if (!buffer) {
    564         return -errno;
    565     }
    566     i = strlen(buffer);
    567     while ((i > 0) && (buffer[i - 1] == '\n')) {
    568         buffer[--i] = '\0';
    569     }
    570     if (!*buffer) {
    571         free(buffer);
    572         return 0;
    573     }
    574     z = true;
    575     for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
    576         fields[i] = strtoull(cp, &cp, 10);
    577         if (fields[i] != 0) {
    578             z = false;
    579         }
    580     }
    581     if (z) { /* never accessed */
    582         free(buffer);
    583         return 0;
    584     }
    585 
    586     if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
    587         path += sizeof(BLK_DEV_SYS_DIR) - 1;
    588     }
    589 
    590     printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
    591            "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
    592            "W-wait", "in-fli", "activ", "T-wait", path, buffer);
    593     free(buffer);
    594 
    595     if (fields[__STAT_IO_TICKS]) {
    596         unsigned long read_perf = 0;
    597         unsigned long read_ios = 0;
    598         if (fields[__STAT_READ_TICKS]) {
    599             unsigned long long divisor = fields[__STAT_READ_TICKS]
    600                                        * fields[__STAT_IO_TICKS];
    601             read_perf = ((unsigned long long)SECTOR_SIZE
    602                            * fields[__STAT_READ_SECTORS]
    603                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
    604                                         / divisor;
    605             read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
    606                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
    607                                         / divisor;
    608         }
    609 
    610         unsigned long write_perf = 0;
    611         unsigned long write_ios = 0;
    612         if (fields[__STAT_WRITE_TICKS]) {
    613             unsigned long long divisor = fields[__STAT_WRITE_TICKS]
    614                                        * fields[__STAT_IO_TICKS];
    615             write_perf = ((unsigned long long)SECTOR_SIZE
    616                            * fields[__STAT_WRITE_SECTORS]
    617                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
    618                                         / divisor;
    619             write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
    620                            * fields[__STAT_IN_QUEUE] + (divisor >> 1))
    621                                         / divisor;
    622         }
    623 
    624         unsigned queue = (fields[__STAT_IN_QUEUE]
    625                              + (fields[__STAT_IO_TICKS] >> 1))
    626                                  / fields[__STAT_IO_TICKS];
    627 
    628         if (!write_perf && !write_ios) {
    629             printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
    630         } else {
    631             printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
    632                    read_ios, write_perf, write_ios, queue);
    633         }
    634 
    635         /* bugreport timeout factor adjustment */
    636         if ((write_perf > 1) && (write_perf < worst_write_perf)) {
    637             worst_write_perf = write_perf;
    638         }
    639     }
    640     return 0;
    641 }
    642 
    643 /* timeout in ms */
    644 static unsigned long logcat_timeout(const char *name) {
    645     log_id_t id = android_name_to_log_id(name);
    646     unsigned long property_size = __android_logger_get_buffer_size(id);
    647     /* Engineering margin is ten-fold our guess */
    648     return 10 * (property_size + worst_write_perf) / worst_write_perf;
    649 }
    650 
    651 void Dumpstate::PrintHeader() const {
    652     std::string build, fingerprint, radio, bootloader, network;
    653     char date[80];
    654 
    655     build = android::base::GetProperty("ro.build.display.id", "(unknown)");
    656     fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
    657     radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
    658     bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
    659     network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
    660     strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
    661 
    662     printf("========================================================\n");
    663     printf("== dumpstate: %s\n", date);
    664     printf("========================================================\n");
    665 
    666     printf("\n");
    667     printf("Build: %s\n", build.c_str());
    668     // NOTE: fingerprint entry format is important for other tools.
    669     printf("Build fingerprint: '%s'\n", fingerprint.c_str());
    670     printf("Bootloader: %s\n", bootloader.c_str());
    671     printf("Radio: %s\n", radio.c_str());
    672     printf("Network: %s\n", network.c_str());
    673 
    674     printf("Kernel: ");
    675     DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
    676     printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
    677     printf("Bugreport format version: %s\n", version_.c_str());
    678     printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
    679            PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str());
    680     printf("\n");
    681 }
    682 
    683 // List of file extensions that can cause a zip file attachment to be rejected by some email
    684 // service providers.
    685 static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
    686       ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
    687       ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
    688       ".shb", ".sys", ".vb",  ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
    689 };
    690 
    691 bool Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd) {
    692     if (!IsZipping()) {
    693         MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
    694                entry_name.c_str());
    695         return false;
    696     }
    697     std::string valid_name = entry_name;
    698 
    699     // Rename extension if necessary.
    700     size_t idx = entry_name.rfind(".");
    701     if (idx != std::string::npos) {
    702         std::string extension = entry_name.substr(idx);
    703         std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
    704         if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
    705             valid_name = entry_name + ".renamed";
    706             MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
    707         }
    708     }
    709 
    710     // Logging statement  below is useful to time how long each entry takes, but it's too verbose.
    711     // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
    712     int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
    713                                                   get_mtime(fd, ds.now_));
    714     if (err != 0) {
    715         MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
    716                ZipWriter::ErrorCodeString(err));
    717         return false;
    718     }
    719 
    720     std::vector<uint8_t> buffer(65536);
    721     while (1) {
    722         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
    723         if (bytes_read == 0) {
    724             break;
    725         } else if (bytes_read == -1) {
    726             MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
    727             return false;
    728         }
    729         err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
    730         if (err) {
    731             MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
    732             return false;
    733         }
    734     }
    735 
    736     err = zip_writer_->FinishEntry();
    737     if (err != 0) {
    738         MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
    739         return false;
    740     }
    741 
    742     return true;
    743 }
    744 
    745 bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
    746     android::base::unique_fd fd(
    747         TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
    748     if (fd == -1) {
    749         MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
    750         return false;
    751     }
    752 
    753     return AddZipEntryFromFd(entry_name, fd.get());
    754 }
    755 
    756 /* adds a file to the existing zipped bugreport */
    757 static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
    758     return ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
    759 }
    760 
    761 void Dumpstate::AddDir(const std::string& dir, bool recursive) {
    762     if (!IsZipping()) {
    763         MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
    764         return;
    765     }
    766     MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
    767     DurationReporter duration_reporter(dir, true);
    768     dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
    769 }
    770 
    771 bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
    772     if (!IsZipping()) {
    773         MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
    774                entry_name.c_str());
    775         return false;
    776     }
    777     MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
    778     int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
    779     if (err != 0) {
    780         MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
    781                ZipWriter::ErrorCodeString(err));
    782         return false;
    783     }
    784 
    785     err = zip_writer_->WriteBytes(content.c_str(), content.length());
    786     if (err != 0) {
    787         MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
    788                ZipWriter::ErrorCodeString(err));
    789         return false;
    790     }
    791 
    792     err = zip_writer_->FinishEntry();
    793     if (err != 0) {
    794         MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
    795         return false;
    796     }
    797 
    798     return true;
    799 }
    800 
    801 static void DoKmsg() {
    802     struct stat st;
    803     if (!stat(PSTORE_LAST_KMSG, &st)) {
    804         /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
    805         DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
    806     } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
    807         DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
    808     } else {
    809         /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
    810         DumpFile("LAST KMSG", "/proc/last_kmsg");
    811     }
    812 }
    813 
    814 static void DoLogcat() {
    815     unsigned long timeout;
    816     // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
    817     // calculate timeout
    818     timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
    819     if (timeout < 20000) {
    820         timeout = 20000;
    821     }
    822     RunCommand("SYSTEM LOG",
    823                {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid",
    824                         "-d", "*:v"},
    825                CommandOptions::WithTimeout(timeout / 1000).Build());
    826     timeout = logcat_timeout("events");
    827     if (timeout < 20000) {
    828         timeout = 20000;
    829     }
    830     RunCommand("EVENT LOG",
    831                {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid",
    832                         "-d", "*:v"},
    833                CommandOptions::WithTimeout(timeout / 1000).Build());
    834     timeout = logcat_timeout("radio");
    835     if (timeout < 20000) {
    836         timeout = 20000;
    837     }
    838     RunCommand("RADIO LOG",
    839                {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid",
    840                         "-d", "*:v"},
    841                CommandOptions::WithTimeout(timeout / 1000).Build());
    842 
    843     RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
    844 
    845     /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
    846     RunCommand("LAST LOGCAT",
    847                 {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-v", "uid",
    848                         "-d", "*:v"});
    849 }
    850 
    851 static void DumpIpTablesAsRoot() {
    852     RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
    853     RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
    854     RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
    855     /* no ip6 nat */
    856     RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
    857     RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
    858     RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
    859     RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
    860 }
    861 
    862 static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file,
    863                                   const std::string& anr_traces_dir) {
    864     std::string dump_traces_dir;
    865 
    866     if (dump_traces_path != nullptr) {
    867         if (add_to_zip) {
    868             dump_traces_dir = dirname(dump_traces_path);
    869             MYLOGD("Adding ANR traces (directory %s) to the zip file\n", dump_traces_dir.c_str());
    870             ds.AddDir(dump_traces_dir, true);
    871         } else {
    872             MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
    873                    dump_traces_path);
    874             ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
    875         }
    876     }
    877 
    878 
    879     // Make sure directory is not added twice.
    880     // TODO: this is an overzealous check because it's relying on dump_traces_path - which is
    881     // generated by dump_traces() -  and anr_traces_path - which is retrieved from a system
    882     // property - but in reality they're the same path (although the former could be nullptr).
    883     // Anyways, once dump_traces() is refactored as a private Dumpstate function, this logic should
    884     // be revisited.
    885     bool already_dumped = anr_traces_dir == dump_traces_dir;
    886 
    887     MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
    888            dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);
    889 
    890     int fd = TEMP_FAILURE_RETRY(
    891         open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
    892     if (fd < 0) {
    893         printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno));
    894     } else {
    895         if (add_to_zip) {
    896             if (!already_dumped) {
    897                 MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
    898                        anr_traces_dir.c_str());
    899                 ds.AddDir(anr_traces_dir, true);
    900             }
    901         } else {
    902             MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
    903                    anr_traces_file.c_str());
    904             dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd);
    905         }
    906     }
    907 }
    908 
    909 static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
    910     MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
    911            anr_traces_dir.c_str());
    912 
    913     // If we're here, dump_traces_path will always be a temporary file
    914     // (created with mkostemp or similar) that contains dumps taken earlier
    915     // on in the process.
    916     if (dump_traces_path != nullptr) {
    917         if (add_to_zip) {
    918             ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
    919         } else {
    920             MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
    921                    dump_traces_path);
    922             ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
    923         }
    924 
    925         const int ret = unlink(dump_traces_path);
    926         if (ret == -1) {
    927             MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
    928                    strerror(errno));
    929         }
    930     }
    931 
    932     // Add a specific message for the first ANR Dump.
    933     if (anr_data->size() > 0) {
    934         AddDumps(anr_data->begin(), anr_data->begin() + 1,
    935                  "VM TRACES AT LAST ANR", add_to_zip);
    936 
    937         if (anr_data->size() > 1) {
    938             // NOTE: Historical ANRs are always added as separate entries in the
    939             // bugreport zip file.
    940             AddDumps(anr_data->begin() + 1, anr_data->end(),
    941                      "HISTORICAL ANR", true /* add_to_zip */);
    942         }
    943     } else {
    944         printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
    945     }
    946 }
    947 
    948 static void AddAnrTraceFiles() {
    949     const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
    950 
    951     std::string anr_traces_file;
    952     std::string anr_traces_dir;
    953     bool is_global_trace_file = true;
    954 
    955     // First check whether the stack-trace-dir property is set. When it's set,
    956     // each ANR trace will be written to a separate file and not to a global
    957     // stack trace file.
    958     anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
    959     if (anr_traces_dir.empty()) {
    960         anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
    961         if (!anr_traces_file.empty()) {
    962             anr_traces_dir = dirname(anr_traces_file.c_str());
    963         }
    964     } else {
    965         is_global_trace_file = false;
    966     }
    967 
    968     // We have neither configured a global trace file nor a trace directory,
    969     // there will be nothing to dump.
    970     if (anr_traces_file.empty() && anr_traces_dir.empty()) {
    971         printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
    972         return;
    973     }
    974 
    975     if (is_global_trace_file) {
    976         AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir);
    977     } else {
    978         AddAnrTraceDir(add_to_zip, anr_traces_dir);
    979     }
    980 
    981     /* slow traces for slow operations */
    982     struct stat st;
    983     if (!anr_traces_dir.empty()) {
    984         int i = 0;
    985         while (true) {
    986             const std::string slow_trace_path =
    987                 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
    988             if (stat(slow_trace_path.c_str(), &st)) {
    989                 // No traces file at this index, done with the files.
    990                 break;
    991             }
    992             ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
    993             i++;
    994         }
    995     }
    996 }
    997 
    998 static void DumpBlockStatFiles() {
    999     DurationReporter duration_reporter("DUMP BLOCK STAT");
   1000 
   1001     std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
   1002 
   1003     if (dirptr == nullptr) {
   1004         MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
   1005         return;
   1006     }
   1007 
   1008     printf("------ DUMP BLOCK STAT ------\n\n");
   1009     while (struct dirent *d = readdir(dirptr.get())) {
   1010         if ((d->d_name[0] == '.')
   1011          && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
   1012           || (d->d_name[1] == '\0'))) {
   1013             continue;
   1014         }
   1015         const std::string new_path =
   1016             android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
   1017         printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
   1018         dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
   1019         printf("\n");
   1020     }
   1021      return;
   1022 }
   1023 
   1024 static void DumpPacketStats() {
   1025     DumpFile("NETWORK DEV INFO", "/proc/net/dev");
   1026     DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
   1027     DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
   1028     DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
   1029     DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
   1030 }
   1031 
   1032 static void DumpIpAddrAndRules() {
   1033     /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
   1034     RunCommand("NETWORK INTERFACES", {"ip", "link"});
   1035     RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
   1036     RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
   1037     RunCommand("IP RULES", {"ip", "rule", "show"});
   1038     RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
   1039 }
   1040 
   1041 static void dumpstate() {
   1042     DurationReporter duration_reporter("DUMPSTATE");
   1043 
   1044     dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
   1045     RunCommand("UPTIME", {"uptime"});
   1046     DumpBlockStatFiles();
   1047     dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
   1048     DumpFile("MEMORY INFO", "/proc/meminfo");
   1049     RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
   1050                             "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
   1051     RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
   1052     DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
   1053     DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
   1054     DumpFile("SLAB INFO", "/proc/slabinfo");
   1055     DumpFile("ZONEINFO", "/proc/zoneinfo");
   1056     DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
   1057     DumpFile("BUDDYINFO", "/proc/buddyinfo");
   1058     DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
   1059 
   1060     DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
   1061     DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
   1062     DumpFile("KERNEL SYNC", "/d/sync");
   1063 
   1064     RunCommand("PROCESSES AND THREADS",
   1065                {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"});
   1066     RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
   1067 
   1068     if (ds.IsZipping()) {
   1069         RunCommand(
   1070                 "HARDWARE HALS",
   1071                 {"lshal", std::string("--debug=") + kLsHalDebugPath},
   1072                 CommandOptions::AS_ROOT);
   1073 
   1074         ds.AddZipEntry("lshal-debug.txt", kLsHalDebugPath);
   1075 
   1076         unlink(kLsHalDebugPath.c_str());
   1077     } else {
   1078         RunCommand(
   1079                 "HARDWARE HALS", {"lshal", "--debug"}, CommandOptions::AS_ROOT);
   1080     }
   1081 
   1082     RunCommand("PRINTENV", {"printenv"});
   1083     RunCommand("NETSTAT", {"netstat", "-nW"});
   1084     struct stat s;
   1085     if (stat("/proc/modules", &s) != 0) {
   1086         MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
   1087     } else {
   1088         RunCommand("LSMOD", {"lsmod"});
   1089     }
   1090 
   1091     do_dmesg();
   1092 
   1093     RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
   1094     for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
   1095     for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
   1096     for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
   1097 
   1098     /* Dump Bluetooth HCI logs */
   1099     ds.AddDir("/data/misc/bluetooth/logs", true);
   1100 
   1101     if (!ds.do_early_screenshot_) {
   1102         MYLOGI("taking late screenshot\n");
   1103         ds.TakeScreenshot();
   1104     }
   1105 
   1106     DoLogcat();
   1107 
   1108     AddAnrTraceFiles();
   1109 
   1110     // NOTE: tombstones are always added as separate entries in the zip archive
   1111     // and are not interspersed with the main report.
   1112     const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(),
   1113                                             "TOMBSTONE", true /* add_to_zip */);
   1114     if (!tombstones_dumped) {
   1115         printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
   1116     }
   1117 
   1118     DumpPacketStats();
   1119 
   1120     DoKmsg();
   1121 
   1122     DumpIpAddrAndRules();
   1123 
   1124     dump_route_tables();
   1125 
   1126     RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
   1127     RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
   1128     RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
   1129 
   1130     RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
   1131                CommandOptions::WithTimeout(10).Build());
   1132 
   1133     RunCommand("SYSTEM PROPERTIES", {"getprop"});
   1134 
   1135     RunCommand("VOLD DUMP", {"vdc", "dump"});
   1136     RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
   1137 
   1138     RunCommand("STORAGED TASKIOINFO", {"storaged", "-u"}, CommandOptions::WithTimeout(10).Build());
   1139 
   1140     RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
   1141 
   1142     RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
   1143 
   1144     printf("------ BACKLIGHTS ------\n");
   1145     printf("LCD brightness=");
   1146     DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
   1147     printf("Button brightness=");
   1148     DumpFile("", "/sys/class/leds/button-backlight/brightness");
   1149     printf("Keyboard brightness=");
   1150     DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
   1151     printf("ALS mode=");
   1152     DumpFile("", "/sys/class/leds/lcd-backlight/als");
   1153     printf("LCD driver registers:\n");
   1154     DumpFile("", "/sys/class/leds/lcd-backlight/registers");
   1155     printf("\n");
   1156 
   1157     /* Binder state is expensive to look at as it uses a lot of memory. */
   1158     DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
   1159     DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
   1160     DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
   1161     DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
   1162     DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
   1163 
   1164     ds.DumpstateBoard();
   1165 
   1166     /* Migrate the ril_dumpstate to a device specific dumpstate? */
   1167     int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
   1168     if (rilDumpstateTimeout > 0) {
   1169         // su does not exist on user builds, so try running without it.
   1170         // This way any implementations of vril-dump that do not require
   1171         // root can run on user builds.
   1172         CommandOptions::CommandOptionsBuilder options =
   1173             CommandOptions::WithTimeout(rilDumpstateTimeout);
   1174         if (!PropertiesHelper::IsUserBuild()) {
   1175             options.AsRoot();
   1176         }
   1177         RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
   1178     }
   1179 
   1180     printf("========================================================\n");
   1181     printf("== Android Framework Services\n");
   1182     printf("========================================================\n");
   1183 
   1184     RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
   1185                10);
   1186 
   1187     printf("========================================================\n");
   1188     printf("== Checkins\n");
   1189     printf("========================================================\n");
   1190 
   1191     RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
   1192     RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
   1193     RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
   1194     RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
   1195     RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
   1196     RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
   1197 
   1198     printf("========================================================\n");
   1199     printf("== Running Application Activities\n");
   1200     printf("========================================================\n");
   1201 
   1202     RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"});
   1203 
   1204     printf("========================================================\n");
   1205     printf("== Running Application Services\n");
   1206     printf("========================================================\n");
   1207 
   1208     RunDumpsys("APP SERVICES", {"activity", "service", "all"});
   1209 
   1210     printf("========================================================\n");
   1211     printf("== Running Application Providers\n");
   1212     printf("========================================================\n");
   1213 
   1214     RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
   1215 
   1216     printf("========================================================\n");
   1217     printf("== Dropbox crashes\n");
   1218     printf("========================================================\n");
   1219 
   1220     RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
   1221     RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
   1222 
   1223     printf("========================================================\n");
   1224     printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
   1225            ds.progress_->GetMax(), ds.progress_->GetInitialMax());
   1226     printf("========================================================\n");
   1227     printf("== dumpstate: done (id %d)\n", ds.id_);
   1228     printf("========================================================\n");
   1229 }
   1230 
   1231 // This method collects dumpsys for telephony debugging only
   1232 static void DumpstateTelephonyOnly() {
   1233     DurationReporter duration_reporter("DUMPSTATE");
   1234 
   1235     DumpIpTablesAsRoot();
   1236 
   1237     if (!DropRootUser()) {
   1238         return;
   1239     }
   1240 
   1241     do_dmesg();
   1242     DoLogcat();
   1243     DumpPacketStats();
   1244     DoKmsg();
   1245     DumpIpAddrAndRules();
   1246     dump_route_tables();
   1247 
   1248     RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
   1249                CommandOptions::WithTimeout(10).Build());
   1250 
   1251     RunCommand("SYSTEM PROPERTIES", {"getprop"});
   1252 
   1253     printf("========================================================\n");
   1254     printf("== Android Framework Services\n");
   1255     printf("========================================================\n");
   1256 
   1257     RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(), 10);
   1258     RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(), 10);
   1259 
   1260     printf("========================================================\n");
   1261     printf("== Running Application Services\n");
   1262     printf("========================================================\n");
   1263 
   1264     RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
   1265 
   1266     printf("========================================================\n");
   1267     printf("== dumpstate: done (id %d)\n", ds.id_);
   1268     printf("========================================================\n");
   1269 }
   1270 
   1271 void Dumpstate::DumpstateBoard() {
   1272     DurationReporter duration_reporter("dumpstate_board()");
   1273     printf("========================================================\n");
   1274     printf("== Board\n");
   1275     printf("========================================================\n");
   1276 
   1277     ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
   1278     if (dumpstate_device == nullptr) {
   1279         MYLOGE("No IDumpstateDevice implementation\n");
   1280         return;
   1281     }
   1282 
   1283     if (!IsZipping()) {
   1284         MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
   1285         return;
   1286     }
   1287 
   1288     std::string path[NUM_OF_DUMPS];
   1289     android::base::unique_fd fd[NUM_OF_DUMPS];
   1290     int numFds = 0;
   1291 
   1292     for (int i = 0; i < NUM_OF_DUMPS; i++) {
   1293         path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i];
   1294         MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str());
   1295 
   1296         fd[i] = android::base::unique_fd(
   1297             TEMP_FAILURE_RETRY(open(path[i].c_str(),
   1298             O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
   1299             S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
   1300         if (fd[i] < 0) {
   1301             MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno));
   1302             return;
   1303         } else {
   1304             numFds++;
   1305         }
   1306     }
   1307 
   1308     native_handle_t *handle = native_handle_create(numFds, 0);
   1309     if (handle == nullptr) {
   1310         MYLOGE("Could not create native_handle\n");
   1311         return;
   1312     }
   1313 
   1314     for (int i = 0; i < numFds; i++) {
   1315         handle->data[i] = fd[i].release();
   1316     }
   1317 
   1318     // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
   1319     android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
   1320     if (!status.isOk()) {
   1321         MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
   1322         native_handle_close(handle);
   1323         native_handle_delete(handle);
   1324         return;
   1325     }
   1326 
   1327     for (int i = 0; i < numFds; i++) {
   1328         struct stat s;
   1329         if (fstat(handle->data[i], &s) == -1) {
   1330             MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno);
   1331         } else if (s.st_size > 0) {
   1332             AddZipEntry(kDumpstateBoardFiles[i], path[i]);
   1333         } else {
   1334             MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
   1335         }
   1336     }
   1337 
   1338     printf("*** See dumpstate-board.txt entry ***\n");
   1339 
   1340     native_handle_close(handle);
   1341     native_handle_delete(handle);
   1342 
   1343     for (int i = 0; i < numFds; i++) {
   1344         if (remove(path[i].c_str()) != 0) {
   1345             MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno));
   1346         }
   1347     }
   1348 }
   1349 
   1350 static void ShowUsageAndExit(int exitCode = 1) {
   1351     fprintf(stderr,
   1352             "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
   1353             "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
   1354             "  -h: display this help message\n"
   1355             "  -b: play sound file instead of vibrate, at beginning of job\n"
   1356             "  -e: play sound file instead of vibrate, at end of job\n"
   1357             "  -o: write to file (instead of stdout)\n"
   1358             "  -d: append date to filename (requires -o)\n"
   1359             "  -p: capture screenshot to filename.png (requires -o)\n"
   1360             "  -z: generate zipped file (requires -o)\n"
   1361             "  -s: write output to control socket (for init)\n"
   1362             "  -S: write file location to control socket (for init; requires -o and -z)"
   1363             "  -q: disable vibrate\n"
   1364             "  -B: send broadcast when finished (requires -o)\n"
   1365             "  -P: send broadcast when started and update system properties on "
   1366             "progress (requires -o and -B)\n"
   1367             "  -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
   1368             "shouldn't be used with -P)\n"
   1369             "  -v: prints the dumpstate header and exit\n");
   1370     exit(exitCode);
   1371 }
   1372 
   1373 static void ExitOnInvalidArgs() {
   1374     fprintf(stderr, "invalid combination of args\n");
   1375     ShowUsageAndExit();
   1376 }
   1377 
   1378 static void sig_handler(int) {
   1379     _exit(EXIT_FAILURE);
   1380 }
   1381 
   1382 static void register_sig_handler() {
   1383     struct sigaction sa;
   1384     sigemptyset(&sa.sa_mask);
   1385     sa.sa_flags = 0;
   1386     sa.sa_handler = sig_handler;
   1387     sigaction(SIGPIPE, &sa, NULL); // broken pipe
   1388     sigaction(SIGSEGV, &sa, NULL); // segment fault
   1389     sigaction(SIGINT, &sa, NULL); // ctrl-c
   1390     sigaction(SIGTERM, &sa, NULL); // killed
   1391     sigaction(SIGQUIT, &sa, NULL); // quit
   1392 }
   1393 
   1394 bool Dumpstate::FinishZipFile() {
   1395     std::string entry_name = base_name_ + "-" + name_ + ".txt";
   1396     MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
   1397            tmp_path_.c_str());
   1398     // Final timestamp
   1399     char date[80];
   1400     time_t the_real_now_please_stand_up = time(nullptr);
   1401     strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
   1402     MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
   1403            the_real_now_please_stand_up - ds.now_);
   1404 
   1405     if (!ds.AddZipEntry(entry_name, tmp_path_)) {
   1406         MYLOGE("Failed to add text entry to .zip file\n");
   1407         return false;
   1408     }
   1409     if (!AddTextZipEntry("main_entry.txt", entry_name)) {
   1410         MYLOGE("Failed to add main_entry.txt to .zip file\n");
   1411         return false;
   1412     }
   1413 
   1414     // Add log file (which contains stderr output) to zip...
   1415     fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
   1416     if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
   1417         MYLOGE("Failed to add dumpstate log to .zip file\n");
   1418         return false;
   1419     }
   1420     // ... and re-opens it for further logging.
   1421     redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
   1422     fprintf(stderr, "\n");
   1423 
   1424     int32_t err = zip_writer_->Finish();
   1425     if (err != 0) {
   1426         MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
   1427         return false;
   1428     }
   1429 
   1430     // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
   1431     ds.zip_file.reset(nullptr);
   1432 
   1433     MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
   1434     if (remove(tmp_path_.c_str()) != 0) {
   1435         MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
   1436     }
   1437 
   1438     return true;
   1439 }
   1440 
   1441 static std::string SHA256_file_hash(std::string filepath) {
   1442     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
   1443             | O_CLOEXEC | O_NOFOLLOW)));
   1444     if (fd == -1) {
   1445         MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
   1446         return NULL;
   1447     }
   1448 
   1449     SHA256_CTX ctx;
   1450     SHA256_Init(&ctx);
   1451 
   1452     std::vector<uint8_t> buffer(65536);
   1453     while (1) {
   1454         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
   1455         if (bytes_read == 0) {
   1456             break;
   1457         } else if (bytes_read == -1) {
   1458             MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
   1459             return NULL;
   1460         }
   1461 
   1462         SHA256_Update(&ctx, buffer.data(), bytes_read);
   1463     }
   1464 
   1465     uint8_t hash[SHA256_DIGEST_LENGTH];
   1466     SHA256_Final(hash, &ctx);
   1467 
   1468     char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
   1469     for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
   1470         sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
   1471     }
   1472     hash_buffer[sizeof(hash_buffer) - 1] = 0;
   1473     return std::string(hash_buffer);
   1474 }
   1475 
   1476 static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
   1477     // clang-format off
   1478     std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
   1479                     "--receiver-foreground", "--receiver-include-background", "-a", action};
   1480     // clang-format on
   1481 
   1482     am.insert(am.end(), args.begin(), args.end());
   1483 
   1484     RunCommand("", am,
   1485                CommandOptions::WithTimeout(20)
   1486                    .Log("Sending broadcast: '%s'\n")
   1487                    .Always()
   1488                    .DropRoot()
   1489                    .RedirectStderr()
   1490                    .Build());
   1491 }
   1492 
   1493 static void Vibrate(int duration_ms) {
   1494     // clang-format off
   1495     RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
   1496                CommandOptions::WithTimeout(10)
   1497                    .Log("Vibrate: '%s'\n")
   1498                    .Always()
   1499                    .Build());
   1500     // clang-format on
   1501 }
   1502 
   1503 int main(int argc, char *argv[]) {
   1504     int do_add_date = 0;
   1505     int do_zip_file = 0;
   1506     int do_vibrate = 1;
   1507     char* use_outfile = 0;
   1508     int use_socket = 0;
   1509     int use_control_socket = 0;
   1510     int do_fb = 0;
   1511     int do_broadcast = 0;
   1512     int is_remote_mode = 0;
   1513     bool show_header_only = false;
   1514     bool do_start_service = false;
   1515     bool telephony_only = false;
   1516 
   1517     /* set as high priority, and protect from OOM killer */
   1518     setpriority(PRIO_PROCESS, 0, -20);
   1519 
   1520     FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
   1521     if (oom_adj) {
   1522         fputs("-1000", oom_adj);
   1523         fclose(oom_adj);
   1524     } else {
   1525         /* fallback to kernels <= 2.6.35 */
   1526         oom_adj = fopen("/proc/self/oom_adj", "we");
   1527         if (oom_adj) {
   1528             fputs("-17", oom_adj);
   1529             fclose(oom_adj);
   1530         }
   1531     }
   1532 
   1533     /* parse arguments */
   1534     int c;
   1535     while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
   1536         switch (c) {
   1537             // clang-format off
   1538             case 'd': do_add_date = 1;            break;
   1539             case 'z': do_zip_file = 1;            break;
   1540             case 'o': use_outfile = optarg;       break;
   1541             case 's': use_socket = 1;             break;
   1542             case 'S': use_control_socket = 1;     break;
   1543             case 'v': show_header_only = true;    break;
   1544             case 'q': do_vibrate = 0;             break;
   1545             case 'p': do_fb = 1;                  break;
   1546             case 'P': ds.update_progress_ = true; break;
   1547             case 'R': is_remote_mode = 1;         break;
   1548             case 'B': do_broadcast = 1;           break;
   1549             case 'V':                             break; // compatibility no-op
   1550             case 'h':
   1551                 ShowUsageAndExit(0);
   1552                 break;
   1553             default:
   1554                 fprintf(stderr, "Invalid option: %c\n", c);
   1555                 ShowUsageAndExit();
   1556                 // clang-format on
   1557         }
   1558     }
   1559 
   1560     // TODO: use helper function to convert argv into a string
   1561     for (int i = 0; i < argc; i++) {
   1562         ds.args_ += argv[i];
   1563         if (i < argc - 1) {
   1564             ds.args_ += " ";
   1565         }
   1566     }
   1567 
   1568     ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
   1569     if (!ds.extra_options_.empty()) {
   1570         // Framework uses a system property to override some command-line args.
   1571         // Currently, it contains the type of the requested bugreport.
   1572         if (ds.extra_options_ == "bugreportplus") {
   1573             // Currently, the dumpstate binder is only used by Shell to update progress.
   1574             do_start_service = true;
   1575             ds.update_progress_ = true;
   1576             do_fb = 0;
   1577         } else if (ds.extra_options_ == "bugreportremote") {
   1578             do_vibrate = 0;
   1579             is_remote_mode = 1;
   1580             do_fb = 0;
   1581         } else if (ds.extra_options_ == "bugreportwear") {
   1582             ds.update_progress_ = true;
   1583         } else if (ds.extra_options_ == "bugreporttelephony") {
   1584             telephony_only = true;
   1585         } else {
   1586             MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
   1587         }
   1588         // Reset the property
   1589         android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
   1590     }
   1591 
   1592     ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
   1593     if (!ds.notification_title.empty()) {
   1594         // Reset the property
   1595         android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
   1596 
   1597         ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
   1598         if (!ds.notification_description.empty()) {
   1599             // Reset the property
   1600             android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
   1601         }
   1602         MYLOGD("notification (title:  %s, description: %s)\n",
   1603                ds.notification_title.c_str(), ds.notification_description.c_str());
   1604     }
   1605 
   1606     if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
   1607         ExitOnInvalidArgs();
   1608     }
   1609 
   1610     if (use_control_socket && !do_zip_file) {
   1611         ExitOnInvalidArgs();
   1612     }
   1613 
   1614     if (ds.update_progress_ && !do_broadcast) {
   1615         ExitOnInvalidArgs();
   1616     }
   1617 
   1618     if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
   1619         ExitOnInvalidArgs();
   1620     }
   1621 
   1622     if (ds.version_ == VERSION_DEFAULT) {
   1623         ds.version_ = VERSION_CURRENT;
   1624     }
   1625 
   1626     if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
   1627         MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
   1628                ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
   1629                VERSION_SPLIT_ANR.c_str());
   1630         exit(1);
   1631     }
   1632 
   1633     if (show_header_only) {
   1634         ds.PrintHeader();
   1635         exit(0);
   1636     }
   1637 
   1638     /* redirect output if needed */
   1639     bool is_redirecting = !use_socket && use_outfile;
   1640 
   1641     // TODO: temporarily set progress until it's part of the Dumpstate constructor
   1642     std::string stats_path =
   1643         is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
   1644                        : "";
   1645     ds.progress_.reset(new Progress(stats_path));
   1646 
   1647     /* gets the sequential id */
   1648     uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
   1649     ds.id_ = ++last_id;
   1650     android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
   1651 
   1652     MYLOGI("begin\n");
   1653 
   1654     register_sig_handler();
   1655 
   1656     if (do_start_service) {
   1657         MYLOGI("Starting 'dumpstate' service\n");
   1658         android::status_t ret;
   1659         if ((ret = android::os::DumpstateService::Start()) != android::OK) {
   1660             MYLOGE("Unable to start DumpstateService: %d\n", ret);
   1661         }
   1662     }
   1663 
   1664     if (PropertiesHelper::IsDryRun()) {
   1665         MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
   1666     }
   1667 
   1668     MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
   1669            ds.extra_options_.c_str());
   1670 
   1671     MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
   1672 
   1673     ds.do_early_screenshot_ = ds.update_progress_;
   1674 
   1675     // If we are going to use a socket, do it as early as possible
   1676     // to avoid timeouts from bugreport.
   1677     if (use_socket) {
   1678         redirect_to_socket(stdout, "dumpstate");
   1679     }
   1680 
   1681     if (use_control_socket) {
   1682         MYLOGD("Opening control socket\n");
   1683         ds.control_socket_fd_ = open_socket("dumpstate");
   1684         ds.update_progress_ = 1;
   1685     }
   1686 
   1687     if (is_redirecting) {
   1688         ds.bugreport_dir_ = dirname(use_outfile);
   1689         std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
   1690         std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
   1691         ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
   1692                                                     device_name.c_str(), build_id.c_str());
   1693         if (do_add_date) {
   1694             char date[80];
   1695             strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
   1696             ds.name_ = date;
   1697         } else {
   1698             ds.name_ = "undated";
   1699         }
   1700 
   1701         if (telephony_only) {
   1702             ds.base_name_ += "-telephony";
   1703         }
   1704 
   1705         if (do_fb) {
   1706             ds.screenshot_path_ = ds.GetPath(".png");
   1707         }
   1708         ds.tmp_path_ = ds.GetPath(".tmp");
   1709         ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
   1710 
   1711         MYLOGD(
   1712             "Bugreport dir: %s\n"
   1713             "Base name: %s\n"
   1714             "Suffix: %s\n"
   1715             "Log path: %s\n"
   1716             "Temporary path: %s\n"
   1717             "Screenshot path: %s\n",
   1718             ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
   1719             ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
   1720 
   1721         if (do_zip_file) {
   1722             ds.path_ = ds.GetPath(".zip");
   1723             MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
   1724             create_parent_dirs(ds.path_.c_str());
   1725             ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
   1726             if (ds.zip_file == nullptr) {
   1727                 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
   1728                 do_zip_file = 0;
   1729             } else {
   1730                 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
   1731             }
   1732             ds.AddTextZipEntry("version.txt", ds.version_);
   1733         }
   1734 
   1735         if (ds.update_progress_) {
   1736             if (do_broadcast) {
   1737                 // clang-format off
   1738 
   1739                 std::vector<std::string> am_args = {
   1740                      "--receiver-permission", "android.permission.DUMP",
   1741                      "--es", "android.intent.extra.NAME", ds.name_,
   1742                      "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
   1743                      "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
   1744                      "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
   1745                 };
   1746                 // clang-format on
   1747                 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
   1748             }
   1749             if (use_control_socket) {
   1750                 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
   1751             }
   1752         }
   1753     }
   1754 
   1755     /* read /proc/cmdline before dropping root */
   1756     FILE *cmdline = fopen("/proc/cmdline", "re");
   1757     if (cmdline) {
   1758         fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
   1759         fclose(cmdline);
   1760     }
   1761 
   1762     if (do_vibrate) {
   1763         Vibrate(150);
   1764     }
   1765 
   1766     if (do_fb && ds.do_early_screenshot_) {
   1767         if (ds.screenshot_path_.empty()) {
   1768             // should not have happened
   1769             MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
   1770         } else {
   1771             MYLOGI("taking early screenshot\n");
   1772             ds.TakeScreenshot();
   1773         }
   1774     }
   1775 
   1776     if (do_zip_file) {
   1777         if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
   1778             MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
   1779                    strerror(errno));
   1780         }
   1781     }
   1782 
   1783     if (is_redirecting) {
   1784         redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
   1785         if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
   1786             MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
   1787                    ds.log_path_.c_str(), strerror(errno));
   1788         }
   1789         /* TODO: rather than generating a text file now and zipping it later,
   1790            it would be more efficient to redirect stdout to the zip entry
   1791            directly, but the libziparchive doesn't support that option yet. */
   1792         redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
   1793         if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
   1794             MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
   1795                    ds.tmp_path_.c_str(), strerror(errno));
   1796         }
   1797     }
   1798 
   1799     // Don't buffer stdout
   1800     setvbuf(stdout, nullptr, _IONBF, 0);
   1801 
   1802     // NOTE: there should be no stdout output until now, otherwise it would break the header.
   1803     // In particular, DurationReport objects should be created passing 'title, NULL', so their
   1804     // duration is logged into MYLOG instead.
   1805     ds.PrintHeader();
   1806 
   1807     if (telephony_only) {
   1808         DumpstateTelephonyOnly();
   1809         ds.DumpstateBoard();
   1810     } else {
   1811         // Dumps systrace right away, otherwise it will be filled with unnecessary events.
   1812         // First try to dump anrd trace if the daemon is running. Otherwise, dump
   1813         // the raw trace.
   1814         if (!dump_anrd_trace()) {
   1815             dump_systrace();
   1816         }
   1817 
   1818         // Invoking the following dumpsys calls before dump_traces() to try and
   1819         // keep the system stats as close to its initial state as possible.
   1820         RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
   1821                    CommandOptions::WithTimeout(90).DropRoot().Build());
   1822         RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
   1823                    CommandOptions::WithTimeout(10).DropRoot().Build());
   1824 
   1825         // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
   1826         dump_raft();
   1827 
   1828         /* collect stack traces from Dalvik and native processes (needs root) */
   1829         dump_traces_path = dump_traces();
   1830 
   1831         /* Run some operations that require root. */
   1832         tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
   1833         anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()));
   1834 
   1835         ds.AddDir(RECOVERY_DIR, true);
   1836         ds.AddDir(RECOVERY_DATA_DIR, true);
   1837         ds.AddDir(LOGPERSIST_DATA_DIR, false);
   1838         if (!PropertiesHelper::IsUserBuild()) {
   1839             ds.AddDir(PROFILE_DATA_DIR_CUR, true);
   1840             ds.AddDir(PROFILE_DATA_DIR_REF, true);
   1841         }
   1842         add_mountinfo();
   1843         DumpIpTablesAsRoot();
   1844 
   1845         // Capture any IPSec policies in play.  No keys are exposed here.
   1846         RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
   1847                    CommandOptions::WithTimeout(10).Build());
   1848 
   1849         // Run ss as root so we can see socket marks.
   1850         RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
   1851                    CommandOptions::WithTimeout(10).Build());
   1852 
   1853         if (!DropRootUser()) {
   1854             return -1;
   1855         }
   1856 
   1857         dumpstate();
   1858     }
   1859 
   1860     /* close output if needed */
   1861     if (is_redirecting) {
   1862         fclose(stdout);
   1863     }
   1864 
   1865     /* rename or zip the (now complete) .tmp file to its final location */
   1866     if (use_outfile) {
   1867 
   1868         /* check if user changed the suffix using system properties */
   1869         std::string name = android::base::GetProperty(
   1870             android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
   1871         bool change_suffix= false;
   1872         if (!name.empty()) {
   1873             /* must whitelist which characters are allowed, otherwise it could cross directories */
   1874             std::regex valid_regex("^[-_a-zA-Z0-9]+$");
   1875             if (std::regex_match(name.c_str(), valid_regex)) {
   1876                 change_suffix = true;
   1877             } else {
   1878                 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
   1879             }
   1880         }
   1881         if (change_suffix) {
   1882             MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
   1883             ds.name_ = name;
   1884             if (!ds.screenshot_path_.empty()) {
   1885                 std::string new_screenshot_path = ds.GetPath(".png");
   1886                 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
   1887                     MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
   1888                            new_screenshot_path.c_str(), strerror(errno));
   1889                 } else {
   1890                     ds.screenshot_path_ = new_screenshot_path;
   1891                 }
   1892             }
   1893         }
   1894 
   1895         bool do_text_file = true;
   1896         if (do_zip_file) {
   1897             if (!ds.FinishZipFile()) {
   1898                 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
   1899                 do_text_file = true;
   1900             } else {
   1901                 do_text_file = false;
   1902                 // Since zip file is already created, it needs to be renamed.
   1903                 std::string new_path = ds.GetPath(".zip");
   1904                 if (ds.path_ != new_path) {
   1905                     MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
   1906                     if (rename(ds.path_.c_str(), new_path.c_str())) {
   1907                         MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
   1908                                strerror(errno));
   1909                     } else {
   1910                         ds.path_ = new_path;
   1911                     }
   1912                 }
   1913             }
   1914         }
   1915         if (do_text_file) {
   1916             ds.path_ = ds.GetPath(".txt");
   1917             MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
   1918                    ds.tmp_path_.c_str());
   1919             if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
   1920                 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
   1921                        strerror(errno));
   1922                 ds.path_.clear();
   1923             }
   1924         }
   1925         if (use_control_socket) {
   1926             if (do_text_file) {
   1927                 dprintf(ds.control_socket_fd_,
   1928                         "FAIL:could not create zip file, check %s "
   1929                         "for more details\n",
   1930                         ds.log_path_.c_str());
   1931             } else {
   1932                 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
   1933             }
   1934         }
   1935     }
   1936 
   1937     /* vibrate a few but shortly times to let user know it's finished */
   1938     for (int i = 0; i < 3; i++) {
   1939         Vibrate(75);
   1940         usleep((75 + 50) * 1000);
   1941     }
   1942 
   1943     /* tell activity manager we're done */
   1944     if (do_broadcast) {
   1945         if (!ds.path_.empty()) {
   1946             MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
   1947             // clang-format off
   1948 
   1949             std::vector<std::string> am_args = {
   1950                  "--receiver-permission", "android.permission.DUMP",
   1951                  "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
   1952                  "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
   1953                  "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
   1954                  "--es", "android.intent.extra.BUGREPORT", ds.path_,
   1955                  "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
   1956             };
   1957             // clang-format on
   1958             if (do_fb) {
   1959                 am_args.push_back("--es");
   1960                 am_args.push_back("android.intent.extra.SCREENSHOT");
   1961                 am_args.push_back(ds.screenshot_path_);
   1962             }
   1963             if (!ds.notification_title.empty()) {
   1964                 am_args.push_back("--es");
   1965                 am_args.push_back("android.intent.extra.TITLE");
   1966                 am_args.push_back(ds.notification_title);
   1967                 if (!ds.notification_description.empty()) {
   1968                     am_args.push_back("--es");
   1969                     am_args.push_back("android.intent.extra.DESCRIPTION");
   1970                     am_args.push_back(ds.notification_description);
   1971                 }
   1972             }
   1973             if (is_remote_mode) {
   1974                 am_args.push_back("--es");
   1975                 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
   1976                 am_args.push_back(SHA256_file_hash(ds.path_));
   1977                 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
   1978                               am_args);
   1979             } else {
   1980                 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
   1981             }
   1982         } else {
   1983             MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
   1984         }
   1985     }
   1986 
   1987     MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
   1988            ds.progress_->GetInitialMax());
   1989     ds.progress_->Save();
   1990     MYLOGI("done (id %d)\n", ds.id_);
   1991 
   1992     if (is_redirecting) {
   1993         fclose(stderr);
   1994     }
   1995 
   1996     if (use_control_socket && ds.control_socket_fd_ != -1) {
   1997         MYLOGD("Closing control socket\n");
   1998         close(ds.control_socket_fd_);
   1999     }
   2000 
   2001     return 0;
   2002 }
   2003