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