dumpstate.cpp revision 1e9edc619c6b1ca3998a26eaa4882b55ce801f12
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>
248f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn#include <stdbool.h>
25f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <stdio.h>
26f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <stdlib.h>
276e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme#include <string>
28f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <string.h>
297dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#include <sys/capability.h>
307dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#include <sys/prctl.h>
31f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <sys/resource.h>
32f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <sys/stat.h>
33f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <sys/time.h>
34f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <sys/wait.h>
35f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <unistd.h>
36f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
379dc117c415d0df0a3acd900709d05deabe975704Elliott Hughes#include <android-base/stringprintf.h>
38f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include <cutils/properties.h>
39f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
40f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include "private/android_filesystem_config.h"
41f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
42f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#define LOG_TAG "dumpstate"
43656a6b9e3645bfe2cf073b69cbb9d02832f62c26Alex Ray#include <cutils/log.h>
44f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
45f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#include "dumpstate.h"
466e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme#include "ScopedFd.h"
476e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme#include "ziparchive/zip_writer.h"
486e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
496e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Lemeusing android::base::StringPrintf;
50f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
51f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross/* read before root is shed */
52f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossstatic char cmdline_buf[16384] = "(unknown)";
53f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossstatic const char *dump_traces_path = NULL;
54f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
5578f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Lemestatic char build_type[PROPERTY_VALUE_MAX];
5678f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme
572a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
582a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor
598d4cb7ffc11050eebb4d06684e0eb14d9aadacb5Sharvil Nanavati#define RAFT_DIR "/data/misc/raft/"
607dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#define TOMBSTONE_DIR "/data/tombstones"
617dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
627dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris/* Can accomodate a tombstone number up to 9999. */
637dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
647dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris#define NUM_TOMBSTONES  10
657dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
667dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferristypedef struct {
677dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris  char name[TOMBSTONE_MAX_LEN];
687dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris  int fd;
697dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris} tombstone_data_t;
707dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
717dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferrisstatic tombstone_data_t tombstone_data[NUM_TOMBSTONES];
727dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
737dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris/* Get the fds of any tombstone that was modified in the last half an hour. */
747dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferrisstatic void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
757dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    time_t thirty_minutes_ago = time(NULL) - 60*30;
767dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
777dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
7854bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris        int fd = TEMP_FAILURE_RETRY(open(data[i].name,
7954bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris                                         O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
807dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        struct stat st;
817dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
827dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris                (time_t) st.st_mtime >= thirty_minutes_ago) {
837dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris            data[i].fd = fd;
847dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        } else {
857dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris            close(fd);
867dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris            data[i].fd = -1;
877dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        }
887dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    }
897dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris}
907dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
912db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevågstatic void dump_dev_files(const char *title, const char *driverpath, const char *filename)
922db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg{
932db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    DIR *d;
942db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    struct dirent *de;
952db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    char path[PATH_MAX];
962db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg
972db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    d = opendir(driverpath);
982db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    if (d == NULL) {
992db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg        return;
1002db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    }
1012db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg
1022db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    while ((de = readdir(d))) {
1032db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg        if (de->d_type != DT_LNK) {
1042db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg            continue;
1052db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg        }
1062db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg        snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
1072db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg        dump_file(title, path);
1082db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    }
1092db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg
1102db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    closedir(d);
1112db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg}
1122db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg
113326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzynstatic bool skip_not_stat(const char *path) {
114326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    static const char stat[] = "/stat";
115326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    size_t len = strlen(path);
116326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (path[len - 1] == '/') { /* Directory? */
117326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        return false;
118326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
119326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
120326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn}
121326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
122326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzynstatic const char mmcblk0[] = "/sys/block/mmcblk0/";
1238f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzynunsigned long worst_write_perf = 20000; /* in KB/s */
124326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
125326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzynstatic int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
126326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    unsigned long fields[11], read_perf, write_perf;
127326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    bool z;
128326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    char *cp, *buffer = NULL;
129326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    size_t i = 0;
130326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    FILE *fp = fdopen(fd, "rb");
131326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    getline(&buffer, &i, fp);
132326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    fclose(fp);
133326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (!buffer) {
134326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        return -errno;
135326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
136326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    i = strlen(buffer);
137326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    while ((i > 0) && (buffer[i - 1] == '\n')) {
138326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        buffer[--i] = '\0';
139326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
140326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (!*buffer) {
141326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        free(buffer);
142326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        return 0;
143326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
144326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    z = true;
145326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
146326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        fields[i] = strtol(cp, &cp, 0);
147326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        if (fields[i] != 0) {
148326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn            z = false;
149326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        }
150326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
151326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (z) { /* never accessed */
152326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        free(buffer);
153326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        return 0;
154326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
155326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
156326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
157326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        path += sizeof(mmcblk0) - 1;
158326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
159326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
160326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    printf("%s: %s\n", path, buffer);
161326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    free(buffer);
162326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
163326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    read_perf = 0;
164326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (fields[3]) {
165326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        read_perf = 512 * fields[2] / fields[3];
166326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
167326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    write_perf = 0;
168326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    if (fields[7]) {
169326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn        write_perf = 512 * fields[6] / fields[7];
170326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    }
171326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    printf("%s: read: %luKB/s write: %luKB/s\n", path, read_perf, write_perf);
1728f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if ((write_perf > 1) && (write_perf < worst_write_perf)) {
1738f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        worst_write_perf = write_perf;
1748f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
175326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    return 0;
176326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn}
177326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn
1788f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn/* Copied policy from system/core/logd/LogBuffer.cpp */
1798f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
1808f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn#define LOG_BUFFER_SIZE (256 * 1024)
1818f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
1828f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
1838f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
1848f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzynstatic bool valid_size(unsigned long value) {
1858f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
1868f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        return false;
1878f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
1888f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
1898f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    long pages = sysconf(_SC_PHYS_PAGES);
1908f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (pages < 1) {
1918f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        return true;
1928f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
1938f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
1948f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    long pagesize = sysconf(_SC_PAGESIZE);
1958f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (pagesize <= 1) {
1968f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        pagesize = PAGE_SIZE;
1978f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
1988f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
1998f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    // maximum memory impact a somewhat arbitrary ~3%
2008f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    pages = (pages + 31) / 32;
2018f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    unsigned long maximum = pages * pagesize;
2028f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2038f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
2048f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        return true;
2058f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
2068f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2078f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    return value <= maximum;
2088f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn}
2098f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2108f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzynstatic unsigned long property_get_size(const char *key) {
2118f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    unsigned long value;
2128f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    char *cp, property[PROPERTY_VALUE_MAX];
2138f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2148f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    property_get(key, property, "");
2158f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    value = strtoul(property, &cp, 10);
2168f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2178f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    switch(*cp) {
2188f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    case 'm':
2198f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    case 'M':
2208f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        value *= 1024;
2218f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    /* FALLTHRU */
2228f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    case 'k':
2238f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    case 'K':
2248f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        value *= 1024;
2258f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    /* FALLTHRU */
2268f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    case '\0':
2278f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        break;
2288f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2298f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    default:
2308f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        value = 0;
2318f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
2328f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2338f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (!valid_size(value)) {
2348f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        value = 0;
2358f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
2368f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2378f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    return value;
2388f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn}
2398f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2408f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn/* timeout in ms */
2418620bb4118a68721d10c29529dc6978847d08d00Felipe Lemestatic unsigned long logcat_timeout(const char *name) {
2428f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    static const char global_tuneable[] = "persist.logd.size"; // Settings App
2438f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    static const char global_default[] = "ro.logd.size";       // BoardConfig.mk
2448f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    char key[PROP_NAME_MAX];
2458f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    unsigned long property_size, default_size;
2468f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2478f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    default_size = property_get_size(global_tuneable);
2488f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (!default_size) {
2498f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        default_size = property_get_size(global_default);
2508f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
2518f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2528f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
2538f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    property_size = property_get_size(key);
2548f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2558f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (!property_size) {
2568f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        snprintf(key, sizeof(key), "%s.%s", global_default, name);
2578f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        property_size = property_get_size(key);
2588f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
2598f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2608f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (!property_size) {
2618f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        property_size = default_size;
2628f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
2638f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2648f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (!property_size) {
2658f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        property_size = LOG_BUFFER_SIZE;
2668f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
2678f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2688f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    /* Engineering margin is ten-fold our guess */
2698f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    return 10 * (property_size + worst_write_perf) / worst_write_perf;
2708f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn}
2718f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
2728f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn/* End copy from system/core/logd/LogBuffer.cpp */
2738f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn
274f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross/* dumps the current system state to stdout */
27578f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Lemestatic void print_header() {
276f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    time_t now = time(NULL);
277f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
278f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
279f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char network[PROPERTY_VALUE_MAX], date[80];
280f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
281f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ro.build.display.id", build, "(unknown)");
282f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ro.build.fingerprint", fingerprint, "(unknown)");
283f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ro.build.type", build_type, "(unknown)");
284f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ro.baseband", radio, "(unknown)");
285f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ro.bootloader", bootloader, "(unknown)");
286f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("gsm.operator.alpha", network, "(unknown)");
287f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
288f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
289f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
290f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== dumpstate: %s\n", date);
291f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
292f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
293f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("\n");
294f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Build: %s\n", build);
295f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */
296f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Bootloader: %s\n", bootloader);
297f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Radio: %s\n", radio);
298f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Network: %s\n", network);
299f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
300f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Kernel: ");
301f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/proc/version");
302f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
303f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("\n");
30478f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme}
30578f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme
30678f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Lemestatic void dumpstate(const std::string& screenshot_path) {
30778f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    std::unique_ptr<DurationReporter> duration_reporter(new DurationReporter("DUMPSTATE"));
30878f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    unsigned long timeout;
309f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
3102db0f5f31c015b5a89b619f8c95a9bf95c09c75bArve Hjønnevåg    dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
311f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("UPTIME", 10, "uptime", NULL);
312326842fca4883f1256aa9ed019bb3206ee76fca7Mark Salyzyn    dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
3138c8130eb68c89987a94db084608a4229bad06c18Mark Salyzyn    dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
314f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("MEMORY INFO", "/proc/meminfo");
315b32c7e14ccc6507f6ce3fc02414ba04b797f4558Elliott Hughes    run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-H", NULL);
3162b1f88b6ac78e330ff006da6fecf8bc9d976ec67Nick Kralevich    run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
317f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
318f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("VMALLOC INFO", "/proc/vmallocinfo");
319f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("SLAB INFO", "/proc/slabinfo");
320f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("ZONEINFO", "/proc/zoneinfo");
321f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
322f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BUDDYINFO", "/proc/buddyinfo");
3232281af967dd840aade7bc55b19ea7df0e6da36f2Colin Cross    dump_file("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
324f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
325f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("KERNEL WAKELOCKS", "/proc/wakelocks");
32629e27a84c144fe3b941648094cad2a3f1e61e8b3Todd Poynor    dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
327f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
32885aea748861b5665e68b786b55f1c798f56fc0daMathias Agopian    dump_file("KERNEL SYNC", "/d/sync");
329f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
330a3533a3ae6bf8d0e1780c153cafdec86926ec22cElliott Hughes    run_command("PROCESSES AND THREADS", 10, "ps", "-Z", "-t", "-p", "-P", NULL);
331b82c925d3cd54d5eff9f4f9e6d5aeb41f75365f5Nick Kralevich    run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
332f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
333f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    do_dmesg();
334f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
335f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
3361dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
3371dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
338f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
3396e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    if (!screenshot_path.empty()) {
340e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme        ALOGI("taking late screenshot\n");
341e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme        take_screenshot(screenshot_path);
3426e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        ALOGI("wrote screenshot: %s\n", screenshot_path.c_str());
3435a93003d3f0d1808b6dcd9928041ec62ea7f67adJeff Sharkey    }
3445a93003d3f0d1808b6dcd9928041ec62ea7f67adJeff Sharkey
345f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
3468f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    // calculate timeout
3478f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
3488f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (timeout < 20000) {
3498f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        timeout = 20000;
3508f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
3517831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn    run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
3527831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                        "-v", "printable",
3537831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                        "-d",
3547831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                        "*:v", NULL);
355c7ad8cb82f035576c28707a8cbeb16b7ead2a4e7Mark Salyzyn    timeout = logcat_timeout("events") + logcat_timeout("security");
3568f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (timeout < 20000) {
3578f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        timeout = 20000;
3588f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
3597831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn    run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
360c7ad8cb82f035576c28707a8cbeb16b7ead2a4e7Mark Salyzyn                                                       "-b", "security",
3617831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-v", "threadtime",
3627831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-v", "printable",
3637831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-d",
3647831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "*:v", NULL);
3658f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    timeout = logcat_timeout("radio");
3668f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    if (timeout < 20000) {
3678f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn        timeout = 20000;
3688f37aa5011bf5d8c0a67126b92e3b435ffd4dca0Mark Salyzyn    }
3697831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn    run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
3707831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-v", "threadtime",
3717831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-v", "printable",
3727831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "-d",
3737831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                                       "*:v", NULL);
374f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
375ecc0763e6c96c418ea4ee6c993d58d16a58407b3Mark Salyzyn    run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
376ecc0763e6c96c418ea4ee6c993d58d16a58407b3Mark Salyzyn
377804339a59e4abcbcf5a50a60ff0543e6b404e572Sharvil Nanavati    run_command("RAFT LOGS", 600, SU_PATH, "root", "logcompressor", "-r", RAFT_DIR, NULL);
3788d4cb7ffc11050eebb4d06684e0eb14d9aadacb5Sharvil Nanavati
379f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* show the traces we collected in main(), if that was done */
380f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (dump_traces_path != NULL) {
381f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        dump_file("VM TRACES JUST NOW", dump_traces_path);
382f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
383f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
384f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* only show ANR traces if they're less than 15 minutes old */
385f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    struct stat st;
386f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char anr_traces_path[PATH_MAX];
387f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
388f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (!anr_traces_path[0]) {
389f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
390f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    } else {
39154bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris      int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
39254bcc5ffd5a79f4f194089c58d3de571532bf39bChristopher Ferris                                       O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
3937dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris      if (fd < 0) {
3947dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris          printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
3957dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris      } else {
3967dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris          dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
3977dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris      }
398f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
399f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
400f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* slow traces for slow operations */
401f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (anr_traces_path[0] != 0) {
402f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        int tail = strlen(anr_traces_path)-1;
403f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        while (tail > 0 && anr_traces_path[tail] != '/') {
404f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            tail--;
405f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
406f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        int i = 0;
407f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        while (1) {
408f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
409f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            if (stat(anr_traces_path, &st)) {
410f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                // No traces file at this index, done with the files.
411f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                break;
412f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            }
413f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            dump_file("VM TRACES WHEN SLOW", anr_traces_path);
414f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            i++;
415f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
416f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
417f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
4187dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    int dumped = 0;
4197dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
4207dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        if (tombstone_data[i].fd != -1) {
4217dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris            dumped = 1;
4227dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris            dump_file_from_fd("TOMBSTONE", tombstone_data[i].name, tombstone_data[i].fd);
4237dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris            tombstone_data[i].fd = -1;
4247dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        }
4257dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    }
4267dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    if (!dumped) {
4277dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris        printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
4287dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris    }
4297dc7f3221f26b771c266a26ec785eb74287922f1Christopher Ferris
430f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("NETWORK DEV INFO", "/proc/net/dev");
431f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
432012c2ea5651a56218a4359c78db26dd700d9930bJP Abgrall    dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
433f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
434f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
435f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
4362a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor    if (!stat(PSTORE_LAST_KMSG, &st)) {
4372a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor        /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
4382a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor        dump_file("LAST KMSG", PSTORE_LAST_KMSG);
4392a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor    } else {
4402a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor        /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
4412a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor        dump_file("LAST KMSG", "/proc/last_kmsg");
4422a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor    }
4432a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor
4442262c16372570f57d3107d574abe2c80825d286eMark Salyzyn    /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
4457831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn    run_command("LAST LOGCAT", 10, "logcat", "-L",
4467831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                             "-b", "all",
4477831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                             "-v", "threadtime",
4487831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                             "-v", "printable",
4497831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                             "-d",
4507831638e2a142cbb082d63a60ad5c04ff63933e8Mark Salyzyn                                             "*:v", NULL);
4512262c16372570f57d3107d574abe2c80825d286eMark Salyzyn
452f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
453a59828a5d2740433164872e9a0b44363e2ba0cd4Elliott Hughes
454a59828a5d2740433164872e9a0b44363e2ba0cd4Elliott Hughes    run_command("NETWORK INTERFACES", 10, "ip", "link", NULL);
455d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti
456d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti    run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL);
457d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti    run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL);
458d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti
459f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("IP RULES", 10, "ip", "rule", "show", NULL);
460f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
4612b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran
4622b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran    dump_route_tables();
4632b3bba34aec65b612be8d1f52cd124d9c30955f9Sreeram Ramachandran
464d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti    run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
465d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti    run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
466d4c3d38957870fa27423dbc55d99d68772fbd490Lorenzo Colitti
467f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("IPTABLES", 10, SU_PATH, "root", "iptables", "-L", "-nvx", NULL);
468f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("IP6TABLES", 10, SU_PATH, "root", "ip6tables", "-L", "-nvx", NULL);
469012c2ea5651a56218a4359c78db26dd700d9930bJP Abgrall    run_command("IPTABLE NAT", 10, SU_PATH, "root", "iptables", "-t", "nat", "-L", "-nvx", NULL);
470012c2ea5651a56218a4359c78db26dd700d9930bJP Abgrall    /* no ip6 nat */
471012c2ea5651a56218a4359c78db26dd700d9930bJP Abgrall    run_command("IPTABLE RAW", 10, SU_PATH, "root", "iptables", "-t", "raw", "-L", "-nvx", NULL);
472012c2ea5651a56218a4359c78db26dd700d9930bJP Abgrall    run_command("IP6TABLE RAW", 10, SU_PATH, "root", "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
473f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
474f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("WIFI NETWORKS", 20,
4751d6b97c869718001010cce3db387c73fd11bf32eDmitry Shmidt            SU_PATH, "root", "wpa_cli", "IFNAME=wlan0", "list_networks", NULL);
476f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
477c11f56e5615c5d388c072705322df5bcf22c2012Dmitry Shmidt#ifdef FWDUMP_bcmdhd
4786afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("ND OFFLOAD TABLE", 5,
4796afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti            SU_PATH, "root", "wlutil", "nd_hostip", NULL);
4806afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
4816afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
482c11f56e5615c5d388c072705322df5bcf22c2012Dmitry Shmidt            SU_PATH, "root", "wlutil", "counters", NULL);
4836afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
4846afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("ND OFFLOAD STATUS (1)", 5,
4856afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti            SU_PATH, "root", "wlutil", "nd_status", NULL);
4866afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
487c11f56e5615c5d388c072705322df5bcf22c2012Dmitry Shmidt#endif
4880b2c9268265e9a165551eaa66cb461d3fab8b564Dmitry Shmidt    dump_file("INTERRUPTS (1)", "/proc/interrupts");
4890b2c9268265e9a165551eaa66cb461d3fab8b564Dmitry Shmidt
4906afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "connectivity", "--diag", NULL);
4916afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
492c11f56e5615c5d388c072705322df5bcf22c2012Dmitry Shmidt#ifdef FWDUMP_bcmdhd
493f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("DUMP WIFI STATUS", 20,
494f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
4956afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
4966afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
497f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            SU_PATH, "root", "wlutil", "counters", NULL);
4986afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti
4996afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti    run_command("ND OFFLOAD STATUS (2)", 5,
5006afc38c45af45eb8f64793bca2903b3f4c55579bLorenzo Colitti            SU_PATH, "root", "wlutil", "nd_status", NULL);
501f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross#endif
5020b2c9268265e9a165551eaa66cb461d3fab8b564Dmitry Shmidt    dump_file("INTERRUPTS (2)", "/proc/interrupts");
503f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
504f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    print_properties();
505f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
506f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
507f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
508f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
5098f75fa7bcfec553eddb59b919b44d7a93c9846a1Ken Sumrall    run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);
510f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
511f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
512f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
513f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("------ BACKLIGHTS ------\n");
514f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("LCD brightness=");
515f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness");
516f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Button brightness=");
517f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/sys/class/leds/button-backlight/brightness");
518f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("Keyboard brightness=");
519f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/sys/class/leds/keyboard-backlight/brightness");
520f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("ALS mode=");
521f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/sys/class/leds/lcd-backlight/als");
522f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("LCD driver registers:\n");
523f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
524f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("\n");
525f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
526f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* Binder state is expensive to look at as it uses a lot of memory. */
527f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
528f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
529f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
530f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
531f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
532f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
533f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
534f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== Board\n");
535f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
536f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
537f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    dumpstate_board();
538f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("\n");
539f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
540f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* Migrate the ril_dumpstate to a dumpstate_board()? */
541f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
542f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
543f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
544f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        if (0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1)) {
545f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            // su does not exist on user builds, so try running without it.
546f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            // This way any implementations of vril-dump that do not require
547f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            // root can run on user builds.
548f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
549f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                    "vril-dump", NULL);
550f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        } else {
551f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
552f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                    SU_PATH, "root", "vril-dump", NULL);
553f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
554f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
555f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
556f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
557f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== Android Framework Services\n");
558f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
559f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
560f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* the full dumpsys is starting to take a long time, so we need
561f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross       to increase its timeout.  we really need to do the timeouts in
562f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross       dumpsys itself... */
563f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("DUMPSYS", 60, "dumpsys", NULL);
564f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
565f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
56602bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn    printf("== Checkins\n");
56702bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn    printf("========================================================\n");
56802bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn
56959b1516f4cefcfd599f4e5e9c4a227a48d1ace65Dianne Hackborn    run_command("CHECKIN BATTERYSTATS", 30, "dumpsys", "batterystats", "-c", NULL);
5703e5fa73722c100fc9017c7a47b17a8e727aa34e1Dianne Hackborn    run_command("CHECKIN MEMINFO", 30, "dumpsys", "meminfo", "--checkin", NULL);
57102bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn    run_command("CHECKIN NETSTATS", 30, "dumpsys", "netstats", "--checkin", NULL);
5725cd46aa3399ddeaf12a211390dfde66c796ab299Dianne Hackborn    run_command("CHECKIN PROCSTATS", 30, "dumpsys", "procstats", "-c", NULL);
5731bd5068a5180ac12dda374e15c7b1f70e8334284Dianne Hackborn    run_command("CHECKIN USAGESTATS", 30, "dumpsys", "usagestats", "-c", NULL);
5748b3e133e413774047da8005771f57c21dd31e1e3Ashish Sharma    run_command("CHECKIN PACKAGE", 30, "dumpsys", "package", "--checkin", NULL);
57502bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn
57602bea9786d2ecc4c04f35fd7d9b73d4dd2b73735Dianne Hackborn    printf("========================================================\n");
577f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== Running Application Activities\n");
578f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
579f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
580f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("APP ACTIVITIES", 30, "dumpsys", "activity", "all", NULL);
581f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
582f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
583f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== Running Application Services\n");
584f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
585f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
586f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("APP SERVICES", 30, "dumpsys", "activity", "service", "all", NULL);
587f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
588f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
589f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== Running Application Providers\n");
590f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
591f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
592f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    run_command("APP SERVICES", 30, "dumpsys", "activity", "provider", "all", NULL);
593f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
594f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
595f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
596f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("== dumpstate: done\n");
597f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    printf("========================================================\n");
598f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
599f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
600f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossstatic void usage() {
6011f794c442cc63f7962c21e8e712adeca338af63eJohn Michelau    fprintf(stderr, "usage: dumpstate [-b soundfile] [-e soundfile] [-o file [-d] [-p] [-z]] [-s] [-q]\n"
602f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -o: write to file (instead of stdout)\n"
603f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -d: append date to filename (requires -o)\n"
6046e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            "  -z: generates zipped file (requires -o)\n"
605f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -p: capture screenshot to filename.png (requires -o)\n"
606f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -s: write output to control socket (for init)\n"
607f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -b: play sound file instead of vibrate, at beginning of job\n"
608f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            "  -e: play sound file instead of vibrate, at end of job\n"
6091f794c442cc63f7962c21e8e712adeca338af63eJohn Michelau            "  -q: disable vibrate\n"
61036b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            "  -B: send broadcast when finished (requires -o)\n"
61171bbfc57974331dce79242ce806d92035fce06baFelipe Leme            "  -P: send broadacast when started and update system properties on progress (requires -o and -B)\n"
6122a83daa8a3e1eab292dc1464bbe78f025f4bc0e9Todd Poynor                );
613f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
614f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
615885f888c55587e9366542b5155a06c321cde175aJohn Michelaustatic void sigpipe_handler(int n) {
6162e671bbdb741c2926b6df7b240fdc31c7361f330Andres Morales    // don't complain to stderr or stdout
6172e671bbdb741c2926b6df7b240fdc31c7361f330Andres Morales    _exit(EXIT_FAILURE);
618885f888c55587e9366542b5155a06c321cde175aJohn Michelau}
619885f888c55587e9366542b5155a06c321cde175aJohn Michelau
6201dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brownstatic void vibrate(FILE* vibrator, int ms) {
6211dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    fprintf(vibrator, "%d\n", ms);
6221dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    fflush(vibrator);
6231dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown}
6241dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown
6251e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme/* adds a new entry to the existing zip file. */
6261e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Lemestatic bool add_zip_entry(ZipWriter* writer, const std::string& entry_name,
6271e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        const std::string& entry_path, time_t entry_time) {
6281e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    int32_t err = writer->StartEntryWithTime(entry_name.c_str(),
6291e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            ZipWriter::kCompress, entry_time);
6306e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    if (err) {
6311e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        ALOGE("writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(), ZipWriter::ErrorCodeString(err));
6326e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        return false;
6336e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    }
6346e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
6351e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    ScopedFd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
6366e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    if (fd.get() == -1) {
6371e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        ALOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
6386e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        return false;
6396e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    }
6406e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
6416e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    while (1) {
6426e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        std::vector<uint8_t> buffer(65536);
6436e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), sizeof(buffer)));
6446e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        if (bytes_read == 0) {
6456e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            break;
6466e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        } else if (bytes_read == -1) {
6471e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            ALOGE("read(%s): %s\n", entry_path.c_str(), strerror(errno));
6486e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            return false;
6491e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        }
6501e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        err = writer->WriteBytes(buffer.data(), bytes_read);
6511e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        if (err) {
6521e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            ALOGE("writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
6531e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            return false;
6541e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        }
6556e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    }
6566e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
6571e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    err = writer->FinishEntry();
6586e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    if (err) {
6591e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        ALOGE("writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
6606e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        return false;
6616e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    }
6626e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
6631e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    return true;
6641e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme}
6651e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme
6661e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
6671e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme   temporary file.
6681e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme */
6691e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Lemestatic bool finish_zip_file(ZipWriter* writer,
6701e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        const std::string& bugreport_name, const std::string& bugreport_path,
6711e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        time_t now) {
6721e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    if (!add_zip_entry(writer, bugreport_name, bugreport_path, now)) {
6731e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        ALOGE("Failed to add text entry to .zip file\n");
6746e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        return false;
6756e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    }
6766e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
6771e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    int32_t err = writer->Finish();
6781e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    if (err) {
6791e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        ALOGE("writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
6806e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        return false;
6816e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    }
6826e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
6831e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    if (remove(bugreport_path.c_str())) {
6841e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
6851e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    }
6861e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme
6876e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    return true;
6886e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme}
6896e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
690f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Crossint main(int argc, char *argv[]) {
691885f888c55587e9366542b5155a06c321cde175aJohn Michelau    struct sigaction sigact;
692f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    int do_add_date = 0;
6936e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    int do_zip_file = 0;
6941f794c442cc63f7962c21e8e712adeca338af63eJohn Michelau    int do_vibrate = 1;
695f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    char* use_outfile = 0;
696f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    int use_socket = 0;
697f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    int do_fb = 0;
69827f9e6d849fce956c9b8f1ad5c3d9a954501a76bJeff Sharkey    int do_broadcast = 0;
699e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    int do_early_screenshot = 0;
700f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
7011e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    if (getuid() != 0) {
7021e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        // Old versions of the adb client would call the
7031e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        // dumpstate command directly. Newer clients
7041e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        // call /system/bin/bugreport instead. If we detect
7051e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        // we're being called incorrectly, then exec the
7061e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        // correct program.
7071e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        return execl("/system/bin/bugreport", "/system/bin/bugreport", NULL);
7081e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    }
709f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
7101dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    ALOGI("begin\n");
7112e671bbdb741c2926b6df7b240fdc31c7361f330Andres Morales
7121dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* clear SIGPIPE handler */
713885f888c55587e9366542b5155a06c321cde175aJohn Michelau    memset(&sigact, 0, sizeof(sigact));
714885f888c55587e9366542b5155a06c321cde175aJohn Michelau    sigact.sa_handler = sigpipe_handler;
715885f888c55587e9366542b5155a06c321cde175aJohn Michelau    sigaction(SIGPIPE, &sigact, NULL);
7163e03d3fb6a4cb93f5f978f9d2eed7b7cc62a06a6JP Abgrall
717f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* set as high priority, and protect from OOM killer */
718f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    setpriority(PRIO_PROCESS, 0, -20);
719cd67e9f059e270017d5defd8784c89dd8e6bcde7Nick Kralevich    FILE *oom_adj = fopen("/proc/self/oom_adj", "we");
720f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    if (oom_adj) {
721f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        fputs("-17", oom_adj);
722f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        fclose(oom_adj);
723f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
724f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
7251dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* parse arguments */
726f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    int c;
72771bbfc57974331dce79242ce806d92035fce06baFelipe Leme    while ((c = getopt(argc, argv, "dho:svqzpPB")) != -1) {
728f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        switch (c) {
72971bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'd': do_add_date = 1;          break;
73071bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'z': do_zip_file = 1;          break;
73171bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'o': use_outfile = optarg;     break;
73271bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 's': use_socket = 1;           break;
733f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            case 'v': break;  // compatibility no-op
73471bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'q': do_vibrate = 0;           break;
73571bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'p': do_fb = 1;                break;
73671bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'P': do_update_progress = 1;   break;
73771bbfc57974331dce79242ce806d92035fce06baFelipe Leme            case 'B': do_broadcast = 1;         break;
738f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            case '?': printf("\n");
739f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            case 'h':
740f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                usage();
741f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross                exit(1);
742f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
743f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
744f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
74571bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) {
7466e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        usage();
7476e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        exit(1);
7486e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    }
7496e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
75071bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (do_update_progress && !do_broadcast) {
75171bbfc57974331dce79242ce806d92035fce06baFelipe Leme        usage();
75271bbfc57974331dce79242ce806d92035fce06baFelipe Leme        exit(1);
75371bbfc57974331dce79242ce806d92035fce06baFelipe Leme    }
7546e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme
755e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    do_early_screenshot = do_update_progress;
756e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme
757ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris    // If we are going to use a socket, do it as early as possible
758ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris    // to avoid timeouts from bugreport.
759ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris    if (use_socket) {
760ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris        redirect_to_socket(stdout, "dumpstate");
761ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris    }
762ed9354fc846895dc53397fbb5323bef00b3a3834Christopher Ferris
763ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    /* full path of the directory where the bug report files will be written */
764ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    std::string bugreport_dir;
765ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
766ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    /* full path of the temporary file containing the bug report */
767ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    std::string tmp_path;
768ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
769e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    /* full path of the temporary file containing the screenshot (when requested) */
770e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    std::string screenshot_path;
771e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme
772ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    /* base name (without suffix or extensions) of the bug report files */
773ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    std::string base_name;
774ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
775ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    /* suffix of the bug report files - it's typically the date (when invoked with -d),
776ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme     * although it could be changed by the user using a system property */
777ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    std::string suffix;
77871bbfc57974331dce79242ce806d92035fce06baFelipe Leme
77971bbfc57974331dce79242ce806d92035fce06baFelipe Leme    /* pointer to the actual path, be it zip or text */
78071bbfc57974331dce79242ce806d92035fce06baFelipe Leme    std::string path;
78171bbfc57974331dce79242ce806d92035fce06baFelipe Leme
7821e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    /* pointers to the zipped file file */
7831e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
7841e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    std::unique_ptr<ZipWriter> zip_writer;
7851e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme
78671bbfc57974331dce79242ce806d92035fce06baFelipe Leme    time_t now = time(NULL);
78771bbfc57974331dce79242ce806d92035fce06baFelipe Leme
788ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme    /* redirect output if needed */
78971bbfc57974331dce79242ce806d92035fce06baFelipe Leme    bool is_redirecting = !use_socket && use_outfile;
79071bbfc57974331dce79242ce806d92035fce06baFelipe Leme
79171bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (is_redirecting) {
792ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        bugreport_dir = dirname(use_outfile);
793ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        base_name = basename(use_outfile);
79471bbfc57974331dce79242ce806d92035fce06baFelipe Leme        if (do_add_date) {
79571bbfc57974331dce79242ce806d92035fce06baFelipe Leme            char date[80];
796ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
797ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            suffix = date;
798ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        } else {
799ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            suffix = "undated";
80071bbfc57974331dce79242ce806d92035fce06baFelipe Leme        }
80171bbfc57974331dce79242ce806d92035fce06baFelipe Leme        if (do_fb) {
802ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            // TODO: if dumpstate was an object, the paths could be internal variables and then
803ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            // we could have a function to calculate the derived values, such as:
804ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            //     screenshot_path = GetPath(".png");
805ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png";
80671bbfc57974331dce79242ce806d92035fce06baFelipe Leme        }
807ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
80871bbfc57974331dce79242ce806d92035fce06baFelipe Leme
809ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        ALOGD("Bugreport dir: %s\nBase name: %s\nSuffix: %s\nTemporary path: %s\n"
810ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                "Screenshot path: %s\n", bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(),
811ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                tmp_path.c_str(), screenshot_path.c_str());
81271bbfc57974331dce79242ce806d92035fce06baFelipe Leme
8131e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        if (do_zip_file) {
8141e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            ALOGD("Creating initial .zip file");
8151e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
8161e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            zip_file.reset(fopen(path.c_str(), "wb"));
8171e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            if (!zip_file) {
8181e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme                ALOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
8191e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme                do_zip_file = 0;
8201e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            } else {
8211e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme                zip_writer.reset(new ZipWriter(zip_file.get()));
8221e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            }
8231e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        }
8241e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme
82571bbfc57974331dce79242ce806d92035fce06baFelipe Leme        if (do_update_progress) {
826ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            std::vector<std::string> am_args = {
827ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                 "--receiver-permission", "android.permission.DUMP",
828ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                 "--es", "android.intent.extra.NAME", suffix,
829ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
830ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
831ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            };
832ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
83371bbfc57974331dce79242ce806d92035fce06baFelipe Leme        }
83471bbfc57974331dce79242ce806d92035fce06baFelipe Leme    }
83571bbfc57974331dce79242ce806d92035fce06baFelipe Leme
83678f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme    print_header();
83778f2c86235d5882a8dc84c85a1c1864062e5f3afFelipe Leme
8381dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* open the vibrator before dropping root */
8396e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
8401f794c442cc63f7962c21e8e712adeca338af63eJohn Michelau    if (do_vibrate) {
8416e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
8421dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown        if (vibrator) {
8436e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            vibrate(vibrator.get(), 150);
8441dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown        }
8451f794c442cc63f7962c21e8e712adeca338af63eJohn Michelau    }
846f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
8473634a1e3459cb609da709646107e246cafbc01f9Felipe Leme    if (do_fb && do_early_screenshot) {
8483634a1e3459cb609da709646107e246cafbc01f9Felipe Leme        if (screenshot_path.empty()) {
8493634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            // should not have happened
8503634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            ALOGE("INTERNAL ERROR: skipping early screenshot because path was not set");
8513634a1e3459cb609da709646107e246cafbc01f9Felipe Leme        } else {
8523634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            ALOGI("taking early screenshot\n");
8533634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            take_screenshot(screenshot_path);
8543634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            ALOGI("wrote screenshot: %s\n", screenshot_path.c_str());
8553634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
8563634a1e3459cb609da709646107e246cafbc01f9Felipe Leme                ALOGE("Unable to change ownership of screenshot file %s: %s\n",
8573634a1e3459cb609da709646107e246cafbc01f9Felipe Leme                        screenshot_path.c_str(), strerror(errno));
8583634a1e3459cb609da709646107e246cafbc01f9Felipe Leme            }
859e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme        }
860e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    }
861e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme
8621e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    if (do_zip_file) {
8631e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
8641e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            ALOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
8651e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme        }
8661e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme    }
8671e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme
868f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    /* read /proc/cmdline before dropping root */
869cd67e9f059e270017d5defd8784c89dd8e6bcde7Nick Kralevich    FILE *cmdline = fopen("/proc/cmdline", "re");
8706e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    if (cmdline) {
871f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
872f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        fclose(cmdline);
873f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
874f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
8751dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* collect stack traces from Dalvik and native processes (needs root) */
8761dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    dump_traces_path = dump_traces();
8771dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown
8781dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* Get the tombstone fds here while we are running as root. */
8791dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    get_tombstone_fds(tombstone_data);
8801dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown
8811dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* ensure we will keep capabilities when we drop root */
8821e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
8831e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        ALOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
8841e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        return -1;
8851e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    }
886f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
8871e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    /* switch to non-root user and group */
8881e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW,
889ab46a4922655bc75848660da4268ab85d72a6010Nick Kralevich            AID_MOUNT, AID_INET, AID_NET_BW_STATS, AID_READPROC };
8901e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
8911e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        ALOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
8921e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        return -1;
8931e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    }
8941e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    if (setgid(AID_SHELL) != 0) {
8951e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        ALOGE("Unable to setgid, aborting: %s\n", strerror(errno));
8961e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        return -1;
8971e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    }
8981e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    if (setuid(AID_SHELL) != 0) {
8991e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        ALOGE("Unable to setuid, aborting: %s\n", strerror(errno));
9001e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        return -1;
9011e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    }
902f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
9031e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    struct __user_cap_header_struct capheader;
9041e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    struct __user_cap_data_struct capdata[2];
9051e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    memset(&capheader, 0, sizeof(capheader));
9061e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    memset(&capdata, 0, sizeof(capdata));
9071e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    capheader.version = _LINUX_CAPABILITY_VERSION_3;
9081e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    capheader.pid = 0;
9091e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich
9101e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
9111e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG);
9121e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    capdata[0].inheritable = 0;
9131e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    capdata[1].inheritable = 0;
9141e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich
9151e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich    if (capset(&capheader, &capdata[0]) < 0) {
9161e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        ALOGE("capset failed: %s\n", strerror(errno));
9171e339878c128ef47271278779c2685a8dfa49cd1Nick Kralevich        return -1;
918f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
919f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
92071bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (is_redirecting) {
9216e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        /* TODO: rather than generating a text file now and zipping it later,
9226e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme           it would be more efficient to redirect stdout to the zip entry
9236e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme           directly, but the libziparchive doesn't support that option yet. */
9246e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
925f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
926f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
9273634a1e3459cb609da709646107e246cafbc01f9Felipe Leme    dumpstate(do_early_screenshot ? "": screenshot_path);
928f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
9291dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* done */
9301dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    if (vibrator) {
9311dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown        for (int i = 0; i < 3; i++) {
9326e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            vibrate(vibrator.get(), 75);
933f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross            usleep((75 + 50) * 1000);
934f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        }
935f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
936f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
93755b42a67f69767976ff16ab443b3e7142db693e1Felipe Leme    /* close output if needed */
93871bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (is_redirecting) {
939f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross        fclose(stdout);
940f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
941f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
9426e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    /* rename or zip the (now complete) .tmp file to its final location */
9436e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme    if (use_outfile) {
944ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
945ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        /* check if user changed the suffix using system properties */
946ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        char key[PROPERTY_KEY_MAX];
947ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        char value[PROPERTY_VALUE_MAX];
948ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        sprintf(key, "dumpstate.%d.name", getpid());
949ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        property_get(key, value, "");
950ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        bool change_suffix= false;
951ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        if (value[0]) {
952ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            /* must whitelist which characters are allowed, otherwise it could cross directories */
953ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            std::regex valid_regex("^[-_a-zA-Z0-9]+$");
954ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            if (std::regex_match(value, valid_regex)) {
955ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                change_suffix = true;
956ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            } else {
957ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                ALOGE("invalid suffix provided by user: %s", value);
958ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            }
959ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        }
960ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        if (change_suffix) {
961ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            ALOGI("changing suffix from %s to %s", suffix.c_str(), value);
962ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            suffix = value;
963ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            if (!screenshot_path.empty()) {
964ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                std::string new_screenshot_path =
965ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                        bugreport_dir + "/" + base_name + "-" + suffix + ".png";
966ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
967ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                    ALOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
968ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                            new_screenshot_path.c_str(), strerror(errno));
969ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                } else {
970ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                    screenshot_path = new_screenshot_path;
971ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                }
972ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            }
973ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme        }
974ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme
9756e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        bool do_text_file = true;
9766e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        if (do_zip_file) {
9771e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            ALOGD("Adding text entry to .zip bugreport");
9781e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme            if (!finish_zip_file(zip_writer.get(), base_name + "-" + suffix + ".txt", tmp_path, now)) {
9791e9edc619c6b1ca3998a26eaa4882b55ce801f12Felipe Leme                ALOGE("Failed to finish zip file; sending text bugreport instead\n");
9806e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme                do_text_file = true;
9816e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            } else {
9826e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme                do_text_file = false;
9836e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            }
9846e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        }
9856e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        if (do_text_file) {
986ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            ALOGD("Generating .txt bugreport");
987ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt";
988ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme            if (rename(tmp_path.c_str(), path.c_str())) {
989ad5f6c475934ac6a658a203069a9f055540946e7Felipe Leme                ALOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
9906e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme                path.clear();
9916e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            }
9926e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        }
993f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    }
994f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
9951dc94e315680b47fe430ef90f46c50a25c92fb6dJeff Brown    /* tell activity manager we're done */
99671bbfc57974331dce79242ce806d92035fce06baFelipe Leme    if (do_broadcast) {
9976e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        if (!path.empty()) {
9986e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme            ALOGI("Final bugreport path: %s\n", path.c_str());
99936b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            std::vector<std::string> am_args = {
100036b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme                 "--receiver-permission", "android.permission.DUMP",
100171bbfc57974331dce79242ce806d92035fce06baFelipe Leme                 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
100236b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme                 "--es", "android.intent.extra.BUGREPORT", path
100336b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            };
100436b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            if (do_fb) {
100536b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme                am_args.push_back("--es");
100636b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme                am_args.push_back("android.intent.extra.SCREENSHOT");
100736b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme                am_args.push_back(screenshot_path);
100836b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            }
100936b3f6ff17e456dea81501006e33d5fdd1d3b480Felipe Leme            send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
10106e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        } else {
101171bbfc57974331dce79242ce806d92035fce06baFelipe Leme            ALOGE("Skipping finished broadcast because bugreport could not be generated\n");
10126e01fa6f95fb20a2faab33561056d2e74cc097cbFelipe Leme        }
101327f9e6d849fce956c9b8f1ad5c3d9a954501a76bJeff Sharkey    }
101427f9e6d849fce956c9b8f1ad5c3d9a954501a76bJeff Sharkey
1015e338bf60701e5b955ab0a097f2631f2190218894Felipe Leme    ALOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
1016f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    ALOGI("done\n");
1017f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross
1018f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross    return 0;
1019f45fa6b2853cc32385375a0b63ee39ad6a968869Colin Cross}
1020