Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ebdc7f7 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Minor changes on dumpstate refactoring:"

parents d576f1a5 bbaf3c11
Loading
Loading
Loading
Loading
+75 −115
Original line number Original line Diff line number Diff line
@@ -56,18 +56,10 @@
static char cmdline_buf[16384] = "(unknown)";
static char cmdline_buf[16384] = "(unknown)";
static const char *dump_traces_path = NULL;
static const char *dump_traces_path = NULL;


// Command-line arguments as string
static std::string args;

// TODO: variables below should be part of dumpstate object
// TODO: variables below should be part of dumpstate object
static time_t now;
static std::unique_ptr<ZipWriter> zip_writer;
static std::unique_ptr<ZipWriter> zip_writer;
static std::set<std::string> mount_points;
static std::set<std::string> mount_points;
void add_mountinfo();
void add_mountinfo();
/* suffix of the bugreport files - it's typically the date (when invoked with -d),
 * although it could be changed by the user using a system property */
static std::string suffix;
static std::string extraOptions;


#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
@@ -111,13 +103,6 @@ bool IsUserBuild() {
    return ds.IsUserBuild();
    return ds.IsUserBuild();
}
}


/*
 * List of supported zip format versions.
 *
 * See bugreport-format.md for more info.
 */
static std::string VERSION_DEFAULT = "1.0";

// Relative directory (inside the zip) for all files copied as-is into the bugreport.
// Relative directory (inside the zip) for all files copied as-is into the bugreport.
static const std::string ZIP_ROOT_DIR = "FS";
static const std::string ZIP_ROOT_DIR = "FS";


@@ -127,7 +112,7 @@ static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
/* gets the tombstone data, according to the bugreport type: if zipped, gets all tombstones;
/* gets the tombstone data, according to the bugreport type: if zipped, gets all tombstones;
 * otherwise, gets just those modified in the last half an hour. */
 * otherwise, gets just those modified in the last half an hour. */
