dumpstate.cpp revision cc2a2fa64e22378d980ae0ae95c8865ebea05f69
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
598fecfdda012928bc2fe6d0e66fd4a4c912946254Felipe Lemestatic unsigned long id;
6078f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Lemestatic char build_type[PROPERTY_VALUE_MAX];
61e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemestatic time_t now;
62e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemestatic std::unique_ptr<ZipWriter> zip_writer;
63635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Lemestatic std::set<std::string> mount_points;
64635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Lemevoid add_mountinfo();
65635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Lemestatic bool add_zip_entry(const std::string& entry_name, const std::string& entry_path);
6678f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme
672a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
682a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor
698d4cb7ffc11050eebb4d06684e0eb14d9aadacb5Sharvil Nanavati#define RAFT_DIR "/data/misc/raft/"
70e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme#define RECOVERY_DIR "/cache/recovery"
717dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#define TOMBSTONE_DIR "/data/tombstones"
727dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
737dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris/* Can accomodate a tombstone number up to 9999. */
747dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
757dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#define NUM_TOMBSTONES  10
767dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
777dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferristypedef struct {
787dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris  char name[TOMBSTONE_MAX_LEN];
797dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris  int fd;
807dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris} tombstone_data_t;
817dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
827dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferrisstatic tombstone_data_t tombstone_data[NUM_TOMBSTONES];
837dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
84e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme// Root dir for all files copied as-is into the bugreport
85e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemeconst std::string& ZIP_ROOT_DIR = "FS";
86e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
87809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme/*
88809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme * List of supported zip format versions.
89809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme *
90809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme * See bugreport-format.txt for more info.
91809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme */
92809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme// TODO: change to "v1" before final N build
93809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Lemestatic std::string VERSION_DEFAULT = "v1-dev1";
94809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme// TODO: remove before final N build
95809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Lemestatic std::string VERSION_DUMPSYS_SPLIT = "v1-dev1-dumpsys-split";
96809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme
97e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme/* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones,
98e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme * otherwise gets just those modified in the last half an hour. */
997dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferrisstatic void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
100e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    time_t thirty_minutes_ago = now - 60*30;
1017dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
1027dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
10354bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        int fd = TEMP_FAILURE_RETRY(open(data[i].name,
10454bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris                                         O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
1057dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        struct stat st;
1067dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
107e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) {
108e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        data[i].fd = fd;
1097dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        } else {
110e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        close(fd);
1117dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris            data[i].fd = -1;
1127dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        }
1137dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    }
1147dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris}
1157dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
116635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme// for_each_pid() callback to get mount info about a process.
117635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Lemevoid do_mountinfo(int pid, const char *name) {
118635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    char path[PATH_MAX];
119635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme
120635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
121635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    // are added.
122635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    sprintf(path, "/proc/%d/ns/mnt", pid);
123635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    char linkname[PATH_MAX];
124635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    ssize_t r = readlink(path, linkname, PATH_MAX);
125635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    if (r == -1) {
126cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
127635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme        return;
128635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    }
129635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    linkname[r] = '\0';
130635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme
131635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    if (mount_points.find(linkname) == mount_points.end()) {
132635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme        // First time this mount point was found: add it
133635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme        sprintf(path, "/proc/%d/mountinfo", pid);
134635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme        if (add_zip_entry(ZIP_ROOT_DIR + path, path)) {
135635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme            mount_points.insert(linkname);
136635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme        } else {
137cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme            MYLOGE("Unable to add mountinfo %s to zip file\n", path);
138635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme        }
139635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    }
140635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme}
141635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme
142635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Lemevoid add_mountinfo() {
143635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    if (!zip_writer) return;
144635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    const char *title = "MOUNT INFO";
145635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    mount_points.clear();
146608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    DurationReporter duration_reporter(title, NULL);
147635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    for_each_pid(do_mountinfo, NULL);
1481b0225a4792d92ff67ac8a0aa79352fad40bd805Felipe Leme    MYLOGD("%s: %d entries added to zip file\n", title, (int) mount_points.size());
149635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme}
150635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme
1512db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevågstatic void dump_dev_files(const char *title, const char *driverpath, const char *filename)
1522db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg{
1532db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    DIR *d;
1542db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    struct dirent *de;
1552db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    char path[PATH_MAX];
1562db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg
1572db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    d = opendir(driverpath);
1582db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    if (d == NULL) {
1592db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg        return;
1602db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    }
1612db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg
1622db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    while ((de = readdir(d))) {
1632db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg        if (de->d_type != DT_LNK) {
1642db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg            continue;
1652db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg        }
1662db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg        snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
1672db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg        dump_file(title, path);
1682db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    }
1692db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg
1702db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    closedir(d);
1712db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg}
1722db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg
173326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzynstatic bool skip_not_stat(const char *path) {
174326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    static const char stat[] = "/stat";
175326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    size_t len = strlen(path);
176326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (path[len - 1] == '/') { /* Directory? */
177326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        return false;
178326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
179326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
180326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn}
181326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
182e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemestatic bool skip_none(const char *path) {
183e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    return false;
184e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme}
185e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
186326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzynstatic const char mmcblk0[] = "/sys/block/mmcblk0/";
1878f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzynunsigned long worst_write_perf = 20000; /* in KB/s */
188326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
18901d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
19001d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//  stat offsets
19101d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// Name            units         description
19201d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// ----            -----         -----------
19301d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// read I/Os       requests      number of read I/Os processed
19401d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn#define __STAT_READ_IOS      0
19501d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// read merges     requests      number of read I/Os merged with in-queue I/O
19601d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn#define __STAT_READ_MERGES   1
19701d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// read sectors    sectors       number of sectors read
19801d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn#define __STAT_READ_SECTORS  2
19901d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// read ticks      milliseconds  total wait time for read requests
20001d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn#define __STAT_READ_TICKS    3
20101d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// write I/Os      requests      number of write I/Os processed
20201d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn#define __STAT_WRITE_IOS     4
20301d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// write merges    requests      number of write I/Os merged with in-queue I/O
20401d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn#define __STAT_WRITE_MERGES  5
20501d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// write sectors   sectors       number of sectors written
20601d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn#define __STAT_WRITE_SECTORS 6
20701d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// write ticks     milliseconds  total wait time for write requests
20801d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn#define __STAT_WRITE_TICKS   7
20901d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// in_flight       requests      number of I/Os currently in flight
21001d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn#define __STAT_IN_FLIGHT     8
21101d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// io_ticks        milliseconds  total time this block device has been active
21201d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn#define __STAT_IO_TICKS      9
21301d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// time_in_queue   milliseconds  total wait time for all requests
21401d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn#define __STAT_IN_QUEUE     10
21501d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn#define __STAT_NUMBER_FIELD 11
21601d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
21701d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// read I/Os, write I/Os
21801d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// =====================
21901d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
22001d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// These values increment when an I/O request completes.
22101d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
22201d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// read merges, write merges
22301d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// =========================
22401d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
22501d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// These values increment when an I/O request is merged with an
22601d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// already-queued I/O request.
22701d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
22801d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// read sectors, write sectors
22901d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// ===========================
23001d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
23101d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// These values count the number of sectors read from or written to this
23201d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// block device.  The "sectors" in question are the standard UNIX 512-byte
23301d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// sectors, not any device- or filesystem-specific block size.  The
23401d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// counters are incremented when the I/O completes.
23501d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn#define SECTOR_SIZE 512
23601d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
23701d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// read ticks, write ticks
23801d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// =======================
23901d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
24001d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// These values count the number of milliseconds that I/O requests have
24101d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// waited on this block device.  If there are multiple I/O requests waiting,
24201d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// these values will increase at a rate greater than 1000/second; for
24301d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// example, if 60 read requests wait for an average of 30 ms, the read_ticks
24401d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// field will increase by 60*30 = 1800.
24501d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
24601d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// in_flight
24701d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// =========
24801d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
24901d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// This value counts the number of I/O requests that have been issued to
25001d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// the device driver but have not yet completed.  It does not include I/O
25101d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// requests that are in the queue but not yet issued to the device driver.
25201d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
25301d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// io_ticks
25401d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// ========
25501d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
25601d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// This value counts the number of milliseconds during which the device has
25701d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// had I/O requests queued.
25801d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
25901d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// time_in_queue
26001d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// =============
26101d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
26201d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// This value counts the number of milliseconds that I/O requests have waited
26301d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// on this block device.  If there are multiple I/O requests waiting, this
26401d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// value will increase as the product of the number of milliseconds times the
26501d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn// number of requests waiting (see "read ticks" above for an example).
26601d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn#define S_TO_MS 1000
26701d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn//
26801d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn
269326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzynstatic int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
27001d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn    unsigned long long fields[__STAT_NUMBER_FIELD];
271326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    bool z;
272326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    char *cp, *buffer = NULL;
273326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    size_t i = 0;
274326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    FILE *fp = fdopen(fd, "rb");
275326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    getline(&buffer, &i, fp);
276326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    fclose(fp);
277326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (!buffer) {
278326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        return -errno;
279326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
280326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    i = strlen(buffer);
281326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    while ((i > 0) && (buffer[i - 1] == '\n')) {
282326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        buffer[--i] = '\0';
283326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
284326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (!*buffer) {
285326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        free(buffer);
286326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        return 0;
287326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
288326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    z = true;
289326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
29001d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        fields[i] = strtoull(cp, &cp, 10);
291326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        if (fields[i] != 0) {
292326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn            z = false;
293326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        }
294326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
295326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (z) { /* never accessed */
296326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        free(buffer);
297326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        return 0;
298326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
299326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
300326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
301326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        path += sizeof(mmcblk0) - 1;
302326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
303326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
304326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    printf("%s: %s\n", path, buffer);
305326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    free(buffer);
306326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
30701d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn    if (fields[__STAT_IO_TICKS]) {
30801d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        unsigned long read_perf = 0;
30901d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        unsigned long read_ios = 0;
31001d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        if (fields[__STAT_READ_TICKS]) {
31101d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn            unsigned long long divisor = fields[__STAT_READ_TICKS]
31201d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                                       * fields[__STAT_IO_TICKS];
31301d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn            read_perf = ((unsigned long long)SECTOR_SIZE
31401d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                           * fields[__STAT_READ_SECTORS]
31501d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                           * fields[__STAT_IN_QUEUE] + (divisor >> 1))
31601d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                                        / divisor;
31701d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn            read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
31801d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                           * fields[__STAT_IN_QUEUE] + (divisor >> 1))
31901d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                                        / divisor;
32001d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        }
32101d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn
32201d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        unsigned long write_perf = 0;
32301d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        unsigned long write_ios = 0;
32401d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        if (fields[__STAT_WRITE_TICKS]) {
32501d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn            unsigned long long divisor = fields[__STAT_WRITE_TICKS]
32601d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                                       * fields[__STAT_IO_TICKS];
32701d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn            write_perf = ((unsigned long long)SECTOR_SIZE
32801d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                           * fields[__STAT_WRITE_SECTORS]
32901d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                           * fields[__STAT_IN_QUEUE] + (divisor >> 1))
33001d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                                        / divisor;
33101d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn            write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
33201d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                           * fields[__STAT_IN_QUEUE] + (divisor >> 1))
33301d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                                        / divisor;
33401d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        }
33501d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn
33601d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        unsigned queue = (fields[__STAT_IN_QUEUE]
33701d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                             + (fields[__STAT_IO_TICKS] >> 1))
33801d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                                 / fields[__STAT_IO_TICKS];
33901d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn
34001d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        if (!write_perf && !write_ios) {
34101d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn            printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
34201d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                   path, read_perf, read_ios, queue);
34301d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        } else {
34401d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn            printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
34501d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn                   path, read_perf, read_ios, write_perf, write_ios, queue);
34601d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        }
34701d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn
34801d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        /* bugreport timeout factor adjustment */
34901d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        if ((write_perf > 1) && (write_perf < worst_write_perf)) {
35001d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn            worst_write_perf = write_perf;
35101d6c3935ace93f208fa3d93802b286e7484cfaeMark Salyzyn        }
3528f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
353326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    return 0;
354326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn}
355326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
3568f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn/* Copied policy from system/core/logd/LogBuffer.cpp */
3578f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3588f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn#define LOG_BUFFER_SIZE (256 * 1024)
3598f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
3608f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
3618f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3628f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzynstatic bool valid_size(unsigned long value) {
3638f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
3648f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        return false;
3658f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
3668f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3678f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    long pages = sysconf(_SC_PHYS_PAGES);
3688f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (pages < 1) {
3698f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        return true;
3708f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
3718f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3728f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    long pagesize = sysconf(_SC_PAGESIZE);
3738f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (pagesize <= 1) {
3748f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        pagesize = PAGE_SIZE;
3758f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
3768f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3778f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    // maximum memory impact a somewhat arbitrary ~3%
3788f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    pages = (pages + 31) / 32;
3798f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    unsigned long maximum = pages * pagesize;
3808f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3818f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
3828f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        return true;
3838f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
3848f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3858f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    return value <= maximum;
3868f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn}
3878f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3888f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzynstatic unsigned long property_get_size(const char *key) {
3898f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    unsigned long value;
3908f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    char *cp, property[PROPERTY_VALUE_MAX];
3918f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3928f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    property_get(key, property, "");
3938f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    value = strtoul(property, &cp, 10);
3948f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
3958f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    switch(*cp) {
3968f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    case 'm':
3978f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    case 'M':
3988f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        value *= 1024;
3998f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    /* FALLTHRU */
4008f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    case 'k':
4018f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    case 'K':
4028f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        value *= 1024;
4038f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    /* FALLTHRU */
4048f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    case '\0':
4058f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        break;
4068f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
4078f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    default:
4088f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        value = 0;
4098f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
4108f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
4118f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (!valid_size(value)) {
4128f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        value = 0;
4138f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
4148f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
4158f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    return value;
4168f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn}
4178f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
4188f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn/* timeout in ms */
4198620bb4118a68721d10c29529dc6978847d08d00Felipe Lemestatic unsigned long logcat_timeout(const char *name) {
4208f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    static const char global_tuneable[] = "persist.logd.size"; // Settings App
4218f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    static const char global_default[] = "ro.logd.size";       // BoardConfig.mk
4228f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    char key[PROP_NAME_MAX];
4238f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    unsigned long property_size, default_size;
4248f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
4258f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    default_size = property_get_size(global_tuneable);
4268f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (!default_size) {
4278f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        default_size = property_get_size(global_default);
4288f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
4298f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
4308f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
4318f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    property_size = property_get_size(key);
4328f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
4338f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (!property_size) {
4348f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        snprintf(key, sizeof(key), "%s.%s", global_default, name);
4358f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        property_size = property_get_size(key);
4368f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
4378f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
4388f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (!property_size) {
4398f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        property_size = default_size;
4408f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
4418f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
4428f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (!property_size) {
4438f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        property_size = LOG_BUFFER_SIZE;
4448f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
4458f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
4468f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    /* Engineering margin is ten-fold our guess */
4478f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    return 10 * (property_size + worst_write_perf) / worst_write_perf;
4488f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn}
4498f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
4508f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn/* End copy from system/core/logd/LogBuffer.cpp */
4518f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
452f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross/* dumps the current system state to stdout */
453809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Lemestatic void print_header(std::string version) {
454f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
455f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
456f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char network[PROPERTY_VALUE_MAX], date[80];
457f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
458f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ro.build.display.id", build, "(unknown)");
459f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ro.build.fingerprint", fingerprint, "(unknown)");
460f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ro.build.type", build_type, "(unknown)");
461f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ro.baseband", radio, "(unknown)");
462f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ro.bootloader", bootloader, "(unknown)");
463f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("gsm.operator.alpha", network, "(unknown)");
464f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
465f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
466f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
467f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== dumpstate: %s\n", date);
468f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
469f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
470f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("\n");
471f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Build: %s\n", build);
472f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */
473f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Bootloader: %s\n", bootloader);
474f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Radio: %s\n", radio);
475f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Network: %s\n", network);
476f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
477f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Kernel: ");
478f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/proc/version");
479f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
480809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    printf("Bugreport format version: %s\n", version.c_str());
4818fecfdda012928bc2fe6d0e66fd4a4c912946254Felipe Leme    printf("Dumpstate info: id=%lu pid=%d\n", id, getpid());
482f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("\n");
48378f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme}
48478f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme
485e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme/* adds a new entry to the existing zip file. */
486e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemestatic bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
487111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme    if (!zip_writer) {
48888c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme        MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
48988c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme                entry_name.c_str());
490111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme        return false;
491111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme    }
4926fe9db67f6c92d5fbf87d371da5cca412f672630Felipe Leme    // Logging statement  below is useful to time how long each entry takes, but it's too verbose.
4936fe9db67f6c92d5fbf87d371da5cca412f672630Felipe Leme    // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
494e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(),
495e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            ZipWriter::kCompress, get_mtime(fd, now));
496e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    if (err) {
497cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
498809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme                ZipWriter::ErrorCodeString(err));
499e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        return false;
500e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    }
501e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
502770410dcf2f72cf4e806442263e63719a0be0f5aFelipe Leme    std::vector<uint8_t> buffer(65536);
503e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    while (1) {
504e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), sizeof(buffer)));
505e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        if (bytes_read == 0) {
506e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            break;
507e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        } else if (bytes_read == -1) {
508cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme            MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
509e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            return false;
510e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        }
511e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        err = zip_writer->WriteBytes(buffer.data(), bytes_read);
512e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        if (err) {
513cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme            MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
514e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            return false;
515e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        }
516e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    }
517e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
518e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    err = zip_writer->FinishEntry();
519e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    if (err) {
520cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
521e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        return false;
522e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    }
523e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
524e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    return true;
525e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme}
526e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
527e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme/* adds a new entry to the existing zip file. */
528e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemestatic bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
529e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    ScopedFd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
530e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    if (fd.get() == -1) {
531cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
532e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme        return false;
533e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    }
534e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
535e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    return add_zip_entry_from_fd(entry_name, fd.get());
536e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme}
537e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
538e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme/* adds a file to the existing zipped bugreport */
539e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemestatic int _add_file_from_fd(const char *title, const char *path, int fd) {
540e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
541e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme}
542e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
543e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme/* adds all files from a directory to the zipped bugreport file */
544e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemevoid add_dir(const char *dir, bool recursive) {
545111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme    if (!zip_writer) {
546cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGD("Not adding dir %s because zip_writer is not set\n", dir);
547111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme        return;
548111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme    }
54988c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme    MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive);
550608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    DurationReporter duration_reporter(dir, NULL);
551e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd);
552e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme}
553e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
554809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme/* adds a text entry entry to the existing zip file. */
555809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Lemestatic bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
556111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme    if (!zip_writer) {
557cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGD("Not adding text zip entry %s because zip_writer is not set\n", entry_name.c_str());
558111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme        return false;
559111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme    }
560cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme    MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
561809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
562809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    if (err) {
563cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
564809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme                ZipWriter::ErrorCodeString(err));
565809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme        return false;
566809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    }
567809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme
568809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    err = zip_writer->WriteBytes(content.c_str(), content.length());
569809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    if (err) {
570cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
571809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme                ZipWriter::ErrorCodeString(err));
572809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme        return false;
573809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    }
574809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme
575809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    err = zip_writer->FinishEntry();
576809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    if (err) {
577cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
578809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme        return false;
579809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    }
580809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme
581809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    return true;
582809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme}
583809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme
584fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharanstatic void dumpstate(const std::string& screenshot_path, const std::string& version) {
585770410dcf2f72cf4e806442263e63719a0be0f5aFelipe Leme    DurationReporter duration_reporter("DUMPSTATE");
58678f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    unsigned long timeout;
587f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
5882db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
589f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("UPTIME", 10, "uptime", NULL);
590326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
5918c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
592f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("MEMORY INFO", "/proc/meminfo");
593b32c7e14ccc6507f6ce3fc02414ba04b797f4558Elliott Hughes    run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-H", NULL);
5942b1f88b6ac78e330ff006da6fecf8bc9d976ec67Nick Kralevich    run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
595f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
596f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("VMALLOC INFO", "/proc/vmallocinfo");
597f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("SLAB INFO", "/proc/slabinfo");
598f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("ZONEINFO", "/proc/zoneinfo");
599f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
600f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BUDDYINFO", "/proc/buddyinfo");
6012281af967dd840aade7bc55b19ea7df0e6da36f2Colin Cross    dump_file("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
602f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
60329e27a84c144fe3b941648094cad2a3f1e61e8b3Todd Poynor    dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
604f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
60585aea748861b5665e68b786b55f1c798f56fc0daMathias Agopian    dump_file("KERNEL SYNC", "/d/sync");
606f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
607a3533a3ae6bf8d0e1780c153cafdec86926ec22cElliott Hughes    run_command("PROCESSES AND THREADS", 10, "ps", "-Z", "-t", "-p", "-P", NULL);
608b82c925d3cd54d5eff9f4f9e6d5aeb41f75365f5Nick Kralevich    run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
609f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
6104db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    run_command("ROUTE", 10, "route", NULL);
6114db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    run_command("PRINTENV", 10, "printenv", NULL);
6124db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    run_command("NETSTAT", 10, "netstat", NULL);
6134db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    run_command("LSMOD", 10, "lsmod", NULL);
6144db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
615f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    do_dmesg();
616f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
617f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
6181dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
6191dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
620a297c3258f6f7ea52cc2dcc42d62f85fda12a163Mark Salyzyn    for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
621f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
6226e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    if (!screenshot_path.empty()) {
623cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGI("taking late screenshot\n");
624e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme        take_screenshot(screenshot_path);
625cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
6265a93003d3f0d1808b6dcd9928041ec62ea7f67adJeff Sharkey    }
6275a93003d3f0d1808b6dcd9928041ec62ea7f67adJeff Sharkey
628f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
6298f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    // calculate timeout
6308f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
6318f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (timeout < 20000) {
6328f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        timeout = 20000;
6338f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
6347831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn    run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
6357831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                        "-v", "printable",
6367831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                        "-d",
6377831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                        "*:v", NULL);
63843afe5d0b537999d5de9613626eca24f34cc52efMark Salyzyn    timeout = logcat_timeout("events");
6398f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (timeout < 20000) {
6408f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        timeout = 20000;
6418f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
6427831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn    run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
6437831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-v", "threadtime",
6447831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-v", "printable",
6457831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-d",
6467831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "*:v", NULL);
6478f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    timeout = logcat_timeout("radio");
6488f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (timeout < 20000) {
6498f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        timeout = 20000;
6508f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
6517831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn    run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
6527831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-v", "threadtime",
6537831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-v", "printable",
6547831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-d",
6557831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "*:v", NULL);
656f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
657ecc0763e6c96c418ea4ee6c993d58d16a58407b3Mark Salyzyn    run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
658ecc0763e6c96c418ea4ee6c993d58d16a58407b3Mark Salyzyn
659804339a59e4abcbcf5a50a60ff0543e6b404e572Sharvil Nanavati    run_command("RAFT LOGS", 600, SU_PATH, "root", "logcompressor", "-r", RAFT_DIR, NULL);
6608d4cb7ffc11050eebb4d06684e0eb14d9aadacb5Sharvil Nanavati
661f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* show the traces we collected in main(), if that was done */
662f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (dump_traces_path != NULL) {
663f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        dump_file("VM TRACES JUST NOW", dump_traces_path);
664f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
665f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
666f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* only show ANR traces if they're less than 15 minutes old */
667f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    struct stat st;
668f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char anr_traces_path[PATH_MAX];
669f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
670f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (!anr_traces_path[0]) {
671f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
672f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    } else {
67354bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris      int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
67454bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris                                       O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
6757dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris      if (fd < 0) {
6767dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris          printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
6777dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris      } else {
6787dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris          dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
6797dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris      }
680f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
681f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
682f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* slow traces for slow operations */
683f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (anr_traces_path[0] != 0) {
684f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        int tail = strlen(anr_traces_path)-1;
685f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        while (tail > 0 && anr_traces_path[tail] != '/') {
686f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            tail--;
687f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
688f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        int i = 0;
689f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        while (1) {
690f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
691f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            if (stat(anr_traces_path, &st)) {
692f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                // No traces file at this index, done with the files.
693f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                break;
694f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            }
695f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            dump_file("VM TRACES WHEN SLOW", anr_traces_path);
696f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            i++;
697f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
698f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
699f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
7007dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    int dumped = 0;
7017dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
7027dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        if (tombstone_data[i].fd != -1) {
703e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            const char *name = tombstone_data[i].name;
704e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            int fd = tombstone_data[i].fd;
7057dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris            dumped = 1;
706e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            if (zip_writer) {
707e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme                if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
708cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                    MYLOGE("Unable to add tombstone %s to zip file\n", name);
709e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme                }
710e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            } else {
711e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme                dump_file_from_fd("TOMBSTONE", name, fd);
712e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            }
713e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme            close(fd);
7147dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris            tombstone_data[i].fd = -1;
7157dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        }
7167dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    }
7177dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    if (!dumped) {
7187dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
7197dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    }
7207dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
721f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("NETWORK DEV INFO", "/proc/net/dev");
722f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
723012c2ea5651a56218a4359c78db26dd700d9930bJP Abgrall    dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
724f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
725f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
726f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
7272a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor    if (!stat(PSTORE_LAST_KMSG, &st)) {
7282a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor        /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
7292a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor        dump_file("LAST KMSG", PSTORE_LAST_KMSG);
7302a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor    } else {
7312a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor        /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
7322a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor        dump_file("LAST KMSG", "/proc/last_kmsg");
7332a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor    }
7342a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor
7352262c16372570f57d3107d574abe2c80825d286eMark Salyzyn    /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
7367831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn    run_command("LAST LOGCAT", 10, "logcat", "-L",
7377831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                             "-b", "all",
7387831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                             "-v", "threadtime",
7397831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                             "-v", "printable",
7407831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                             "-d",
7417831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                             "*:v", NULL);
7422262c16372570f57d3107d574abe2c80825d286eMark Salyzyn
743f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
744a59828a5d2740433164872e9a0b44363e2ba0cd4Elliott Hughes
745a59828a5d2740433164872e9a0b44363e2ba0cd4Elliott Hughes    run_command("NETWORK INTERFACES", 10, "ip", "link", NULL);
746d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti
747d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti    run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL);
748d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti    run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL);
749d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti
750f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("IP RULES", 10, "ip", "rule", "show", NULL);
751f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
7522b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran
7532b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran    dump_route_tables();
7542b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran
755d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti    run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
756d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti    run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
757d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti
758f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("IPTABLES", 10, SU_PATH, "root", "iptables", "-L", "-nvx", NULL);
759f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("IP6TABLES", 10, SU_PATH, "root", "ip6tables", "-L", "-nvx", NULL);
760012c2ea5651a56218a4359c78db26dd700d9930bJP Abgrall    run_command("IPTABLE NAT", 10, SU_PATH, "root", "iptables", "-t", "nat", "-L", "-nvx", NULL);
761012c2ea5651a56218a4359c78db26dd700d9930bJP Abgrall    /* no ip6 nat */
762012c2ea5651a56218a4359c78db26dd700d9930bJP Abgrall    run_command("IPTABLE RAW", 10, SU_PATH, "root", "iptables", "-t", "raw", "-L", "-nvx", NULL);
763012c2ea5651a56218a4359c78db26dd700d9930bJP Abgrall    run_command("IP6TABLE RAW", 10, SU_PATH, "root", "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
764f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
765f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("WIFI NETWORKS", 20,
7661d6b97c869718001010cce3db387c73fd11bf32eDmitry Shmidt            SU_PATH, "root", "wpa_cli", "IFNAME=wlan0", "list_networks", NULL);
767f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
768c11f56e5615c5d388c072705322df5bcf22c2012Dmitry Shmidt#ifdef FWDUMP_bcmdhd
7696afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("ND OFFLOAD TABLE", 5,
7706afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti            SU_PATH, "root", "wlutil", "nd_hostip", NULL);
7716afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
7726afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
773c11f56e5615c5d388c072705322df5bcf22c2012Dmitry Shmidt            SU_PATH, "root", "wlutil", "counters", NULL);
7746afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
7756afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("ND OFFLOAD STATUS (1)", 5,
7766afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti            SU_PATH, "root", "wlutil", "nd_status", NULL);
7776afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
778c11f56e5615c5d388c072705322df5bcf22c2012Dmitry Shmidt#endif
7790b2c9268265e9a165551eaa66cb461d3fab8b564Dmitry Shmidt    dump_file("INTERRUPTS (1)", "/proc/interrupts");
7800b2c9268265e9a165551eaa66cb461d3fab8b564Dmitry Shmidt
7816afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "connectivity", "--diag", NULL);
7826afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
783c11f56e5615c5d388c072705322df5bcf22c2012Dmitry Shmidt#ifdef FWDUMP_bcmdhd
784f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("DUMP WIFI STATUS", 20,
785f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
7866afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
7876afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
788f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            SU_PATH, "root", "wlutil", "counters", NULL);
7896afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
7906afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("ND OFFLOAD STATUS (2)", 5,
7916afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti            SU_PATH, "root", "wlutil", "nd_status", NULL);
792f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#endif
7930b2c9268265e9a165551eaa66cb461d3fab8b564Dmitry Shmidt    dump_file("INTERRUPTS (2)", "/proc/interrupts");
794f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
795f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    print_properties();
796f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
797f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
798f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
799f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
8008f75fa7bcfec553eddb59b919b44d7a93c9846a1Ken Sumrall    run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);
801f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
802f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
803f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
804f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("------ BACKLIGHTS ------\n");
805f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("LCD brightness=");
806f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness");
807f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Button brightness=");
808f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/sys/class/leds/button-backlight/brightness");
809f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Keyboard brightness=");
810f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/sys/class/leds/keyboard-backlight/brightness");
811f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("ALS mode=");
812f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/sys/class/leds/lcd-backlight/als");
813f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("LCD driver registers:\n");
814f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
815f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("\n");
816f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
817f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* Binder state is expensive to look at as it uses a lot of memory. */
818f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
819f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
820f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
821f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
822f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
823f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
824f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
825f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== Board\n");
826f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
827f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
828f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dumpstate_board();
829f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("\n");
830f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
831f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* Migrate the ril_dumpstate to a dumpstate_board()? */
832f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
833f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
834f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
835f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        if (0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1)) {
836f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            // su does not exist on user builds, so try running without it.
837f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            // This way any implementations of vril-dump that do not require
838f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            // root can run on user builds.
839f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
840f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                    "vril-dump", NULL);
841f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        } else {
842f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
843f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                    SU_PATH, "root", "vril-dump", NULL);
844f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
845f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
846f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
847f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
848f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== Android Framework Services\n");
849f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
850f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
851f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* the full dumpsys is starting to take a long time, so we need
852f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross       to increase its timeout.  we really need to do the timeouts in
853f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross       dumpsys itself... */
854fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan    if (version == VERSION_DUMPSYS_SPLIT) {
855fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan        // Skipping meminfo and cpuinfo services.
856fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan        run_command("DUMPSYS", 60, "dumpsys", "--skip", "meminfo,cpuinfo", NULL);
857fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan    } else {
858fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan        run_command("DUMPSYS", 60, "dumpsys", NULL);
859fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan    }
860f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
861f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
86202bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn    printf("== Checkins\n");
86302bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn    printf("========================================================\n");
86402bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn
86559b1516f4cefcfd599f4e5e9c4a227a48d1ace65Dianne Hackborn    run_command("CHECKIN BATTERYSTATS", 30, "dumpsys", "batterystats", "-c", NULL);
8663e5fa73722c100fc9017c7a47b17a8e727aa34e1Dianne Hackborn    run_command("CHECKIN MEMINFO", 30, "dumpsys", "meminfo", "--checkin", NULL);
86702bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn    run_command("CHECKIN NETSTATS", 30, "dumpsys", "netstats", "--checkin", NULL);
8685cd46aa3399ddeaf12a211390dfde66c796ab299Dianne Hackborn    run_command("CHECKIN PROCSTATS", 30, "dumpsys", "procstats", "-c", NULL);
8691bd5068a5180ac12dda374e15c7b1f70e8334284Dianne Hackborn    run_command("CHECKIN USAGESTATS", 30, "dumpsys", "usagestats", "-c", NULL);
8708b3e133e413774047da8005771f57c21dd31e1e3Ashish Sharma    run_command("CHECKIN PACKAGE", 30, "dumpsys", "package", "--checkin", NULL);
87102bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn
87202bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn    printf("========================================================\n");
873f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== Running Application Activities\n");
874f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
875f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
876f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("APP ACTIVITIES", 30, "dumpsys", "activity", "all", NULL);
877f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
878f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
879f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== Running Application Services\n");
880f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
881f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
882f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("APP SERVICES", 30, "dumpsys", "activity", "service", "all", NULL);
883f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
884f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
885f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== Running Application Providers\n");
886f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
887f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
888f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("APP SERVICES", 30, "dumpsys", "activity", "provider", "all", NULL);
889f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
890f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
891f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
892608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    printf("== Final progress (pid %d): %d/%d (originally %d)\n",
893608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme            getpid(), progress, weight_total, WEIGHT_TOTAL);
894608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    printf("========================================================\n");
895f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== dumpstate: done\n");
896f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
897f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
898f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
899f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossstatic void usage() {
900809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    fprintf(stderr, "usage: dumpstate [-b soundfile] [-e soundfile] [-o file [-d] [-p] [-z]] [-s] [-q] [-B] [-P] [-R] [-V version]\n"
901809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme            "  -b: play sound file instead of vibrate, at beginning of job\n"
902809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme            "  -e: play sound file instead of vibrate, at end of job\n"
903f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -o: write to file (instead of stdout)\n"
904f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -d: append date to filename (requires -o)\n"
905f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -p: capture screenshot to filename.png (requires -o)\n"
906809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme            "  -z: generates zipped file (requires -o)\n"
907f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -s: write output to control socket (for init)\n"
9081f794c442cc63f7962c21e8e712adeca338af63eJohn Michelau            "  -q: disable vibrate\n"
90936b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            "  -B: send broadcast when finished (requires -o)\n"
910111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme            "  -P: send broadcast when started and update system properties on progress (requires -o and -B)\n"
9114db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski            "  -R: take bugreport in remote mode (requires -o, -z, -d and -B, shouldn't be used with -P)\n"
912809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme            "  -V: sets the bugreport format version (%s or %s)\n",
913809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme            VERSION_DEFAULT.c_str(), VERSION_DUMPSYS_SPLIT.c_str());
914f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
915f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
916885f888c55587e9366542b5155a06c321cde175aJohn Michelaustatic void sigpipe_handler(int n) {
9172e671bbdb741c2926b6df7b240fdc31c7361f330Andres Morales    // don't complain to stderr or stdout
9182e671bbdb741c2926b6df7b240fdc31c7361f330Andres Morales    _exit(EXIT_FAILURE);
919885f888c55587e9366542b5155a06c321cde175aJohn Michelau}
920885f888c55587e9366542b5155a06c321cde175aJohn Michelau
9211e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
9221e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme   temporary file.
9231e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme */
924e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Lemestatic bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
9251e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        time_t now) {
926e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    if (!add_zip_entry(bugreport_name, bugreport_path)) {
927cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("Failed to add text entry to .zip file\n");
9286e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        return false;
9296e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    }
930809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
931cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("Failed to add main_entry.txt to .zip file\n");
932111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme        return false;
933809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    }
9346e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
935e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    int32_t err = zip_writer->Finish();
9361e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    if (err) {
937cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
9386e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        return false;
9396e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    }
9406e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
9416e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    return true;
9426e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme}
9436e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
9444db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinskistatic std::string SHA256_file_hash(std::string filepath) {
945cbbdf73608bace91270622034e4813a2355b7bf1Michal Karpinski    ScopedFd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC
946cbbdf73608bace91270622034e4813a2355b7bf1Michal Karpinski            | O_NOFOLLOW)));
9474db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    if (fd.get() == -1) {
948cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
9494db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        return NULL;
9504db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    }
9514db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
9524db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    SHA256_CTX ctx;
9534db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    SHA256_init(&ctx);
9544db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
9554db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    std::vector<uint8_t> buffer(65536);
9564db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    while (1) {
9574db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
9584db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        if (bytes_read == 0) {
9594db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski            break;
9604db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        } else if (bytes_read == -1) {
961cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme            MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
9624db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski            return NULL;
9634db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        }
9644db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
9654db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        SHA256_update(&ctx, buffer.data(), bytes_read);
9664db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    }
9674db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
9684db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    uint8_t hash[SHA256_DIGEST_SIZE];
9694db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    memcpy(hash, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
9704db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    char hash_buffer[SHA256_DIGEST_SIZE * 2 + 1];
971cbbdf73608bace91270622034e4813a2355b7bf1Michal Karpinski    for(size_t i = 0; i < SHA256_DIGEST_SIZE; i++) {
972cbbdf73608bace91270622034e4813a2355b7bf1Michal Karpinski        sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
9734db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    }
9744db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    hash_buffer[sizeof(hash_buffer) - 1] = 0;
9754db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    return std::string(hash_buffer);
9764db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski}
9774db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
978608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme/* switch to non-root user and group */
979608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Lemebool drop_root() {
980608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    /* ensure we will keep capabilities when we drop root */
981608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
982cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
983608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme        return false;
984608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    }
985608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme
986608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW,
987608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme            AID_MOUNT, AID_INET, AID_NET_BW_STATS, AID_READPROC };
988608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
989cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
990608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme        return false;
991608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    }
992608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    if (setgid(AID_SHELL) != 0) {
993cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("Unable to setgid, aborting: %s\n", strerror(errno));
994608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme        return false;
995608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    }
996608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    if (setuid(AID_SHELL) != 0) {
997cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("Unable to setuid, aborting: %s\n", strerror(errno));
998608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme        return false;
999608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    }
1000608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme
1001608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    struct __user_cap_header_struct capheader;
1002608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    struct __user_cap_data_struct capdata[2];
1003608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    memset(&capheader, 0, sizeof(capheader));
1004608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    memset(&capdata, 0, sizeof(capdata));
1005608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    capheader.version = _LINUX_CAPABILITY_VERSION_3;
1006608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    capheader.pid = 0;
1007608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme
1008608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
1009608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG);
1010608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    capdata[0].inheritable = 0;
1011608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    capdata[1].inheritable = 0;
1012608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme
1013608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    if (capset(&capheader, &capdata[0]) < 0) {
1014cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGE("capset failed: %s\n", strerror(errno));
1015608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme        return false;
1016608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    }
1017608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme
1018608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    return true;
1019608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme}
10204db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
1021f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossint main(int argc, char *argv[]) {
1022885f888c55587e9366542b5155a06c321cde175aJohn Michelau    struct sigaction sigact;
1023f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    int do_add_date = 0;
10246e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    int do_zip_file = 0;
10251f794c442cc63f7962c21e8e712adeca338af63eJohn Michelau    int do_vibrate = 1;
1026f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char* use_outfile = 0;
1027f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    int use_socket = 0;
1028f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    int do_fb = 0;
102927f9e6d849fce956c9b8f1ad5c3d9a954501a76bJeff Sharkey    int do_broadcast = 0;
1030e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    int do_early_screenshot = 0;
10314db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    int is_remote_mode = 0;
1032809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    std::string version = VERSION_DEFAULT;
1033f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
1034e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme    now = time(NULL);
1035e82a27d0c1e3f2cef6f13a1a9efff55638601752Felipe Leme
10361e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    if (getuid() != 0) {
10371e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        // Old versions of the adb client would call the
10381e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        // dumpstate command directly. Newer clients
10391e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        // call /system/bin/bugreport instead. If we detect
10401e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        // we're being called incorrectly, then exec the
10411e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        // correct program.
10421e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        return execl("/system/bin/bugreport", "/system/bin/bugreport", NULL);
10431e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    }
1044f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
1045cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme    MYLOGI("begin\n");
10462e671bbdb741c2926b6df7b240fdc31c7361f330Andres Morales
10478fecfdda012928bc2fe6d0e66fd4a4c912946254Felipe Leme    /* gets the sequential id */
10488fecfdda012928bc2fe6d0e66fd4a4c912946254Felipe Leme    char last_id[PROPERTY_VALUE_MAX];
10498fecfdda012928bc2fe6d0e66fd4a4c912946254Felipe Leme    property_get("dumpstate.last_id", last_id, "0");
10508fecfdda012928bc2fe6d0e66fd4a4c912946254Felipe Leme    id = strtoul(last_id, NULL, 10) + 1;
10518fecfdda012928bc2fe6d0e66fd4a4c912946254Felipe Leme    sprintf(last_id, "%lu", id);
10528fecfdda012928bc2fe6d0e66fd4a4c912946254Felipe Leme    property_set("dumpstate.last_id", last_id);
10538fecfdda012928bc2fe6d0e66fd4a4c912946254Felipe Leme    MYLOGI("dumpstate id: %lu\n", id);
10548fecfdda012928bc2fe6d0e66fd4a4c912946254Felipe Leme
10551dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* clear SIGPIPE handler */
1056885f888c55587e9366542b5155a06c321cde175aJohn Michelau    memset(&sigact, 0, sizeof(sigact));
1057885f888c55587e9366542b5155a06c321cde175aJohn Michelau    sigact.sa_handler = sigpipe_handler;
1058885f888c55587e9366542b5155a06c321cde175aJohn Michelau    sigaction(SIGPIPE, &sigact, NULL);
10593e03d3fb6a4cb93f5f978f9d2eed7b7cc62a06a6JP Abgrall
1060f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* set as high priority, and protect from OOM killer */
1061f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    setpriority(PRIO_PROCESS, 0, -20);
1062cd67e9f059e270017d5defd8784c89dd8e6bcde7Nick Kralevich    FILE *oom_adj = fopen("/proc/self/oom_adj", "we");
1063f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (oom_adj) {
1064f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        fputs("-17", oom_adj);
1065f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        fclose(oom_adj);
1066f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
1067f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
10681dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* parse arguments */
106988c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme    log_args("Dumpstate command line", argc, const_cast<const char **>(argv));
1070f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    int c;
1071809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    while ((c = getopt(argc, argv, "dho:svqzpPBRV:")) != -1) {
1072f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        switch (c) {
107371bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'd': do_add_date = 1;          break;
107471bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'z': do_zip_file = 1;          break;
107571bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'o': use_outfile = optarg;     break;
107671bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 's': use_socket = 1;           break;
1077f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            case 'v': break;  // compatibility no-op
107871bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'q': do_vibrate = 0;           break;
107971bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'p': do_fb = 1;                break;
108071bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'P': do_update_progress = 1;   break;
10814db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski            case 'R': is_remote_mode = 1;       break;
108271bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'B': do_broadcast = 1;         break;
1083809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme            case 'V': version = optarg;         break;
1084f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            case '?': printf("\n");
1085f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            case 'h':
1086f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                usage();
1087f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                exit(1);
1088f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
1089f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
1090f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
109171bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) {
10926e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        usage();
10936e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        exit(1);
10946e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    }
10956e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
109671bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (do_update_progress && !do_broadcast) {
109771bbfc57974331dce79242ce806d92035fce06baFelipe Leme        usage();
109871bbfc57974331dce79242ce806d92035fce06baFelipe Leme        exit(1);
109971bbfc57974331dce79242ce806d92035fce06baFelipe Leme    }
11006e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
11014db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    if (is_remote_mode && (do_update_progress || !do_broadcast || !do_zip_file || !do_add_date)) {
11024db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        usage();
11034db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski        exit(1);
11044db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski    }
11054db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski
1106809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    if (version != VERSION_DEFAULT && version != VERSION_DUMPSYS_SPLIT) {
1107809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme        usage();
1108809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme        exit(1);
1109809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    }
1110809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme
1111cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme    MYLOGI("bugreport format version: %s\n", version.c_str());
1112809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme
1113e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    do_early_screenshot = do_update_progress;
1114e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme
1115ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris    // If we are going to use a socket, do it as early as possible
1116ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris    // to avoid timeouts from bugreport.
1117ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris    if (use_socket) {
1118ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris        redirect_to_socket(stdout, "dumpstate");
1119ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris    }
1120ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris
1121cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme    /* full path of the directory where the bugreport files will be written */
1122ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    std::string bugreport_dir;
1123ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
1124cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme    /* full path of the temporary file containing the bugreport */
1125ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    std::string tmp_path;
1126ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
1127cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme    /* full path of the file containing the dumpstate logs*/
1128cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme    std::string log_path;
1129cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme
1130e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    /* full path of the temporary file containing the screenshot (when requested) */
1131e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    std::string screenshot_path;
1132e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme
1133cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme    /* base name (without suffix or extensions) of the bugreport files */
1134ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    std::string base_name;
1135ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
1136cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme    /* suffix of the bugreport files - it's typically the date (when invoked with -d),
1137ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme     * although it could be changed by the user using a system property */
1138ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    std::string suffix;
113971bbfc57974331dce79242ce806d92035fce06baFelipe Leme
114071bbfc57974331dce79242ce806d92035fce06baFelipe Leme    /* pointer to the actual path, be it zip or text */
114171bbfc57974331dce79242ce806d92035fce06baFelipe Leme    std::string path;
114271bbfc57974331dce79242ce806d92035fce06baFelipe Leme
1143635ca31754ae734b0c540ac5600d58ae55cd4237Felipe Leme    /* pointer to the zipped file */
11441e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
114571bbfc57974331dce79242ce806d92035fce06baFelipe Leme
1146ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    /* redirect output if needed */
114771bbfc57974331dce79242ce806d92035fce06baFelipe Leme    bool is_redirecting = !use_socket && use_outfile;
114871bbfc57974331dce79242ce806d92035fce06baFelipe Leme
114971bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (is_redirecting) {
1150ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        bugreport_dir = dirname(use_outfile);
1151ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        base_name = basename(use_outfile);
115271bbfc57974331dce79242ce806d92035fce06baFelipe Leme        if (do_add_date) {
115371bbfc57974331dce79242ce806d92035fce06baFelipe Leme            char date[80];
1154ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1155ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            suffix = date;
1156ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        } else {
1157ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            suffix = "undated";
115871bbfc57974331dce79242ce806d92035fce06baFelipe Leme        }
115971bbfc57974331dce79242ce806d92035fce06baFelipe Leme        if (do_fb) {
1160ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            // TODO: if dumpstate was an object, the paths could be internal variables and then
1161ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            // we could have a function to calculate the derived values, such as:
1162ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            //     screenshot_path = GetPath(".png");
1163ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png";
116471bbfc57974331dce79242ce806d92035fce06baFelipe Leme        }
1165ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
1166cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        log_path = bugreport_dir + "/dumpstate_log-" + suffix + "-"
1167cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                + std::to_string(getpid()) + ".txt";
1168cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme
1169cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        MYLOGD("Bugreport dir: %s\n"
1170cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                "Base name: %s\n"
1171cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                "Suffix: %s\n"
1172cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                "Log path: %s\n"
1173cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                "Temporary path: %s\n"
1174cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                "Screenshot path: %s\n",
1175cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(),
1176cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                log_path.c_str(), tmp_path.c_str(), screenshot_path.c_str());
117771bbfc57974331dce79242ce806d92035fce06baFelipe Leme
11781e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        if (do_zip_file) {
1179cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme            MYLOGD("Creating initial .zip file\n");
11801e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1181111b9d06cc0fc72438782c9234f28675e5077ef4Felipe Leme            create_parent_dirs(path.c_str());
11821e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            zip_file.reset(fopen(path.c_str(), "wb"));
11831e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            if (!zip_file) {
1184cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
11851e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme                do_zip_file = 0;
11861e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            } else {
11871e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme                zip_writer.reset(new ZipWriter(zip_file.get()));
11881e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            }
1189809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme            add_text_zip_entry("version.txt", version);
11901e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        }
11911e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme
119271bbfc57974331dce79242ce806d92035fce06baFelipe Leme        if (do_update_progress) {
1193ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            std::vector<std::string> am_args = {
1194d5e724a4d3f77024d311b1b4e01846e41fdbe98bFelipe Leme                 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1195ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                 "--es", "android.intent.extra.NAME", suffix,
11968fecfdda012928bc2fe6d0e66fd4a4c912946254Felipe Leme                 "--ei", "android.intent.extra.ID", std::to_string(id),
1197ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1198ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1199ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            };
1200ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
120171bbfc57974331dce79242ce806d92035fce06baFelipe Leme        }
120271bbfc57974331dce79242ce806d92035fce06baFelipe Leme    }
120371bbfc57974331dce79242ce806d92035fce06baFelipe Leme
1204f3599b35c5f7f86cced0f3386a6c80e0b552f358Nick Kralevich    /* read /proc/cmdline before dropping root */
1205f3599b35c5f7f86cced0f3386a6c80e0b552f358Nick Kralevich    FILE *cmdline = fopen("/proc/cmdline", "re");
1206f3599b35c5f7f86cced0f3386a6c80e0b552f358Nick Kralevich    if (cmdline) {
1207f3599b35c5f7f86cced0f3386a6c80e0b552f358Nick Kralevich        fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1208f3599b35c5f7f86cced0f3386a6c80e0b552f358Nick Kralevich        fclose(cmdline);
1209f3599b35c5f7f86cced0f3386a6c80e0b552f358Nick Kralevich    }
1210f3599b35c5f7f86cced0f3386a6c80e0b552f358Nick Kralevich
12111dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* open the vibrator before dropping root */
12126e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
12131f794c442cc63f7962c21e8e712adeca338af63eJohn Michelau    if (do_vibrate) {
12146e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
12151dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown        if (vibrator) {
12166e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            vibrate(vibrator.get(), 150);
12171dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown        }
12181f794c442cc63f7962c21e8e712adeca338af63eJohn Michelau    }
1219f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
12203634a1e3459cb609da709646107e246cafbc01f9Felipe Leme    if (do_fb && do_early_screenshot) {
12213634a1e3459cb609da709646107e246cafbc01f9Felipe Leme        if (screenshot_path.empty()) {
12223634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            // should not have happened
1223cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme            MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
12243634a1e3459cb609da709646107e246cafbc01f9Felipe Leme        } else {
1225cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme            MYLOGI("taking early screenshot\n");
12263634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            take_screenshot(screenshot_path);
1227cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme            MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
12283634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
1229cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
12303634a1e3459cb609da709646107e246cafbc01f9Felipe Leme                        screenshot_path.c_str(), strerror(errno));
12313634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            }
1232e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme        }
1233e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    }
1234e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme
12351e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    if (do_zip_file) {
12361e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
1237cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme            MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
12381e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        }
12391e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    }
12401e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme
124171bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (is_redirecting) {
1242cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
12436fe9db67f6c92d5fbf87d371da5cca412f672630Felipe Leme        if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
12446fe9db67f6c92d5fbf87d371da5cca412f672630Felipe Leme            MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
12456fe9db67f6c92d5fbf87d371da5cca412f672630Felipe Leme                    log_path.c_str(), strerror(errno));
12466fe9db67f6c92d5fbf87d371da5cca412f672630Felipe Leme        }
12476e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        /* TODO: rather than generating a text file now and zipping it later,
12486e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme           it would be more efficient to redirect stdout to the zip entry
12496e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme           directly, but the libziparchive doesn't support that option yet. */
12506e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
12516fe9db67f6c92d5fbf87d371da5cca412f672630Felipe Leme        if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
12526fe9db67f6c92d5fbf87d371da5cca412f672630Felipe Leme            MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
12536fe9db67f6c92d5fbf87d371da5cca412f672630Felipe Leme                    tmp_path.c_str(), strerror(errno));
12546fe9db67f6c92d5fbf87d371da5cca412f672630Felipe Leme        }
1255f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
1256608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    // NOTE: there should be no stdout output until now, otherwise it would break the header.
1257608385dd151e36a93f3e3f4a7514b1e720d20ae9Felipe Leme    // In particular, DurationReport objects should be created passing 'title, NULL', so their
1258cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme    // duration is logged into MYLOG instead.
1259809d74e92c16cf694c929b8ca2b54515af13e9feFelipe Leme    print_header(version);
1260f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
1261fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan    if (version == VERSION_DUMPSYS_SPLIT) {
1262fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan        // Invoking the following dumpsys calls before dump_traces() to try and
1263fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan        // keep the system stats as close to its initial state as possible.
1264d5e724a4d3f77024d311b1b4e01846e41fdbe98bFelipe Leme        run_command("DUMPSYS MEMINFO", 30, SU_PATH, "shell", "dumpsys", "meminfo", "-a", NULL);
1265d5e724a4d3f77024d311b1b4e01846e41fdbe98bFelipe Leme        run_command("DUMPSYS CPUINFO", 30, SU_PATH, "shell", "dumpsys", "cpuinfo", "-a", NULL);
1266fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan    }
1267fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan
1268fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan    /* collect stack traces from Dalvik and native processes (needs root) */
1269fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan    dump_traces_path = dump_traces();
1270fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan
1271fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan    /* Get the tombstone fds, recovery files, and mount info here while we are running as root. */
1272fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan    get_tombstone_fds(tombstone_data);
1273fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan    add_dir(RECOVERY_DIR, true);
1274fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan    add_mountinfo();
1275fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan
1276fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan    if (!drop_root()) {
1277fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan        return -1;
1278fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan    }
1279fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan
1280fdf52d3697aa0396bd9d8883892937b99a6772a0Srinath Sridharan    dumpstate(do_early_screenshot ? "": screenshot_path, version);
1281f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
128255b42a67f69767976ff16ab443b3e7142db693e1Felipe Leme    /* close output if needed */
128371bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (is_redirecting) {
1284f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        fclose(stdout);
1285cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme        fclose(stderr);
1286f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
1287f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
12886e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    /* rename or zip the (now complete) .tmp file to its final location */
12896e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    if (use_outfile) {
1290ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
1291ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        /* check if user changed the suffix using system properties */
1292ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        char key[PROPERTY_KEY_MAX];
1293ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        char value[PROPERTY_VALUE_MAX];
1294ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        sprintf(key, "dumpstate.%d.name", getpid());
1295ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        property_get(key, value, "");
1296ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        bool change_suffix= false;
1297ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        if (value[0]) {
1298ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            /* must whitelist which characters are allowed, otherwise it could cross directories */
1299ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            std::regex valid_regex("^[-_a-zA-Z0-9]+$");
1300ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            if (std::regex_match(value, valid_regex)) {
1301ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                change_suffix = true;
1302ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            } else {
1303cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                MYLOGE("invalid suffix provided by user: %s\n", value);
1304ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            }
1305ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        }
1306ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        if (change_suffix) {
1307cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme            MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), value);
1308ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            suffix = value;
1309ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            if (!screenshot_path.empty()) {
1310ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                std::string new_screenshot_path =
1311ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                        bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1312ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
1313cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                    MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
1314ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                            new_screenshot_path.c_str(), strerror(errno));
1315ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                } else {
1316ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                    screenshot_path = new_screenshot_path;
1317ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                }
1318ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            }
1319ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        }
1320ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
13216e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        bool do_text_file = true;
13226e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        if (do_zip_file) {
132388c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme            std::string entry_name = base_name + "-" + suffix + ".txt";
132488c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme            MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
132588c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme            if (!finish_zip_file(entry_name, tmp_path, now)) {
1326cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
13276e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme                do_text_file = true;
13286e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            } else {
13296e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme                do_text_file = false;
13306e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            }
13316e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        }
13326e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        if (do_text_file) {
1333ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt";
133488c7933df551f6dadd8cc931d104b01d6d1609e4Felipe Leme            MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
1335ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            if (rename(tmp_path.c_str(), path.c_str())) {
1336cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
13376e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme                path.clear();
13386e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            }
13396e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        }
1340f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
1341f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
1342cc2a2fa64e22378d980ae0ae95c8865ebea05f69Felipe Leme    /* vibrate a few but shortly times to let user know it's finished */
1343cc2a2fa64e22378d980ae0ae95c8865ebea05f69Felipe Leme    if (vibrator) {
1344cc2a2fa64e22378d980ae0ae95c8865ebea05f69Felipe Leme        for (int i = 0; i < 3; i++) {
1345cc2a2fa64e22378d980ae0ae95c8865ebea05f69Felipe Leme            vibrate(vibrator.get(), 75);
1346cc2a2fa64e22378d980ae0ae95c8865ebea05f69Felipe Leme            usleep((75 + 50) * 1000);
1347cc2a2fa64e22378d980ae0ae95c8865ebea05f69Felipe Leme        }
1348cc2a2fa64e22378d980ae0ae95c8865ebea05f69Felipe Leme    }
1349cc2a2fa64e22378d980ae0ae95c8865ebea05f69Felipe Leme
13501dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* tell activity manager we're done */
135171bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (do_broadcast) {
13526e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        if (!path.empty()) {
1353cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme            MYLOGI("Final bugreport path: %s\n", path.c_str());
135436b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            std::vector<std::string> am_args = {
135543fd1bbc6675430a4ecfde07e88a414ed5c41c0cFelipe Leme                 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
13568fecfdda012928bc2fe6d0e66fd4a4c912946254Felipe Leme                 "--ei", "android.intent.extra.ID", std::to_string(id),
135771bbfc57974331dce79242ce806d92035fce06baFelipe Leme                 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1358ee2e4a01f9ca9aae7ee111abcd5c139fc810bf65Felipe Leme                 "--ei", "android.intent.extra.MAX", std::to_string(weight_total),
1359cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                 "--es", "android.intent.extra.BUGREPORT", path,
1360cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme                 "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
136136b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            };
136236b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            if (do_fb) {
136336b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme                am_args.push_back("--es");
136436b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme                am_args.push_back("android.intent.extra.SCREENSHOT");
136536b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme                am_args.push_back(screenshot_path);
136636b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            }
13674db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski            if (is_remote_mode) {
13684db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski                am_args.push_back("--es");
13694db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski                am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
13704db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski                am_args.push_back(SHA256_file_hash(path));
13714db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski                send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
13724db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski            } else {
13734db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski                send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
13744db754fd7c13993d81d98157f10e8015422d1e3aMichal Karpinski            }
13756e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        } else {
1376cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme            MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
13776e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        }
137827f9e6d849fce956c9b8f1ad5c3d9a954501a76bJeff Sharkey    }
137927f9e6d849fce956c9b8f1ad5c3d9a954501a76bJeff Sharkey
1380cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme    MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
1381cbce55d4fdbdd2e5a5515054c48d2116c5db2712Felipe Leme    MYLOGI("done\n");
1382f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
1383f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    return 0;
1384f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
1385