dumpstate.cpp revision 4db754fd7c13993d81d98157f10e8015422d1e3a
1f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross/*
2f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * Copyright (C) 2008 The Android Open Source Project
3f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross *
4f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * Licensed under the Apache License, Version 2.0 (the "License");
5f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * you may not use this file except in compliance with the License.
6f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * You may obtain a copy of the License at
7f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross *
8f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross *      http://www.apache.org/licenses/LICENSE-2.0
9f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross *
10f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * Unless required by applicable law or agreed to in writing, software
11f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * distributed under the License is distributed on an "AS IS" BASIS,
12f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * See the License for the specific language governing permissions and
14f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross * limitations under the License.
15f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross */
16f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
172db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg#include <dirent.h>
18f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <errno.h>
19f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <fcntl.h>
20ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme#include <libgen.h>
21f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <limits.h>
226e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme#include <memory>
23ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme#include <regex>
24635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme#include <set>
258f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn#include <stdbool.h>
26f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <stdio.h>
27f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <stdlib.h>
286e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme#include <string>
29f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <string.h>
307dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#include <sys/capability.h>
317dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#include <sys/prctl.h>
32f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <sys/resource.h>
33f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <sys/stat.h>
34f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <sys/time.h>
35f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <sys/wait.h>
36f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <unistd.h>
37f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
389dc117c415d0df0a3acd900709d05deabe975704Elliott Hughes#include <android-base/stringprintf.h>
39f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <cutils/properties.h>
40f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
41f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include "private/android_filesystem_config.h"
42f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
43f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#define LOG_TAG "dumpstate"
44656a6b9e3645bfe2cf073b69cbb9d02832f62c26Alex Ray#include <cutils/log.h>
45f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
46f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include "dumpstate.h"
476e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme#include "ScopedFd.h"
486e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme#include "ziparchive/zip_writer.h"
496e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
504db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski#include "mincrypt/sha256.h"
514db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
526e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Lemeusing android::base::StringPrintf;
53f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
54f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross/* read before root is shed */
55f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossstatic char cmdline_buf[16384] = "(unknown)";
56f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossstatic const char *dump_traces_path = NULL;
57f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
58e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme// TODO: should be part of dumpstate object
5978f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Lemestatic char build_type[PROPERTY_VALUE_MAX];
60e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemestatic time_t now;
61e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemestatic std::unique_ptr<ZipWriter> zip_writer;
62635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Lemestatic std::set<std::string> mount_points;
63635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Lemevoid add_mountinfo();
64635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Lemestatic bool add_zip_entry(const std::string& entry_name, const std::string& entry_path);
6578f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme
662a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
672a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor
688d4cb7ffc11050eebb4d06684e0eb14d9aadacb5Sharvil Nanavati#define RAFT_DIR "/data/misc/raft/"
69e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme#define RECOVERY_DIR "/cache/recovery"
707dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#define TOMBSTONE_DIR "/data/tombstones"
717dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
727dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris/* Can accomodate a tombstone number up to 9999. */
737dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
747dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#define NUM_TOMBSTONES  10
757dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
767dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferristypedef struct {
777dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris  char name[TOMBSTONE_MAX_LEN];
787dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris  int fd;
797dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris} tombstone_data_t;
807dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
817dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferrisstatic tombstone_data_t tombstone_data[NUM_TOMBSTONES];
827dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
83e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme// Root dir for all files copied as-is into the bugreport
84e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemeconst std::string& ZIP_ROOT_DIR = "FS";
85e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
86e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme/* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones,
87e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme * otherwise gets just those modified in the last half an hour. */
887dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferrisstatic void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
89e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    time_t thirty_minutes_ago = now - 60*30;
907dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
917dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
9254bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        int fd = TEMP_FAILURE_RETRY(open(data[i].name,
9354bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris                                         O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
947dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        struct stat st;
957dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
96e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) {
97e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        data[i].fd = fd;
987dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        } else {
99e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        close(fd);
1007dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris            data[i].fd = -1;
1017dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        }
1027dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    }
1037dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris}
1047dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
105635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme// for_each_pid() callback to get mount info about a process.
106635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Lemevoid do_mountinfo(int pid, const char *name) {
107635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    char path[PATH_MAX];
108635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme
109635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
110635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    // are added.
111635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    sprintf(path, "/proc/%d/ns/mnt", pid);
112635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    char linkname[PATH_MAX];
113635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    ssize_t r = readlink(path, linkname, PATH_MAX);
114635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    if (r == -1) {
115635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme        ALOGE("Unable to read link for %s: %s\n", path, strerror(errno));
116635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme        return;
117635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    }
118635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    linkname[r] = '\0';
119635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme
120635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    if (mount_points.find(linkname) == mount_points.end()) {
121635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme        // First time this mount point was found: add it
122635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme        sprintf(path, "/proc/%d/mountinfo", pid);
123635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme        if (add_zip_entry(ZIP_ROOT_DIR + path, path)) {
124635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme            mount_points.insert(linkname);
125635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme        } else {
126635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme            ALOGE("Unable to add mountinfo %s to zip file\n", path);
127635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme        }
128635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    }
129635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme}
130635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme
131635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Lemevoid add_mountinfo() {
132635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    if (!zip_writer) return;
133635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    const char *title = "MOUNT INFO";
134635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    mount_points.clear();
135635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    DurationReporter duration_reporter(title);
136635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    for_each_pid(do_mountinfo, NULL);
137635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    printf("%s: %d entries added to zip file\n", title, mount_points.size());
138635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme}
139635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme
1402db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevågstatic void dump_dev_files(const char *title, const char *driverpath, const char *filename)
1412db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg{
1422db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    DIR *d;
1432db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    struct dirent *de;
1442db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    char path[PATH_MAX];
1452db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg
1462db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    d = opendir(driverpath);
1472db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    if (d == NULL) {
1482db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg        return;
1492db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    }
1502db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg
1512db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    while ((de = readdir(d))) {
1522db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg        if (de->d_type != DT_LNK) {
1532db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg            continue;
1542db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg        }
1552db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg        snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
1562db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg        dump_file(title, path);
1572db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    }
1582db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg
1592db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    closedir(d);
1602db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg}
1612db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg
162326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzynstatic bool skip_not_stat(const char *path) {
163326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    static const char stat[] = "/stat";
164326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    size_t len = strlen(path);
165326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (path[len - 1] == '/') { /* Directory? */
166326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        return false;
167326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
168326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
169326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn}
170326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
171e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemestatic bool skip_none(const char *path) {
172e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    return false;
173e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme}
174e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
175326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzynstatic const char mmcblk0[] = "/sys/block/mmcblk0/";
1768f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzynunsigned long worst_write_perf = 20000; /* in KB/s */
177326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
178326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzynstatic int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
179326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    unsigned long fields[11], read_perf, write_perf;
180326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    bool z;
181326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    char *cp, *buffer = NULL;
182326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    size_t i = 0;
183326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    FILE *fp = fdopen(fd, "rb");
184326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    getline(&buffer, &i, fp);
185326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    fclose(fp);
186326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (!buffer) {
187326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        return -errno;
188326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
189326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    i = strlen(buffer);
190326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    while ((i > 0) && (buffer[i - 1] == '\n')) {
191326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        buffer[--i] = '\0';
192326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
193326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (!*buffer) {
194326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        free(buffer);
195326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        return 0;
196326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
197326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    z = true;
198326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
199326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        fields[i] = strtol(cp, &cp, 0);
200326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        if (fields[i] != 0) {
201326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn            z = false;
202326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        }
203326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
204326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (z) { /* never accessed */
205326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        free(buffer);
206326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        return 0;
207326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
208326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
209326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
210326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        path += sizeof(mmcblk0) - 1;
211326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
212326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
213326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    printf("%s: %s\n", path, buffer);
214326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    free(buffer);
215326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
216326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    read_perf = 0;
217326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (fields[3]) {
218326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        read_perf = 512 * fields[2] / fields[3];
219326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
220326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    write_perf = 0;
221326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (fields[7]) {
222326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        write_perf = 512 * fields[6] / fields[7];
223326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
224326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    printf("%s: read: %luKB/s write: %luKB/s\n", path, read_perf, write_perf);
2258f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if ((write_perf > 1) && (write_perf < worst_write_perf)) {
2268f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        worst_write_perf = write_perf;
2278f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
228326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    return 0;
229326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn}
230326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
2318f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn/* Copied policy from system/core/logd/LogBuffer.cpp */
2328f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2338f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn#define LOG_BUFFER_SIZE (256 * 1024)
2348f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
2358f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
2368f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2378f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzynstatic bool valid_size(unsigned long value) {
2388f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
2398f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        return false;
2408f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
2418f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2428f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    long pages = sysconf(_SC_PHYS_PAGES);
2438f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (pages < 1) {
2448f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        return true;
2458f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
2468f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2478f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    long pagesize = sysconf(_SC_PAGESIZE);
2488f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (pagesize <= 1) {
2498f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        pagesize = PAGE_SIZE;
2508f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
2518f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2528f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    // maximum memory impact a somewhat arbitrary ~3%
2538f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    pages = (pages + 31) / 32;
2548f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    unsigned long maximum = pages * pagesize;
2558f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2568f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
2578f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        return true;
2588f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
2598f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2608f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    return value <= maximum;
2618f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn}
2628f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2638f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzynstatic unsigned long property_get_size(const char *key) {
2648f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    unsigned long value;
2658f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    char *cp, property[PROPERTY_VALUE_MAX];
2668f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2678f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    property_get(key, property, "");
2688f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    value = strtoul(property, &cp, 10);
2698f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2708f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    switch(*cp) {
2718f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    case 'm':
2728f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    case 'M':
2738f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        value *= 1024;
2748f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    /* FALLTHRU */
2758f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    case 'k':
2768f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    case 'K':
2778f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        value *= 1024;
2788f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    /* FALLTHRU */
2798f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    case '\0':
2808f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        break;
2818f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2828f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    default:
2838f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        value = 0;
2848f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
2858f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2868f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (!valid_size(value)) {
2878f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        value = 0;
2888f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
2898f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2908f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    return value;
2918f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn}
2928f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2938f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn/* timeout in ms */
2948620bb4118a68721d10c29529dc6978847d08d00Felipe Lemestatic unsigned long logcat_timeout(const char *name) {
2958f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    static const char global_tuneable[] = "persist.logd.size"; // Settings App
2968f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    static const char global_default[] = "ro.logd.size";       // BoardConfig.mk
2978f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    char key[PROP_NAME_MAX];
2988f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    unsigned long property_size, default_size;
2998f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3008f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    default_size = property_get_size(global_tuneable);
3018f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (!default_size) {
3028f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        default_size = property_get_size(global_default);
3038f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
3048f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3058f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
3068f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    property_size = property_get_size(key);
3078f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3088f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (!property_size) {
3098f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        snprintf(key, sizeof(key), "%s.%s", global_default, name);
3108f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        property_size = property_get_size(key);
3118f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
3128f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3138f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (!property_size) {
3148f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        property_size = default_size;
3158f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
3168f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3178f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (!property_size) {
3188f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        property_size = LOG_BUFFER_SIZE;
3198f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
3208f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3218f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    /* Engineering margin is ten-fold our guess */
3228f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    return 10 * (property_size + worst_write_perf) / worst_write_perf;
3238f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn}
3248f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3258f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn/* End copy from system/core/logd/LogBuffer.cpp */
3268f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
327f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross/* dumps the current system state to stdout */
32878f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Lemestatic void print_header() {
329f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
330f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
331f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char network[PROPERTY_VALUE_MAX], date[80];
332f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
333f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ro.build.display.id", build, "(unknown)");
334f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ro.build.fingerprint", fingerprint, "(unknown)");
335f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ro.build.type", build_type, "(unknown)");
336f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ro.baseband", radio, "(unknown)");
337f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ro.bootloader", bootloader, "(unknown)");
338f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("gsm.operator.alpha", network, "(unknown)");
339f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
340f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
341f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
342f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== dumpstate: %s\n", date);
343f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
344f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
345f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("\n");
346f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Build: %s\n", build);
347f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */
348f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Bootloader: %s\n", bootloader);
349f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Radio: %s\n", radio);
350f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Network: %s\n", network);
351f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
352f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Kernel: ");
353f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/proc/version");
354f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
355f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("\n");
35678f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme}
35778f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme
358e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme/* adds a new entry to the existing zip file. */
359e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemestatic bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
360e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(),
361e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            ZipWriter::kCompress, get_mtime(fd, now));
362e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    if (err) {
363e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        ALOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(), ZipWriter::ErrorCodeString(err));
364e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        return false;
365e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    }
366e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
367e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    while (1) {
368e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        std::vector<uint8_t> buffer(65536);
369e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), sizeof(buffer)));
370e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        if (bytes_read == 0) {
371e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            break;
372e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        } else if (bytes_read == -1) {
373e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            ALOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
374e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            return false;
375e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        }
376e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        err = zip_writer->WriteBytes(buffer.data(), bytes_read);
377e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        if (err) {
378e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            ALOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
379e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            return false;
380e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        }
381e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    }
382e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
383e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    err = zip_writer->FinishEntry();
384e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    if (err) {
385e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        ALOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
386e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        return false;
387e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    }
388e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
389e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    return true;
390e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme}
391e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
392e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme/* adds a new entry to the existing zip file. */
393e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemestatic bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
394e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    ScopedFd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
395e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    if (fd.get() == -1) {
396e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        ALOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
397e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        return false;
398e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    }
399e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
400e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    return add_zip_entry_from_fd(entry_name, fd.get());
401e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme}
402e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
403e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme/* adds a file to the existing zipped bugreport */
404e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemestatic int _add_file_from_fd(const char *title, const char *path, int fd) {
405e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
406e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme}
407e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
408e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme/* adds all files from a directory to the zipped bugreport file */
409e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemevoid add_dir(const char *dir, bool recursive) {
410e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    if (!zip_writer) return;
411e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    DurationReporter duration_reporter(dir);
412e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd);
413e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme}
414e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
41578f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Lemestatic void dumpstate(const std::string& screenshot_path) {
416e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    std::unique_ptr<DurationReporter> duration_reporter(new DurationReporter("DUMPSTATE"));
41778f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    unsigned long timeout;
418f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
4192db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
420f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("UPTIME", 10, "uptime", NULL);
421326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
4228c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
423f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("MEMORY INFO", "/proc/meminfo");
424b32c7e14ccc6507f6ce3fc02414ba04b797f4558Elliott Hughes    run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-H", NULL);
4252b1f88b6ac78e330ff006da6fecf8bc9d976ec67Nick Kralevich    run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
426f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
427f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("VMALLOC INFO", "/proc/vmallocinfo");
428f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("SLAB INFO", "/proc/slabinfo");
429f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("ZONEINFO", "/proc/zoneinfo");
430f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
431f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BUDDYINFO", "/proc/buddyinfo");
4322281af967dd840aade7bc55b19ea7df0e6da36f2Colin Cross    dump_file("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
433f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
434f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("KERNEL WAKELOCKS", "/proc/wakelocks");
43529e27a84c144fe3b941648094cad2a3f1e61e8b3Todd Poynor    dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
436f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
43785aea748861b5665e68b786b55f1c798f56fc0daMathias Agopian    dump_file("KERNEL SYNC", "/d/sync");
438f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
439a3533a3ae6bf8d0e1780c153cafdec86926ec22cElliott Hughes    run_command("PROCESSES AND THREADS", 10, "ps", "-Z", "-t", "-p", "-P", NULL);
440b82c925d3cd54d5eff9f4f9e6d5aeb41f75365f5Nick Kralevich    run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
441f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
4424db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    run_command("ROUTE", 10, "route", NULL);
4434db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    run_command("PRINTENV", 10, "printenv", NULL);
4444db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    run_command("NETSTAT", 10, "netstat", NULL);
4454db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    run_command("LSMOD", 10, "lsmod", NULL);
4464db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
447f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    do_dmesg();
448f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
449f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
4501dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
4511dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
452f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
4536e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    if (!screenshot_path.empty()) {
454e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme        ALOGI("taking late screenshot\n");
455e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme        take_screenshot(screenshot_path);
4566e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        ALOGI("wrote screenshot: %s\n", screenshot_path.c_str());
4575a93003d3f0d1808b6dcd9928041ec62ea7f67adJeff Sharkey    }
4585a93003d3f0d1808b6dcd9928041ec62ea7f67adJeff Sharkey
459f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
4608f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    // calculate timeout
4618f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
4628f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (timeout < 20000) {
4638f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        timeout = 20000;
4648f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
4657831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn    run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
4667831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                        "-v", "printable",
4677831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                        "-d",
4687831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                        "*:v", NULL);
469c7ad8cb82f035576c28707a8cbeb16b7ead2a4e7Mark Salyzyn    timeout = logcat_timeout("events") + logcat_timeout("security");
4708f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (timeout < 20000) {
4718f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        timeout = 20000;
4728f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
4737831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn    run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
474c7ad8cb82f035576c28707a8cbeb16b7ead2a4e7Mark Salyzyn                                                       "-b", "security",
4757831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-v", "threadtime",
4767831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-v", "printable",
4777831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-d",
4787831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "*:v", NULL);
4798f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    timeout = logcat_timeout("radio");
4808f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (timeout < 20000) {
4818f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        timeout = 20000;
4828f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
4837831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn    run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
4847831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-v", "threadtime",
4857831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-v", "printable",
4867831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-d",
4877831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "*:v", NULL);
488f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
489ecc0763e6c96c418ea4ee6c993d58d16a58407b3Mark Salyzyn    run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
490ecc0763e6c96c418ea4ee6c993d58d16a58407b3Mark Salyzyn
491804339a59e4abcbcf5a50a60ff0543e6b404e572Sharvil Nanavati    run_command("RAFT LOGS", 600, SU_PATH, "root", "logcompressor", "-r", RAFT_DIR, NULL);
4928d4cb7ffc11050eebb4d06684e0eb14d9aadacb5Sharvil Nanavati
493f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* show the traces we collected in main(), if that was done */
494f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (dump_traces_path != NULL) {
495f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        dump_file("VM TRACES JUST NOW", dump_traces_path);
496f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
497f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
498f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* only show ANR traces if they're less than 15 minutes old */
499f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    struct stat st;
500f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char anr_traces_path[PATH_MAX];
501f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
502f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (!anr_traces_path[0]) {
503f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
504f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    } else {
50554bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris      int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
50654bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris                                       O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
5077dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris      if (fd < 0) {
5087dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris          printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
5097dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris      } else {
5107dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris          dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
5117dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris      }
512f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
513f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
514f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* slow traces for slow operations */
515f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (anr_traces_path[0] != 0) {
516f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        int tail = strlen(anr_traces_path)-1;
517f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        while (tail > 0 && anr_traces_path[tail] != '/') {
518f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            tail--;
519f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
520f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        int i = 0;
521f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        while (1) {
522f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
523f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            if (stat(anr_traces_path, &st)) {
524f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                // No traces file at this index, done with the files.
525f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                break;
526f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            }
527f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            dump_file("VM TRACES WHEN SLOW", anr_traces_path);
528f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            i++;
529f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
530f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
531f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
5327dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    int dumped = 0;
5337dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
5347dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        if (tombstone_data[i].fd != -1) {
535e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            const char *name = tombstone_data[i].name;
536e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            int fd = tombstone_data[i].fd;
5377dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris            dumped = 1;
538e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            if (zip_writer) {
539e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme                if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
540e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme                    ALOGE("Unable to add tombstone %s to zip file\n", name);
541e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme                }
542e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            } else {
543e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme                dump_file_from_fd("TOMBSTONE", name, fd);
544e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            }
545e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            close(fd);
5467dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris            tombstone_data[i].fd = -1;
5477dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        }
5487dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    }
5497dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    if (!dumped) {
5507dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
5517dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    }
5527dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
553f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("NETWORK DEV INFO", "/proc/net/dev");
554f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
555012c2ea5651a56218a4359c78db26dd700d9930bJP Abgrall    dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
556f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
557f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
558f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
5592a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor    if (!stat(PSTORE_LAST_KMSG, &st)) {
5602a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor        /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
5612a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor        dump_file("LAST KMSG", PSTORE_LAST_KMSG);
5622a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor    } else {
5632a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor        /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
5642a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor        dump_file("LAST KMSG", "/proc/last_kmsg");
5652a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor    }
5662a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor
5672262c16372570f57d3107d574abe2c80825d286eMark Salyzyn    /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
5687831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn    run_command("LAST LOGCAT", 10, "logcat", "-L",
5697831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                             "-b", "all",
5707831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                             "-v", "threadtime",
5717831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                             "-v", "printable",
5727831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                             "-d",
5737831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                             "*:v", NULL);
5742262c16372570f57d3107d574abe2c80825d286eMark Salyzyn
575f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
576a59828a5d2740433164872e9a0b44363e2ba0cd4Elliott Hughes
577a59828a5d2740433164872e9a0b44363e2ba0cd4Elliott Hughes    run_command("NETWORK INTERFACES", 10, "ip", "link", NULL);
578d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti
579d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti    run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL);
580d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti    run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL);
581d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti
582f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("IP RULES", 10, "ip", "rule", "show", NULL);
583f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
5842b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran
5852b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran    dump_route_tables();
5862b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran
587d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti    run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
588d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti    run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
589d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti
590f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("IPTABLES", 10, SU_PATH, "root", "iptables", "-L", "-nvx", NULL);
591f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("IP6TABLES", 10, SU_PATH, "root", "ip6tables", "-L", "-nvx", NULL);
592012c2ea5651a56218a4359c78db26dd700d9930bJP Abgrall    run_command("IPTABLE NAT", 10, SU_PATH, "root", "iptables", "-t", "nat", "-L", "-nvx", NULL);
593012c2ea5651a56218a4359c78db26dd700d9930bJP Abgrall    /* no ip6 nat */
594012c2ea5651a56218a4359c78db26dd700d9930bJP Abgrall    run_command("IPTABLE RAW", 10, SU_PATH, "root", "iptables", "-t", "raw", "-L", "-nvx", NULL);
595012c2ea5651a56218a4359c78db26dd700d9930bJP Abgrall    run_command("IP6TABLE RAW", 10, SU_PATH, "root", "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
596f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
597f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("WIFI NETWORKS", 20,
5981d6b97c869718001010cce3db387c73fd11bf32eDmitry Shmidt            SU_PATH, "root", "wpa_cli", "IFNAME=wlan0", "list_networks", NULL);
599f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
600c11f56e5615c5d388c072705322df5bcf22c2012Dmitry Shmidt#ifdef FWDUMP_bcmdhd
6016afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("ND OFFLOAD TABLE", 5,
6026afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti            SU_PATH, "root", "wlutil", "nd_hostip", NULL);
6036afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
6046afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
605c11f56e5615c5d388c072705322df5bcf22c2012Dmitry Shmidt            SU_PATH, "root", "wlutil", "counters", NULL);
6066afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
6076afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("ND OFFLOAD STATUS (1)", 5,
6086afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti            SU_PATH, "root", "wlutil", "nd_status", NULL);
6096afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
610c11f56e5615c5d388c072705322df5bcf22c2012Dmitry Shmidt#endif
6110b2c9268265e9a165551eaa66cb461d3fab8b564Dmitry Shmidt    dump_file("INTERRUPTS (1)", "/proc/interrupts");
6120b2c9268265e9a165551eaa66cb461d3fab8b564Dmitry Shmidt
6136afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "connectivity", "--diag", NULL);
6146afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
615c11f56e5615c5d388c072705322df5bcf22c2012Dmitry Shmidt#ifdef FWDUMP_bcmdhd
616f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("DUMP WIFI STATUS", 20,
617f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
6186afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
6196afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
620f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            SU_PATH, "root", "wlutil", "counters", NULL);
6216afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
6226afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("ND OFFLOAD STATUS (2)", 5,
6236afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti            SU_PATH, "root", "wlutil", "nd_status", NULL);
624f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#endif
6250b2c9268265e9a165551eaa66cb461d3fab8b564Dmitry Shmidt    dump_file("INTERRUPTS (2)", "/proc/interrupts");
626f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
627f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    print_properties();
628f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
629f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
630f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
631f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
6328f75fa7bcfec553eddb59b919b44d7a93c9846a1Ken Sumrall    run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);
633f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
634f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
635f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
636f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("------ BACKLIGHTS ------\n");
637f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("LCD brightness=");
638f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness");
639f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Button brightness=");
640f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/sys/class/leds/button-backlight/brightness");
641f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Keyboard brightness=");
642f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/sys/class/leds/keyboard-backlight/brightness");
643f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("ALS mode=");
644f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/sys/class/leds/lcd-backlight/als");
645f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("LCD driver registers:\n");
646f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
647f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("\n");
648f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
649f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* Binder state is expensive to look at as it uses a lot of memory. */
650f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
651f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
652f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
653f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
654f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
655f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
656f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
657f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== Board\n");
658f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
659f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
660f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dumpstate_board();
661f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("\n");
662f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
663f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* Migrate the ril_dumpstate to a dumpstate_board()? */
664f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
665f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
666f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
667f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        if (0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1)) {
668f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            // su does not exist on user builds, so try running without it.
669f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            // This way any implementations of vril-dump that do not require
670f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            // root can run on user builds.
671f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
672f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                    "vril-dump", NULL);
673f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        } else {
674f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
675f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                    SU_PATH, "root", "vril-dump", NULL);
676f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
677f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
678f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
679f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
680f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== Android Framework Services\n");
681f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
682f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
683f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* the full dumpsys is starting to take a long time, so we need
684f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross       to increase its timeout.  we really need to do the timeouts in
685f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross       dumpsys itself... */
686f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("DUMPSYS", 60, "dumpsys", NULL);
687f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
688f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
68902bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn    printf("== Checkins\n");
69002bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn    printf("========================================================\n");
69102bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn
69259b1516f4cefcfd599f4e5e9c4a227a48d1ace65Dianne Hackborn    run_command("CHECKIN BATTERYSTATS", 30, "dumpsys", "batterystats", "-c", NULL);
6933e5fa73722c100fc9017c7a47b17a8e727aa34e1Dianne Hackborn    run_command("CHECKIN MEMINFO", 30, "dumpsys", "meminfo", "--checkin", NULL);
69402bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn    run_command("CHECKIN NETSTATS", 30, "dumpsys", "netstats", "--checkin", NULL);
6955cd46aa3399ddeaf12a211390dfde66c796ab299Dianne Hackborn    run_command("CHECKIN PROCSTATS", 30, "dumpsys", "procstats", "-c", NULL);
6961bd5068a5180ac12dda374e15c7b1f70e8334284Dianne Hackborn    run_command("CHECKIN USAGESTATS", 30, "dumpsys", "usagestats", "-c", NULL);
6978b3e133e413774047da8005771f57c21dd31e1e3Ashish Sharma    run_command("CHECKIN PACKAGE", 30, "dumpsys", "package", "--checkin", NULL);
69802bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn
69902bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn    printf("========================================================\n");
700f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== Running Application Activities\n");
701f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
702f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
703f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("APP ACTIVITIES", 30, "dumpsys", "activity", "all", NULL);
704f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
705f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
706f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== Running Application Services\n");
707f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
708f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
709f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("APP SERVICES", 30, "dumpsys", "activity", "service", "all", NULL);
710f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
711f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
712f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== Running Application Providers\n");
713f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
714f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
715f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("APP SERVICES", 30, "dumpsys", "activity", "provider", "all", NULL);
716f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
717f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
718f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
719f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== dumpstate: done\n");
720f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
721f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
722f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
723f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossstatic void usage() {
7241f794c442cc63f7962c21e8e712adeca338af63eJohn Michelau    fprintf(stderr, "usage: dumpstate [-b soundfile] [-e soundfile] [-o file [-d] [-p] [-z]] [-s] [-q]\n"
725f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -o: write to file (instead of stdout)\n"
726f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -d: append date to filename (requires -o)\n"
7276e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            "  -z: generates zipped file (requires -o)\n"
728f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -p: capture screenshot to filename.png (requires -o)\n"
729f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -s: write output to control socket (for init)\n"
730f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -b: play sound file instead of vibrate, at beginning of job\n"
731f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -e: play sound file instead of vibrate, at end of job\n"
7321f794c442cc63f7962c21e8e712adeca338af63eJohn Michelau            "  -q: disable vibrate\n"
73336b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            "  -B: send broadcast when finished (requires -o)\n"
73471bbfc57974331dce79242ce806d92035fce06baFelipe Leme            "  -P: send broadacast when started and update system properties on progress (requires -o and -B)\n"
7354db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski            "  -R: take bugreport in remote mode (requires -o, -z, -d and -B, shouldn't be used with -P)\n"
7362a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor                );
737f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
738f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
739885f888c55587e9366542b5155a06c321cde175aJohn Michelaustatic void sigpipe_handler(int n) {
7402e671bbdb741c2926b6df7b240fdc31c7361f330Andres Morales    // don't complain to stderr or stdout
7412e671bbdb741c2926b6df7b240fdc31c7361f330Andres Morales    _exit(EXIT_FAILURE);
742885f888c55587e9366542b5155a06c321cde175aJohn Michelau}
743885f888c55587e9366542b5155a06c321cde175aJohn Michelau
7441e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
7451e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme   temporary file.
7461e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme */
747e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemestatic bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
7481e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        time_t now) {
749e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    if (!add_zip_entry(bugreport_name, bugreport_path)) {
7501e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        ALOGE("Failed to add text entry to .zip file\n");
7516e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        return false;
7526e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    }
7536e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
754e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    int32_t err = zip_writer->Finish();
7551e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    if (err) {
756e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        ALOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
7576e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        return false;
7586e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    }
7596e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
7601e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    if (remove(bugreport_path.c_str())) {
7611e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
7621e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    }
7631e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme
7646e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    return true;
7656e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme}
7666e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
7674db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinskistatic std::string SHA256_file_hash(std::string filepath) {
7684db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    ScopedFd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
7694db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    if (fd.get() == -1) {
7704db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        ALOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
7714db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        return NULL;
7724db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    }
7734db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
7744db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    SHA256_CTX ctx;
7754db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    SHA256_init(&ctx);
7764db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
7774db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    std::vector<uint8_t> buffer(65536);
7784db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    while (1) {
7794db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
7804db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        if (bytes_read == 0) {
7814db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski            break;
7824db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        } else if (bytes_read == -1) {
7834db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski            ALOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
7844db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski            return NULL;
7854db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        }
7864db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
7874db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        SHA256_update(&ctx, buffer.data(), bytes_read);
7884db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    }
7894db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
7904db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    uint8_t hash[SHA256_DIGEST_SIZE];
7914db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    memcpy(hash, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
7924db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    char hash_buffer[SHA256_DIGEST_SIZE * 2 + 1];
7934db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    for(int i = 0; i < SHA256_DIGEST_SIZE; i++) {
7944db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        snprintf(hash_buffer + (i * 2), sizeof(hash_buffer), "%02x", hash[i]);
7954db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    }
7964db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    hash_buffer[sizeof(hash_buffer) - 1] = 0;
7974db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    return std::string(hash_buffer);
7984db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski}
7994db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
8004db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
801f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossint main(int argc, char *argv[]) {
802885f888c55587e9366542b5155a06c321cde175aJohn Michelau    struct sigaction sigact;
803f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    int do_add_date = 0;
8046e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    int do_zip_file = 0;
8051f794c442cc63f7962c21e8e712adeca338af63eJohn Michelau    int do_vibrate = 1;
806f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char* use_outfile = 0;
807f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    int use_socket = 0;
808f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    int do_fb = 0;
80927f9e6d849fce956c9b8f1ad5c3d9a954501a76bJeff Sharkey    int do_broadcast = 0;
810e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    int do_early_screenshot = 0;
8114db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    int is_remote_mode = 0;
812f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
813e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    now = time(NULL);
814e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
8151e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    if (getuid() != 0) {
8161e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        // Old versions of the adb client would call the
8171e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        // dumpstate command directly. Newer clients
8181e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        // call /system/bin/bugreport instead. If we detect
8191e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        // we're being called incorrectly, then exec the
8201e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        // correct program.
8211e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        return execl("/system/bin/bugreport", "/system/bin/bugreport", NULL);
8221e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    }
823f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
8241dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    ALOGI("begin\n");
8252e671bbdb741c2926b6df7b240fdc31c7361f330Andres Morales
8261dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* clear SIGPIPE handler */
827885f888c55587e9366542b5155a06c321cde175aJohn Michelau    memset(&sigact, 0, sizeof(sigact));
828885f888c55587e9366542b5155a06c321cde175aJohn Michelau    sigact.sa_handler = sigpipe_handler;
829885f888c55587e9366542b5155a06c321cde175aJohn Michelau    sigaction(SIGPIPE, &sigact, NULL);
8303e03d3fb6a4cb93f5f978f9d2eed7b7cc62a06a6JP Abgrall
831f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* set as high priority, and protect from OOM killer */
832f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    setpriority(PRIO_PROCESS, 0, -20);
833cd67e9f059e270017d5defd8784c89dd8e6bcde7Nick Kralevich    FILE *oom_adj = fopen("/proc/self/oom_adj", "we");
834f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (oom_adj) {
835f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        fputs("-17", oom_adj);
836f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        fclose(oom_adj);
837f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
838f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
8391dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* parse arguments */
840f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    int c;
8414db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    while ((c = getopt(argc, argv, "dho:svqzpPBR")) != -1) {
842f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        switch (c) {
84371bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'd': do_add_date = 1;          break;
84471bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'z': do_zip_file = 1;          break;
84571bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'o': use_outfile = optarg;     break;
84671bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 's': use_socket = 1;           break;
847f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            case 'v': break;  // compatibility no-op
84871bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'q': do_vibrate = 0;           break;
84971bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'p': do_fb = 1;                break;
85071bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'P': do_update_progress = 1;   break;
8514db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski            case 'R': is_remote_mode = 1;       break;
85271bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'B': do_broadcast = 1;         break;
853f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            case '?': printf("\n");
854f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            case 'h':
855f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                usage();
856f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                exit(1);
857f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
858f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
859f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
86071bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) {
8616e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        usage();
8626e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        exit(1);
8636e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    }
8646e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
86571bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (do_update_progress && !do_broadcast) {
86671bbfc57974331dce79242ce806d92035fce06baFelipe Leme        usage();
86771bbfc57974331dce79242ce806d92035fce06baFelipe Leme        exit(1);
86871bbfc57974331dce79242ce806d92035fce06baFelipe Leme    }
8696e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
8704db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    if (is_remote_mode && (do_update_progress || !do_broadcast || !do_zip_file || !do_add_date)) {
8714db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        usage();
8724db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        exit(1);
8734db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    }
8744db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
875e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    do_early_screenshot = do_update_progress;
876e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme
877ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris    // If we are going to use a socket, do it as early as possible
878ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris    // to avoid timeouts from bugreport.
879ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris    if (use_socket) {
880ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris        redirect_to_socket(stdout, "dumpstate");
881ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris    }
882ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris
883ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    /* full path of the directory where the bug report files will be written */
884ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    std::string bugreport_dir;
885ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
886ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    /* full path of the temporary file containing the bug report */
887ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    std::string tmp_path;
888ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
889e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    /* full path of the temporary file containing the screenshot (when requested) */
890e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    std::string screenshot_path;
891e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme
892ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    /* base name (without suffix or extensions) of the bug report files */
893ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    std::string base_name;
894ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
895ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    /* suffix of the bug report files - it's typically the date (when invoked with -d),
896ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme     * although it could be changed by the user using a system property */
897ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    std::string suffix;
89871bbfc57974331dce79242ce806d92035fce06baFelipe Leme
89971bbfc57974331dce79242ce806d92035fce06baFelipe Leme    /* pointer to the actual path, be it zip or text */
90071bbfc57974331dce79242ce806d92035fce06baFelipe Leme    std::string path;
90171bbfc57974331dce79242ce806d92035fce06baFelipe Leme
902635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    /* pointer to the zipped file */
9031e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
90471bbfc57974331dce79242ce806d92035fce06baFelipe Leme
905ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    /* redirect output if needed */
90671bbfc57974331dce79242ce806d92035fce06baFelipe Leme    bool is_redirecting = !use_socket && use_outfile;
90771bbfc57974331dce79242ce806d92035fce06baFelipe Leme
90871bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (is_redirecting) {
909ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        bugreport_dir = dirname(use_outfile);
910ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        base_name = basename(use_outfile);
91171bbfc57974331dce79242ce806d92035fce06baFelipe Leme        if (do_add_date) {
91271bbfc57974331dce79242ce806d92035fce06baFelipe Leme            char date[80];
913ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
914ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            suffix = date;
915ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        } else {
916ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            suffix = "undated";
91771bbfc57974331dce79242ce806d92035fce06baFelipe Leme        }
91871bbfc57974331dce79242ce806d92035fce06baFelipe Leme        if (do_fb) {
919ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            // TODO: if dumpstate was an object, the paths could be internal variables and then
920ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            // we could have a function to calculate the derived values, such as:
921ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            //     screenshot_path = GetPath(".png");
922ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png";
92371bbfc57974331dce79242ce806d92035fce06baFelipe Leme        }
924ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
92571bbfc57974331dce79242ce806d92035fce06baFelipe Leme
926ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        ALOGD("Bugreport dir: %s\nBase name: %s\nSuffix: %s\nTemporary path: %s\n"
927ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                "Screenshot path: %s\n", bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(),
928ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                tmp_path.c_str(), screenshot_path.c_str());
92971bbfc57974331dce79242ce806d92035fce06baFelipe Leme
9301e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        if (do_zip_file) {
9311e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            ALOGD("Creating initial .zip file");
9321e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
9331e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            zip_file.reset(fopen(path.c_str(), "wb"));
9341e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            if (!zip_file) {
9351e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme                ALOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
9361e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme                do_zip_file = 0;
9371e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            } else {
9381e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme                zip_writer.reset(new ZipWriter(zip_file.get()));
9391e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            }
9401e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        }
9411e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme
94271bbfc57974331dce79242ce806d92035fce06baFelipe Leme        if (do_update_progress) {
943ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            std::vector<std::string> am_args = {
944ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                 "--receiver-permission", "android.permission.DUMP",
945ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                 "--es", "android.intent.extra.NAME", suffix,
946ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
947ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
948ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            };
949ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
95071bbfc57974331dce79242ce806d92035fce06baFelipe Leme        }
95171bbfc57974331dce79242ce806d92035fce06baFelipe Leme    }
95271bbfc57974331dce79242ce806d92035fce06baFelipe Leme
95378f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    print_header();
95478f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme
9551dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* open the vibrator before dropping root */
9566e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
9571f794c442cc63f7962c21e8e712adeca338af63eJohn Michelau    if (do_vibrate) {
9586e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
9591dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown        if (vibrator) {
9606e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            vibrate(vibrator.get(), 150);
9611dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown        }
9621f794c442cc63f7962c21e8e712adeca338af63eJohn Michelau    }
963f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
9643634a1e3459cb609da709646107e246cafbc01f9Felipe Leme    if (do_fb && do_early_screenshot) {
9653634a1e3459cb609da709646107e246cafbc01f9Felipe Leme        if (screenshot_path.empty()) {
9663634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            // should not have happened
9673634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            ALOGE("INTERNAL ERROR: skipping early screenshot because path was not set");
9683634a1e3459cb609da709646107e246cafbc01f9Felipe Leme        } else {
9693634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            ALOGI("taking early screenshot\n");
9703634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            take_screenshot(screenshot_path);
9713634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            ALOGI("wrote screenshot: %s\n", screenshot_path.c_str());
9723634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
9733634a1e3459cb609da709646107e246cafbc01f9Felipe Leme                ALOGE("Unable to change ownership of screenshot file %s: %s\n",
9743634a1e3459cb609da709646107e246cafbc01f9Felipe Leme                        screenshot_path.c_str(), strerror(errno));
9753634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            }
976e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme        }
977e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    }
978e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme
9791e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    if (do_zip_file) {
9801e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
9811e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            ALOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
9821e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        }
9831e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    }
9841e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme
985f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* read /proc/cmdline before dropping root */
986cd67e9f059e270017d5defd8784c89dd8e6bcde7Nick Kralevich    FILE *cmdline = fopen("/proc/cmdline", "re");
9876e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    if (cmdline) {
988f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
989f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        fclose(cmdline);
990f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
991f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
9921dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* collect stack traces from Dalvik and native processes (needs root) */
9931dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    dump_traces_path = dump_traces();
9941dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown
995635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    /* Get the tombstone fds, recovery files, and mount info here while we are running as root. */
9961dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    get_tombstone_fds(tombstone_data);
997e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    add_dir(RECOVERY_DIR, true);
998635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    add_mountinfo();
9991dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown
10001dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* ensure we will keep capabilities when we drop root */
10011e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
10021e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        ALOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
10031e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        return -1;
10041e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    }
1005f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
10061e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    /* switch to non-root user and group */
10071e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW,
1008ab46a4922655bc75848660da4268ab85d72a6010Nick Kralevich            AID_MOUNT, AID_INET, AID_NET_BW_STATS, AID_READPROC };
10091e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
10101e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        ALOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
10111e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        return -1;
10121e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    }
10131e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    if (setgid(AID_SHELL) != 0) {
10141e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        ALOGE("Unable to setgid, aborting: %s\n", strerror(errno));
10151e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        return -1;
10161e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    }
10171e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    if (setuid(AID_SHELL) != 0) {
10181e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        ALOGE("Unable to setuid, aborting: %s\n", strerror(errno));
10191e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        return -1;
10201e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    }
1021f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
10221e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    struct __user_cap_header_struct capheader;
10231e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    struct __user_cap_data_struct capdata[2];
10241e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    memset(&capheader, 0, sizeof(capheader));
10251e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    memset(&capdata, 0, sizeof(capdata));
10261e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    capheader.version = _LINUX_CAPABILITY_VERSION_3;
10271e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    capheader.pid = 0;
10281e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich
10291e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
10301e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG);
10311e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    capdata[0].inheritable = 0;
10321e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    capdata[1].inheritable = 0;
10331e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich
10341e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    if (capset(&capheader, &capdata[0]) < 0) {
10351e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        ALOGE("capset failed: %s\n", strerror(errno));
10361e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        return -1;
1037f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
1038f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
103971bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (is_redirecting) {
10406e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        /* TODO: rather than generating a text file now and zipping it later,
10416e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme           it would be more efficient to redirect stdout to the zip entry
10426e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme           directly, but the libziparchive doesn't support that option yet. */
10436e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
1044f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
1045f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
10463634a1e3459cb609da709646107e246cafbc01f9Felipe Leme    dumpstate(do_early_screenshot ? "": screenshot_path);
1047f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
10481dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* done */
10491dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    if (vibrator) {
10501dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown        for (int i = 0; i < 3; i++) {
10516e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            vibrate(vibrator.get(), 75);
1052f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            usleep((75 + 50) * 1000);
1053f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
1054f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
1055f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
105655b42a67f69767976ff16ab443b3e7142db693e1Felipe Leme    /* close output if needed */
105771bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (is_redirecting) {
1058f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        fclose(stdout);
1059f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
1060f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
10616e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    /* rename or zip the (now complete) .tmp file to its final location */
10626e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    if (use_outfile) {
1063ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
1064ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        /* check if user changed the suffix using system properties */
1065ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        char key[PROPERTY_KEY_MAX];
1066ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        char value[PROPERTY_VALUE_MAX];
1067ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        sprintf(key, "dumpstate.%d.name", getpid());
1068ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        property_get(key, value, "");
1069ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        bool change_suffix= false;
1070ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        if (value[0]) {
1071ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            /* must whitelist which characters are allowed, otherwise it could cross directories */
1072ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            std::regex valid_regex("^[-_a-zA-Z0-9]+$");
1073ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            if (std::regex_match(value, valid_regex)) {
1074ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                change_suffix = true;
1075ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            } else {
1076ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                ALOGE("invalid suffix provided by user: %s", value);
1077ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            }
1078ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        }
1079ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        if (change_suffix) {
1080ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            ALOGI("changing suffix from %s to %s", suffix.c_str(), value);
1081ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            suffix = value;
1082ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            if (!screenshot_path.empty()) {
1083ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                std::string new_screenshot_path =
1084ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                        bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1085ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
1086ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                    ALOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
1087ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                            new_screenshot_path.c_str(), strerror(errno));
1088ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                } else {
1089ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                    screenshot_path = new_screenshot_path;
1090ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                }
1091ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            }
1092ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        }
1093ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
10946e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        bool do_text_file = true;
10956e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        if (do_zip_file) {
10961e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            ALOGD("Adding text entry to .zip bugreport");
1097e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            if (!finish_zip_file(base_name + "-" + suffix + ".txt", tmp_path, now)) {
10981e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme                ALOGE("Failed to finish zip file; sending text bugreport instead\n");
10996e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme                do_text_file = true;
11006e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            } else {
11016e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme                do_text_file = false;
11026e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            }
11036e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        }
11046e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        if (do_text_file) {
1105ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            ALOGD("Generating .txt bugreport");
1106ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt";
1107ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            if (rename(tmp_path.c_str(), path.c_str())) {
1108ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                ALOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
11096e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme                path.clear();
11106e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            }
11116e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        }
1112f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
1113f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
11141dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* tell activity manager we're done */
111571bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (do_broadcast) {
11166e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        if (!path.empty()) {
11176e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            ALOGI("Final bugreport path: %s\n", path.c_str());
111836b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            std::vector<std::string> am_args = {
111936b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme                 "--receiver-permission", "android.permission.DUMP",
112071bbfc57974331dce79242ce806d92035fce06baFelipe Leme                 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
112136b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme                 "--es", "android.intent.extra.BUGREPORT", path
112236b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            };
112336b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            if (do_fb) {
112436b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme                am_args.push_back("--es");
112536b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme                am_args.push_back("android.intent.extra.SCREENSHOT");
112636b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme                am_args.push_back(screenshot_path);
112736b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            }
11284db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski            if (is_remote_mode) {
11294db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski                am_args.push_back("--es");
11304db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski                am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
11314db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski                am_args.push_back(SHA256_file_hash(path));
11324db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski                send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
11334db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski            } else {
11344db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski                send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
11354db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski            }
11366e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        } else {
113771bbfc57974331dce79242ce806d92035fce06baFelipe Leme            ALOGE("Skipping finished broadcast because bugreport could not be generated\n");
11386e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        }
113927f9e6d849fce956c9b8f1ad5c3d9a954501a76bJeff Sharkey    }
114027f9e6d849fce956c9b8f1ad5c3d9a954501a76bJeff Sharkey
1141e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    ALOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
1142f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    ALOGI("done\n");
1143f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
1144f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    return 0;
1145f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
1146