static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
    time_t thirty_minutes_ago = now - 60*30;
    time_t thirty_minutes_ago = ds.now_ - 60 * 30;
    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
        snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
        snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
        int fd = TEMP_FAILURE_RETRY(open(data[i].name,
        int fd = TEMP_FAILURE_RETRY(open(data[i].name,
@@ -336,7 +321,7 @@ static void dump_systrace() {
        MYLOGD("Not dumping systrace because zip_writer is not set\n");
        MYLOGD("Not dumping systrace because zip_writer is not set\n");
        return;
        return;
    }
    }
    std::string systrace_path = ds.bugreportDir_ + "/systrace-" + suffix + ".txt";
    std::string systrace_path = ds.GetPath("-systrace.txt");
    if (systrace_path.empty()) {
    if (systrace_path.empty()) {
        MYLOGE("Not dumping systrace because path is empty\n");
        MYLOGE("Not dumping systrace because path is empty\n");
        return;
        return;
@@ -377,7 +362,7 @@ static void dump_raft() {
        return;
        return;
    }
    }


    std::string raft_log_path = ds.bugreportDir_ + "/raft_log.txt";
    std::string raft_log_path = ds.GetPath("-raft_log.txt");
    if (raft_log_path.empty()) {
    if (raft_log_path.empty()) {
        MYLOGD("raft_log_path is empty\n");
        MYLOGD("raft_log_path is empty\n");
        return;
        return;
@@ -686,8 +671,8 @@ static unsigned long logcat_timeout(const char *name) {


/* End copy from system/core/logd/LogBuffer.cpp */
/* End copy from system/core/logd/LogBuffer.cpp */


/* dumps the current system state to stdout */
// TODO: move to utils.cpp
void print_header(const std::string& version) {
void Dumpstate::PrintHeader() {
    std::string build, fingerprint, radio, bootloader, network;
    std::string build, fingerprint, radio, bootloader, network;
    char date[80];
    char date[80];


@@ -696,7 +681,7 @@ void print_header(const std::string& version) {
    radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
    radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
    bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
    bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
    network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
    network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
    strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
    strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));


    printf("========================================================\n");
    printf("========================================================\n");
    printf("== dumpstate: %s\n", date);
    printf("== dumpstate: %s\n", date);
@@ -713,9 +698,9 @@ void print_header(const std::string& version) {
    printf("Kernel: ");
    printf("Kernel: ");
    DumpFile("", "/proc/version");
    DumpFile("", "/proc/version");
    printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
    printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
    printf("Bugreport format version: %s\n", version.c_str());
    printf("Bugreport format version: %s\n", version_.c_str());
    printf("Dumpstate info: id=%lu pid=%d dryRun=%d args=%s extraOptions=%s\n", ds.id_, getpid(),
    printf("Dumpstate info: id=%lu pid=%d dryRun=%d args=%s extraOptions=%s\n", id_, getpid(),
           ds.IsDryRun(), args.c_str(), extraOptions.c_str());
           dryRun_, args_.c_str(), extraOptions_.c_str());
    printf("\n");
    printf("\n");
}
}


@@ -748,8 +733,8 @@ bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {


    // Logging statement  below is useful to time how long each entry takes, but it's too verbose.
    // Logging statement  below is useful to time how long each entry takes, but it's too verbose.
    // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
    // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
    int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(),
    int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
            ZipWriter::kCompress, get_mtime(fd, now));
                                                 get_mtime(fd, ds.now_));
    if (err) {
    if (err) {
        MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
        MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
                ZipWriter::ErrorCodeString(err));
                ZipWriter::ErrorCodeString(err));
@@ -815,7 +800,7 @@ static bool add_text_zip_entry(const std::string& entry_name, const std::string&
        return false;
        return false;
    }
    }
    MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
    MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
    int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
    int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
    if (err) {
    if (err) {
        MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
        MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
                ZipWriter::ErrorCodeString(err));
                ZipWriter::ErrorCodeString(err));
@@ -849,8 +834,7 @@ static void dump_iptables() {
    RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
    RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
}
}


static void dumpstate(const std::string& screenshot_path,
static void dumpstate() {
                      const std::string& version __attribute__((unused))) {
    DurationReporter durationReporter("DUMPSTATE");
    DurationReporter durationReporter("DUMPSTATE");
    unsigned long timeout;
    unsigned long timeout;


@@ -897,10 +881,9 @@ static void dumpstate(const std::string& screenshot_path,
    /* Dump Bluetooth HCI logs */
    /* Dump Bluetooth HCI logs */
    add_dir("/data/misc/bluetooth/logs", true);
    add_dir("/data/misc/bluetooth/logs", true);


    if (!screenshot_path.empty()) {
    if (!ds.doEarlyScreenshot_) {
        MYLOGI("taking late screenshot\n");
        MYLOGI("taking late screenshot\n");
        take_screenshot(screenshot_path);
        ds.TakeScreenshot();
        MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
    }
    }


    // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
    // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
@@ -1147,7 +1130,7 @@ static void dumpstate(const std::string& screenshot_path,


static void ShowUsageAndExit(int exitCode = 1) {
static void ShowUsageAndExit(int exitCode = 1) {
    fprintf(stderr,
    fprintf(stderr,
            "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
            "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
            "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
            "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
            "  -h: display this help message\n"
            "  -h: display this help message\n"
            "  -b: play sound file instead of vibrate, at beginning of job\n"
            "  -b: play sound file instead of vibrate, at beginning of job\n"
@@ -1203,13 +1186,13 @@ static void register_sig_handler() {
   temporary file.
   temporary file.
 */
 */
static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
                            const std::string& log_path, time_t now) {
                            const std::string& log_path) {
    // Final timestamp
    // Final timestamp
    char date[80];
    char date[80];
    time_t the_real_now_please_stand_up = time(nullptr);
    time_t the_real_now_please_stand_up = time(nullptr);
    strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
    strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
    MYLOGD("dumpstate id %lu finished around %s (%ld s)\n", ds.id_, date,
    MYLOGD("dumpstate id %lu finished around %s (%ld s)\n", ds.id_, date,
           the_real_now_please_stand_up - now);
           the_real_now_please_stand_up - ds.now_);


    if (!add_zip_entry(bugreport_name, bugreport_path)) {
    if (!add_zip_entry(bugreport_name, bugreport_path)) {
        MYLOGE("Failed to add text entry to .zip file\n");
        MYLOGE("Failed to add text entry to .zip file\n");
@@ -1292,11 +1275,7 @@ int main(int argc, char *argv[]) {
    int use_control_socket = 0;
    int use_control_socket = 0;
    int do_fb = 0;
    int do_fb = 0;
    int do_broadcast = 0;
    int do_broadcast = 0;
    int do_early_screenshot = 0;
    int is_remote_mode = 0;
    int is_remote_mode = 0;
    std::string version = VERSION_DEFAULT;

    now = time(nullptr);


    MYLOGI("begin\n");
    MYLOGI("begin\n");


@@ -1314,14 +1293,14 @@ int main(int argc, char *argv[]) {


    // TODO: use helper function to convert argv into a string
    // TODO: use helper function to convert argv into a string
    for (int i = 0; i < argc; i++) {
    for (int i = 0; i < argc; i++) {
        args += argv[i];
        ds.args_ += argv[i];
        if (i < argc - 1) {
        if (i < argc - 1) {
            args += " ";
            ds.args_ += " ";
        }
        }
    }
    }


    extraOptions = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
    ds.extraOptions_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
    MYLOGI("Dumpstate args: %s (extra options: %s)\n", args.c_str(), extraOptions.c_str());
    MYLOGI("Dumpstate args: %s (extra options: %s)\n", ds.args_.c_str(), ds.extraOptions_.c_str());


    /* gets the sequential id */
    /* gets the sequential id */
    int lastId = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
    int lastId = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
@@ -1358,10 +1337,10 @@ int main(int argc, char *argv[]) {
            case 'v':                            break;  // compatibility no-op
            case 'v':                            break;  // compatibility no-op
            case 'q': do_vibrate = 0;            break;
            case 'q': do_vibrate = 0;            break;
            case 'p': do_fb = 1;                 break;
            case 'p': do_fb = 1;                 break;
            case 'P': ds.updateProgress_ = 1;   break;
            case 'P': ds.updateProgress_ = true; break;
            case 'R': is_remote_mode = 1;        break;
            case 'R': is_remote_mode = 1;        break;
            case 'B': do_broadcast = 1;          break;
            case 'B': do_broadcast = 1;          break;
            case 'V': version = optarg;         break;
            case 'V': ds.version_ = optarg;      break;
            case 'h':
            case 'h':
                ShowUsageAndExit(0);
                ShowUsageAndExit(0);
                break;
                break;
@@ -1372,23 +1351,23 @@ int main(int argc, char *argv[]) {
        }
        }
    }
    }


    if (!extraOptions.empty()) {
    if (!ds.extraOptions_.empty()) {
        // Framework uses a system property to override some command-line args.
        // Framework uses a system property to override some command-line args.
        // Currently, it contains the type of the requested bugreport.
        // Currently, it contains the type of the requested bugreport.
        if (extraOptions == "bugreportplus") {
        if (ds.extraOptions_ == "bugreportplus") {
            MYLOGD("Running as bugreportplus: add -P, remove -p\n");
            MYLOGD("Running as bugreportplus: add -P, remove -p\n");
            ds.updateProgress_ = 1;
            ds.updateProgress_ = true;
            do_fb = 0;
            do_fb = 0;
        } else if (extraOptions == "bugreportremote") {
        } else if (ds.extraOptions_ == "bugreportremote") {
            MYLOGD("Running as bugreportremote: add -q -R, remove -p\n");
            MYLOGD("Running as bugreportremote: add -q -R, remove -p\n");
            do_vibrate = 0;
            do_vibrate = 0;
            is_remote_mode = 1;
            is_remote_mode = 1;
            do_fb = 0;
            do_fb = 0;
        } else if (extraOptions == "bugreportwear") {
        } else if (ds.extraOptions_ == "bugreportwear") {
            MYLOGD("Running as bugreportwear: add -P\n");
            MYLOGD("Running as bugreportwear: add -P\n");
            ds.updateProgress_ = 1;
            ds.updateProgress_ = true;
        } else {
        } else {
            MYLOGE("Unknown extra option: %s\n", extraOptions.c_str());
            MYLOGE("Unknown extra option: %s\n", ds.extraOptions_.c_str());
        }
        }
        // Reset the property
        // Reset the property
        android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
        android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
@@ -1410,13 +1389,13 @@ int main(int argc, char *argv[]) {
        ExitOnInvalidArgs();
        ExitOnInvalidArgs();
    }
    }


    if (version != VERSION_DEFAULT) {
    if (ds.version_ != VERSION_DEFAULT) {
        ShowUsageAndExit();
        ShowUsageAndExit();
    }
    }


    MYLOGI("bugreport format version: %s\n", version.c_str());
    MYLOGI("bugreport format version: %s\n", ds.version_.c_str());


    do_early_screenshot = ds.updateProgress_;
    ds.doEarlyScreenshot_ = ds.updateProgress_;


    // If we are going to use a socket, do it as early as possible
    // If we are going to use a socket, do it as early as possible
    // to avoid timeouts from bugreport.
    // to avoid timeouts from bugreport.
@@ -1436,15 +1415,6 @@ int main(int argc, char *argv[]) {
    /* full path of the file containing the dumpstate logs */
    /* full path of the file containing the dumpstate logs */
    std::string log_path;
    std::string log_path;


    /* full path of the systrace file, when enabled */
    std::string systrace_path;

    /* full path of the temporary file containing the screenshot (when requested) */
    std::string screenshot_path;

    /* base name (without suffix or extensions) of the bugreport files */
    std::string base_name;

    /* pointer to the actual path, be it zip or text */
    /* pointer to the actual path, be it zip or text */
    std::string path;
    std::string path;


@@ -1456,25 +1426,21 @@ int main(int argc, char *argv[]) {


    if (is_redirecting) {
    if (is_redirecting) {
        ds.bugreportDir_ = dirname(use_outfile);
        ds.bugreportDir_ = dirname(use_outfile);
        base_name = basename(use_outfile);
        ds.baseName_ = basename(use_outfile);
        if (do_add_date) {
        if (do_add_date) {
            char date[80];
            char date[80];
            strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
            strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
            suffix = date;
            ds.suffix_ = date;
        } else {
        } else {
            suffix = "undated";
            ds.suffix_ = "undated";
        }
        }
        std::string buildId = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
        std::string buildId = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
        base_name = base_name + "-" + buildId;
        ds.baseName_ = ds.baseName_ + "-" + buildId;
        if (do_fb) {
        if (do_fb) {
            // TODO: if dumpstate was an object, the paths could be internal variables and then
            ds.screenshotPath_ = ds.GetPath(".png");
            // we could have a function to calculate the derived values, such as:
            //     screenshot_path = GetPath(".png");
            screenshot_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".png";
        }
        }
        tmp_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".tmp";
        tmp_path = ds.GetPath(".tmp");
        log_path =
        log_path = ds.GetPath("-dumpstate_log-" + std::to_string(getpid()) + ".txt");
            ds.bugreportDir_ + "/dumpstate_log-" + suffix + "-" + std::to_string(getpid()) + ".txt";


        MYLOGD(
        MYLOGD(
            "Bugreport dir: %s\n"
            "Bugreport dir: %s\n"
@@ -1483,11 +1449,11 @@ int main(int argc, char *argv[]) {
            "Log path: %s\n"
            "Log path: %s\n"
            "Temporary path: %s\n"
            "Temporary path: %s\n"
            "Screenshot path: %s\n",
            "Screenshot path: %s\n",
            ds.bugreportDir_.c_str(), base_name.c_str(), suffix.c_str(), log_path.c_str(),
            ds.bugreportDir_.c_str(), ds.baseName_.c_str(), ds.suffix_.c_str(), log_path.c_str(),
            tmp_path.c_str(), screenshot_path.c_str());
            tmp_path.c_str(), ds.screenshotPath_.c_str());


        if (do_zip_file) {
        if (do_zip_file) {
            path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".zip";
            path = ds.GetPath(".zip");
            MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
            MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
            create_parent_dirs(path.c_str());
            create_parent_dirs(path.c_str());
            zip_file.reset(fopen(path.c_str(), "wb"));
            zip_file.reset(fopen(path.c_str(), "wb"));
@@ -1497,7 +1463,7 @@ int main(int argc, char *argv[]) {
            } else {
            } else {
                zip_writer.reset(new ZipWriter(zip_file.get()));
                zip_writer.reset(new ZipWriter(zip_file.get()));
            }
            }
            add_text_zip_entry("version.txt", version);
            add_text_zip_entry("version.txt", ds.version_);
        }
        }


        if (ds.updateProgress_) {
        if (ds.updateProgress_) {
@@ -1505,7 +1471,7 @@ int main(int argc, char *argv[]) {
                // clang-format off
                // clang-format off
                std::vector<std::string> am_args = {
                std::vector<std::string> am_args = {
                     "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
                     "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
                     "--es", "android.intent.extra.NAME", suffix,
                     "--es", "android.intent.extra.NAME", ds.suffix_,
                     "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
                     "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
                     "--ei", "android.intent.extra.PID", std::to_string(getpid()),
                     "--ei", "android.intent.extra.PID", std::to_string(getpid()),
                     "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
                     "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
@@ -1535,18 +1501,13 @@ int main(int argc, char *argv[]) {
        }
        }
    }
    }


    if (do_fb && do_early_screenshot) {
    if (do_fb && ds.doEarlyScreenshot_) {
        if (screenshot_path.empty()) {
        if (ds.screenshotPath_.empty()) {
            // should not have happened
            // should not have happened
            MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
            MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
        } else {
        } else {
            MYLOGI("taking early screenshot\n");
            MYLOGI("taking early screenshot\n");
            take_screenshot(screenshot_path);
            ds.TakeScreenshot();
            MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
            if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
                MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
                        screenshot_path.c_str(), strerror(errno));
            }
        }
        }
    }
    }


@@ -1574,7 +1535,7 @@ int main(int argc, char *argv[]) {
    // NOTE: there should be no stdout output until now, otherwise it would break the header.
    // NOTE: there should be no stdout output until now, otherwise it would break the header.
    // In particular, DurationReport objects should be created passing 'title, NULL', so their
    // In particular, DurationReport objects should be created passing 'title, NULL', so their
    // duration is logged into MYLOG instead.
    // duration is logged into MYLOG instead.
    print_header(version);
    ds.PrintHeader();


    // Dumps systrace right away, otherwise it will be filled with unnecessary events.
    // Dumps systrace right away, otherwise it will be filled with unnecessary events.
    // First try to dump anrd trace if the daemon is running. Otherwise, dump
    // First try to dump anrd trace if the daemon is running. Otherwise, dump
@@ -1619,7 +1580,7 @@ int main(int argc, char *argv[]) {
        return -1;
        return -1;
    }
    }


    dumpstate(do_early_screenshot ? "": screenshot_path, version);
    dumpstate();


    /* close output if needed */
    /* close output if needed */
    if (is_redirecting) {
    if (is_redirecting) {
@@ -1643,31 +1604,30 @@ int main(int argc, char *argv[]) {
            }
            }
        }
        }
        if (change_suffix) {
        if (change_suffix) {
            MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), name.c_str());
            MYLOGI("changing suffix from %s to %s\n", ds.suffix_.c_str(), name.c_str());
            suffix = name;
            ds.suffix_ = name;
            if (!screenshot_path.empty()) {
            if (!ds.screenshotPath_.empty()) {
                std::string new_screenshot_path =
                std::string newScreenshotPath = ds.GetPath(".png");
                    ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".png";
                if (rename(ds.screenshotPath_.c_str(), newScreenshotPath.c_str())) {
                if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
                    MYLOGE("rename(%s, %s): %s\n", ds.screenshotPath_.c_str(),
                    MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
                           newScreenshotPath.c_str(), strerror(errno));
                            new_screenshot_path.c_str(), strerror(errno));
                } else {
                } else {
                    screenshot_path = new_screenshot_path;
                    ds.screenshotPath_ = newScreenshotPath;
                }
                }
            }
            }
        }
        }


        bool do_text_file = true;
        bool do_text_file = true;
        if (do_zip_file) {
        if (do_zip_file) {
            std::string entry_name = base_name + "-" + suffix + ".txt";
            std::string entry_name = ds.baseName_ + "-" + ds.suffix_ + ".txt";
            MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
            MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
            if (!finish_zip_file(entry_name, tmp_path, log_path, now)) {
            if (!finish_zip_file(entry_name, tmp_path, log_path)) {
                MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
                MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
                do_text_file = true;
                do_text_file = true;
            } else {
            } else {
                do_text_file = false;
                do_text_file = false;
                // Since zip file is already created, it needs to be renamed.
                // Since zip file is already created, it needs to be renamed.
                std::string new_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".zip";
                std::string new_path = ds.GetPath(".zip");
                if (path != new_path) {
                if (path != new_path) {
                    MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
                    MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
                    if (rename(path.c_str(), new_path.c_str())) {
                    if (rename(path.c_str(), new_path.c_str())) {
@@ -1680,7 +1640,7 @@ int main(int argc, char *argv[]) {
            }
            }
        }
        }
        if (do_text_file) {
        if (do_text_file) {
            path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".txt";
            path = ds.GetPath(".txt");
            MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
            MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
            if (rename(tmp_path.c_str(), path.c_str())) {
            if (rename(tmp_path.c_str(), path.c_str())) {
                MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
                MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
@@ -1724,7 +1684,7 @@ int main(int argc, char *argv[]) {
            if (do_fb) {
            if (do_fb) {
                am_args.push_back("--es");
                am_args.push_back("--es");
                am_args.push_back("android.intent.extra.SCREENSHOT");
                am_args.push_back("android.intent.extra.SCREENSHOT");
                am_args.push_back(screenshot_path);
                am_args.push_back(ds.screenshotPath_);
            }
            }
            if (is_remote_mode) {
            if (is_remote_mode) {
                am_args.push_back("--es");
                am_args.push_back("--es");
+44 −4
Original line number Original line Diff line number Diff line
@@ -192,6 +192,13 @@ class CommandOptions {
// TODO: move to dumpstate.cpp / utils.cpp once it's used in just one file
// TODO: move to dumpstate.cpp / utils.cpp once it's used in just one file
static const int WEIGHT_TOTAL = 6500;
static const int WEIGHT_TOTAL = 6500;


/*
 * List of supported zip format versions.
 *
 * See bugreport-format.md for more info.
 */
static std::string VERSION_DEFAULT = "1.0";

/*
/*
 * Main class driving a bugreport generation.
 * Main class driving a bugreport generation.
 *
 *
@@ -255,6 +262,13 @@ class Dumpstate {
     */
     */
    int DumpFile(const std::string& title, const std::string& path);
    int DumpFile(const std::string& title, const std::string& path);


    /*
     * Takes a screenshot and save it to the given `path`.
     *
     * If `path` is empty, uses a standard path based on the bugreport name.
     */
    void TakeScreenshot(const std::string& path = "");

    // TODO: members below should be private once refactor is finished
    // TODO: members below should be private once refactor is finished


    /*
    /*
@@ -262,6 +276,12 @@ class Dumpstate {
     */
     */
    void UpdateProgress(int delta);
    void UpdateProgress(int delta);


    /* Prints the dumpstate header on `stdout`. */
    void PrintHeader();

    /* Gets the path of a bugreport file with the given suffix. */
    std::string GetPath(const std::string& suffix);

    // TODO: initialize fields on constructor
    // TODO: initialize fields on constructor


    // dumpstate id - unique after each device reboot.
    // dumpstate id - unique after each device reboot.
@@ -270,6 +290,9 @@ class Dumpstate {
    // Whether progress updates should be published.
    // Whether progress updates should be published.
    bool updateProgress_ = false;
    bool updateProgress_ = false;


    // Whether it should take an screenshot earlier in the process.
    bool doEarlyScreenshot_ = false;

    // Currrent progress.
    // Currrent progress.
    int progress_ = 0;
    int progress_ = 0;


@@ -279,10 +302,30 @@ class Dumpstate {
    // When set, defines a socket file-descriptor use to report progress to bugreportz.
    // When set, defines a socket file-descriptor use to report progress to bugreportz.
    int controlSocketFd_ = -1;
    int controlSocketFd_ = -1;


    // Bugreport format version;
    std::string version_ = VERSION_DEFAULT;

    // Command-line arguments as string
    std::string args_;


    // Full path of the directory where the bugreport files will be written;
    // Extra options passed as system property.
    std::string extraOptions_;

    // Full path of the directory where the bugreport files will be written.
    std::string bugreportDir_;
    std::string bugreportDir_;


    // Full path of the temporary file containing the screenshot (when requested).
    std::string screenshotPath_;

    time_t now_;

    // Suffix of the bugreport files - it's typically the date (when invoked with -d),
    // although it could be changed by the user using a system property.
    std::string suffix_;

    // Base name (without suffix or extensions) of the bugreport files.
    std::string baseName_;

  private:
  private:
    // Used by GetInstance() only.
    // Used by GetInstance() only.
    Dumpstate(bool dryRun = false, const std::string& buildType = "user");
    Dumpstate(bool dryRun = false, const std::string& buildType = "user");
@@ -380,9 +423,6 @@ void play_sound(const char *path);
/* Implemented by libdumpstate_board to dump board-specific info */
/* Implemented by libdumpstate_board to dump board-specific info */
void dumpstate_board();
void dumpstate_board();


/* Takes a screenshot and save it to the given file */
void take_screenshot(const std::string& path);

/* Vibrates for a given durating (in milliseconds). */
/* Vibrates for a given durating (in milliseconds). */
void vibrate(FILE* vibrator, int ms);
void vibrate(FILE* vibrator, int ms);


+15 −4
Original line number Original line Diff line number Diff line
@@ -163,7 +163,7 @@ CommandOptions::CommandOptionsBuilder CommandOptions::WithTimeout(long timeout)
}
}


Dumpstate::Dumpstate(bool dryRun, const std::string& buildType)
Dumpstate::Dumpstate(bool dryRun, const std::string& buildType)
    : dryRun_(dryRun), buildType_(buildType) {
    : now_(time(nullptr)), dryRun_(dryRun), buildType_(buildType) {
}
}


Dumpstate& Dumpstate::GetInstance() {
Dumpstate& Dumpstate::GetInstance() {
@@ -208,6 +208,10 @@ bool Dumpstate::IsUserBuild() {
    return "user" == buildType_;
    return "user" == buildType_;
}
}


std::string Dumpstate::GetPath(const std::string& suffix) {
    return bugreportDir_ + "/" + baseName_ + "-" + suffix_ + suffix;
}

void for_each_userid(void (*func)(int), const char *header) {
void for_each_userid(void (*func)(int), const char *header) {
    if (IsDryRun()) return;
    if (IsDryRun()) return;


@@ -1342,9 +1346,16 @@ void Dumpstate::UpdateProgress(int delta) {
    }
    }
}
}


void take_screenshot(const std::string& path) {
void Dumpstate::TakeScreenshot(const std::string& path) {
    RunCommand("", {"/system/bin/screencap", "-p", path},
    const std::string& realPath = path.empty() ? screenshotPath_ : path;
               CommandOptions::WithTimeout(10).Always().RedirectStderr().Build());
    int status =
        RunCommand("", {"/system/bin/screencap", "-p", realPath},
                   CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
    if (status == 0) {
        MYLOGD("Screenshot saved on %s\n", realPath.c_str());
    } else {
        MYLOGE("Failed to take screenshot on %s\n", realPath.c_str());
    }
}
}


void vibrate(FILE* vibrator, int ms) {
void vibrate(FILE* vibrator, int ms) {