Loading cmds/dumpstate/bugreport-format.md +2 −2 Original line number Diff line number Diff line Loading @@ -63,8 +63,8 @@ changes become stable. For example, the initial version during _Android N_ development was **1.0-dev1**. When `dumpsys` was split in 2 sections but not all tools were ready to parse that format, the version was named **1.0-dev2**, which had to be passed do `dumpsys` explicitly (i.e., trhough a `-V 1.0-dev2` argument). Once that format became stable and tools which had to be passed to `dumpsys` explicitly (by setting the `dumpstate.version` system property). Once that format became stable and tools knew how to parse it, the default version became **1.0-dev2**. Similarly, if changes in the file format are made after the initial release of Loading cmds/dumpstate/dumpstate.cpp +146 −137 Original line number Diff line number Diff line Loading @@ -111,6 +111,7 @@ static const std::string ZIP_ROOT_DIR = "FS"; static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options"; static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id"; static constexpr char PROPERTY_VERSION[] = "dumpstate.version"; /* 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. */ Loading Loading @@ -161,7 +162,7 @@ void add_mountinfo() { if (!ds.IsZipping()) return; std::string title = "MOUNT INFO"; mount_points.clear(); DurationReporter durationReporter(title, nullptr); DurationReporter duration_reporter(title, nullptr); for_each_pid(do_mountinfo, nullptr); MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size()); } Loading Loading @@ -612,8 +613,8 @@ void Dumpstate::PrintHeader() const { JustDumpFile("", "/proc/version"); printf("Command line: %s\n", strtok(cmdline_buf, "\n")); printf("Bugreport format version: %s\n", version_.c_str()); printf("Dumpstate info: id=%lu pid=%d dryRun=%d args=%s extraOptions=%s\n", id_, getpid(), dryRun_, args_.c_str(), extraOptions_.c_str()); printf("Dumpstate info: id=%lu pid=%d dry_run=%d args=%s extra_options=%s\n", id_, getpid(), dry_run_, args_.c_str(), extra_options_.c_str()); printf("\n"); } Loading Loading @@ -705,7 +706,7 @@ void Dumpstate::AddDir(const std::string& dir, bool recursive) { return; } MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive); DurationReporter durationReporter(dir, nullptr); DurationReporter duration_reporter(dir, nullptr); dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd); } Loading Loading @@ -751,7 +752,7 @@ static void dump_iptables() { } static void dumpstate() { DurationReporter durationReporter("DUMPSTATE"); DurationReporter duration_reporter("DUMPSTATE"); unsigned long timeout; dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version"); Loading Loading @@ -797,7 +798,7 @@ static void dumpstate() { /* Dump Bluetooth HCI logs */ ds.AddDir("/data/misc/bluetooth/logs", true); if (!ds.doEarlyScreenshot_) { if (!ds.do_early_screenshot_) { MYLOGI("taking late screenshot\n"); ds.TakeScreenshot(); } Loading Loading @@ -1038,7 +1039,7 @@ static void dumpstate() { printf("========================================================\n"); printf("== Final progress (pid %d): %d/%d (originally %d)\n", getpid(), ds.progress_, ds.weightTotal_, WEIGHT_TOTAL); ds.weight_total_, WEIGHT_TOTAL); printf("========================================================\n"); printf("== dumpstate: done (id %lu)\n", ds.id_); printf("========================================================\n"); Loading @@ -1063,8 +1064,7 @@ static void ShowUsageAndExit(int exitCode = 1) { "progress (requires -o and -B)\n" " -R: take bugreport in remote mode (requires -o, -z, -d and -B, " "shouldn't be used with -P)\n" " -V: sets the bugreport format version (valid values: %s)\n", VERSION_DEFAULT.c_str()); " -v: prints the dumpstate header and exit\n"); exit(exitCode); } Loading Loading @@ -1099,9 +1099,9 @@ static void register_sig_handler() { } bool Dumpstate::FinishZipFile() { std::string entry_name = baseName_ + "-" + name_ + ".txt"; std::string entry_name = base_name_ + "-" + name_ + ".txt"; MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(), tmp_path.c_str()); tmp_path_.c_str()); // Final timestamp char date[80]; time_t the_real_now_please_stand_up = time(nullptr); Loading @@ -1109,7 +1109,7 @@ bool Dumpstate::FinishZipFile() { MYLOGD("dumpstate id %lu finished around %s (%ld s)\n", ds.id_, date, the_real_now_please_stand_up - ds.now_); if (!ds.AddZipEntry(entry_name, tmp_path)) { if (!ds.AddZipEntry(entry_name, tmp_path_)) { MYLOGE("Failed to add text entry to .zip file\n"); return false; } Loading @@ -1120,12 +1120,12 @@ bool Dumpstate::FinishZipFile() { // Add log file (which contains stderr output) to zip... fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n"); if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path.c_str())) { if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) { MYLOGE("Failed to add dumpstate log to .zip file\n"); return false; } // ... and re-opens it for further logging. redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path.c_str())); redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str())); fprintf(stderr, "\n"); int32_t err = zip_writer->Finish(); Loading @@ -1138,12 +1138,12 @@ bool Dumpstate::FinishZipFile() { ds.zip_file.reset(nullptr); if (IsUserBuild()) { MYLOGD("Removing temporary file %s\n", tmp_path.c_str()) if (remove(tmp_path.c_str()) != 0) { ALOGW("remove(%s): %s\n", tmp_path.c_str(), strerror(errno)); MYLOGD("Removing temporary file %s\n", tmp_path_.c_str()) if (remove(tmp_path_.c_str()) != 0) { ALOGW("remove(%s): %s\n", tmp_path_.c_str(), strerror(errno)); } } else { MYLOGD("Keeping temporary file %s on non-user build\n", tmp_path.c_str()) MYLOGD("Keeping temporary file %s on non-user build\n", tmp_path_.c_str()) } return true; Loading Loading @@ -1194,37 +1194,7 @@ int main(int argc, char *argv[]) { int do_fb = 0; int do_broadcast = 0; int is_remote_mode = 0; MYLOGI("begin\n"); if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) { MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno)); } else { MYLOGD("Wake lock acquired.\n"); atexit(wake_lock_releaser); register_sig_handler(); } if (ds.IsDryRun()) { MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n"); } // TODO: use helper function to convert argv into a string for (int i = 0; i < argc; i++) { ds.args_ += argv[i]; if (i < argc - 1) { ds.args_ += " "; } } ds.extraOptions_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, ""); MYLOGI("Dumpstate args: %s (extra options: %s)\n", ds.args_.c_str(), ds.extraOptions_.c_str()); /* gets the sequential id */ int lastId = android::base::GetIntProperty(PROPERTY_LAST_ID, 0); ds.id_ = ++lastId; android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(lastId)); MYLOGI("dumpstate id: %lu\n", ds.id_); bool show_header_only = false; /* set as high priority, and protect from OOM killer */ setpriority(PRIO_PROCESS, 0, -20); Loading Loading @@ -1252,13 +1222,13 @@ int main(int argc, char *argv[]) { case 'o': use_outfile = optarg; break; case 's': use_socket = 1; break; case 'S': use_control_socket = 1; break; case 'v': break; // compatibility no-op case 'v': show_header_only = true; break; case 'q': do_vibrate = 0; break; case 'p': do_fb = 1; break; case 'P': ds.updateProgress_ = true; break; case 'P': ds.update_progress_ = true; break; case 'R': is_remote_mode = 1; break; case 'B': do_broadcast = 1; break; case 'V': ds.version_ = optarg; break; case 'V': break; // compatibility no-op case 'h': ShowUsageAndExit(0); break; Loading @@ -1269,29 +1239,35 @@ int main(int argc, char *argv[]) { } } if (!ds.extraOptions_.empty()) { // TODO: use helper function to convert argv into a string for (int i = 0; i < argc; i++) { ds.args_ += argv[i]; if (i < argc - 1) { ds.args_ += " "; } } ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, ""); if (!ds.extra_options_.empty()) { // Framework uses a system property to override some command-line args. // Currently, it contains the type of the requested bugreport. if (ds.extraOptions_ == "bugreportplus") { MYLOGD("Running as bugreportplus: add -P, remove -p\n"); ds.updateProgress_ = true; if (ds.extra_options_ == "bugreportplus") { ds.update_progress_ = true; do_fb = 0; } else if (ds.extraOptions_ == "bugreportremote") { MYLOGD("Running as bugreportremote: add -q -R, remove -p\n"); } else if (ds.extra_options_ == "bugreportremote") { do_vibrate = 0; is_remote_mode = 1; do_fb = 0; } else if (ds.extraOptions_ == "bugreportwear") { MYLOGD("Running as bugreportwear: add -P\n"); ds.updateProgress_ = true; } else if (ds.extra_options_ == "bugreportwear") { ds.update_progress_ = true; } else { MYLOGE("Unknown extra option: %s\n", ds.extraOptions_.c_str()); MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str()); } // Reset the property android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, ""); } if ((do_zip_file || do_add_date || ds.updateProgress_ || do_broadcast) && !use_outfile) { if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) { ExitOnInvalidArgs(); } Loading @@ -1299,21 +1275,54 @@ int main(int argc, char *argv[]) { ExitOnInvalidArgs(); } if (ds.updateProgress_ && !do_broadcast) { if (ds.update_progress_ && !do_broadcast) { ExitOnInvalidArgs(); } if (is_remote_mode && (ds.updateProgress_ || !do_broadcast || !do_zip_file || !do_add_date)) { if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) { ExitOnInvalidArgs(); } if (ds.version_ != VERSION_DEFAULT) { ShowUsageAndExit(); if (ds.version_ == VERSION_DEFAULT) { ds.version_ = VERSION_CURRENT; } if (ds.version_ != VERSION_CURRENT) { MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s')\n", ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str()); exit(1); } if (show_header_only) { ds.PrintHeader(); exit(0); } /* gets the sequential id */ int last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0); ds.id_ = ++last_id; android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id)); MYLOGI("begin\n"); if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) { MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno)); } else { MYLOGD("Wake lock acquired.\n"); atexit(wake_lock_releaser); register_sig_handler(); } if (ds.IsDryRun()) { MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n"); } MYLOGI("dumpstate info: id=%lu, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(), ds.extra_options_.c_str()); MYLOGI("bugreport format version: %s\n", ds.version_.c_str()); ds.doEarlyScreenshot_ = ds.updateProgress_; ds.do_early_screenshot_ = ds.update_progress_; // If we are going to use a socket, do it as early as possible // to avoid timeouts from bugreport. Loading @@ -1323,16 +1332,16 @@ int main(int argc, char *argv[]) { if (use_control_socket) { MYLOGD("Opening control socket\n"); ds.controlSocketFd_ = open_socket("dumpstate"); ds.updateProgress_ = 1; ds.control_socket_fd_ = open_socket("dumpstate"); ds.update_progress_ = 1; } /* redirect output if needed */ bool is_redirecting = !use_socket && use_outfile; if (is_redirecting) { ds.bugreportDir_ = dirname(use_outfile); ds.baseName_ = basename(use_outfile); ds.bugreport_dir_ = dirname(use_outfile); ds.base_name_ = basename(use_outfile); if (do_add_date) { char date[80]; strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_)); Loading @@ -1341,12 +1350,12 @@ int main(int argc, char *argv[]) { ds.name_ = "undated"; } std::string buildId = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD"); ds.baseName_ = ds.baseName_ + "-" + buildId; ds.base_name_ += "-" + buildId; if (do_fb) { ds.screenshotPath_ = ds.GetPath(".png"); ds.screenshot_path_ = ds.GetPath(".png"); } ds.tmp_path = ds.GetPath(".tmp"); ds.log_path = ds.GetPath("-dumpstate_log-" + std::to_string(getpid()) + ".txt"); ds.tmp_path_ = ds.GetPath(".tmp"); ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(getpid()) + ".txt"); MYLOGD( "Bugreport dir: %s\n" Loading @@ -1355,16 +1364,16 @@ int main(int argc, char *argv[]) { "Log path: %s\n" "Temporary path: %s\n" "Screenshot path: %s\n", ds.bugreportDir_.c_str(), ds.baseName_.c_str(), ds.name_.c_str(), ds.log_path.c_str(), ds.tmp_path.c_str(), ds.screenshotPath_.c_str()); ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str()); if (do_zip_file) { ds.path = ds.GetPath(".zip"); MYLOGD("Creating initial .zip file (%s)\n", ds.path.c_str()); create_parent_dirs(ds.path.c_str()); ds.zip_file.reset(fopen(ds.path.c_str(), "wb")); ds.path_ = ds.GetPath(".zip"); MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str()); create_parent_dirs(ds.path_.c_str()); ds.zip_file.reset(fopen(ds.path_.c_str(), "wb")); if (ds.zip_file == nullptr) { MYLOGE("fopen(%s, 'wb'): %s\n", ds.path.c_str(), strerror(errno)); MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno)); do_zip_file = 0; } else { zip_writer.reset(new ZipWriter(ds.zip_file.get())); Loading @@ -1372,7 +1381,7 @@ int main(int argc, char *argv[]) { ds.AddTextZipEntry("version.txt", ds.version_); } if (ds.updateProgress_) { if (ds.update_progress_) { if (do_broadcast) { // clang-format off std::vector<std::string> am_args = { Loading @@ -1386,7 +1395,7 @@ int main(int argc, char *argv[]) { send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args); } if (use_control_socket) { dprintf(ds.controlSocketFd_, "BEGIN:%s\n", ds.path.c_str()); dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str()); } } } Loading @@ -1407,8 +1416,8 @@ int main(int argc, char *argv[]) { } } if (do_fb && ds.doEarlyScreenshot_) { if (ds.screenshotPath_.empty()) { if (do_fb && ds.do_early_screenshot_) { if (ds.screenshot_path_.empty()) { // should not have happened MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n"); } else { Loading @@ -1418,25 +1427,25 @@ int main(int argc, char *argv[]) { } if (do_zip_file) { if (chown(ds.path.c_str(), AID_SHELL, AID_SHELL)) { MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path.c_str(), if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) { MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(), strerror(errno)); } } if (is_redirecting) { redirect_to_file(stderr, const_cast<char*>(ds.log_path.c_str())); if (chown(ds.log_path.c_str(), AID_SHELL, AID_SHELL)) { MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", ds.log_path.c_str(), strerror(errno)); redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str())); if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) { MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", ds.log_path_.c_str(), strerror(errno)); } /* TODO: rather than generating a text file now and zipping it later, it would be more efficient to redirect stdout to the zip entry directly, but the libziparchive doesn't support that option yet. */ redirect_to_file(stdout, const_cast<char*>(ds.tmp_path.c_str())); if (chown(ds.tmp_path.c_str(), AID_SHELL, AID_SHELL)) { redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str())); if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) { MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n", ds.tmp_path.c_str(), strerror(errno)); ds.tmp_path_.c_str(), strerror(errno)); } } // NOTE: there should be no stdout output until now, otherwise it would break the header. Loading Loading @@ -1513,13 +1522,13 @@ int main(int argc, char *argv[]) { if (change_suffix) { MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str()); ds.name_ = name; if (!ds.screenshotPath_.empty()) { std::string newScreenshotPath = ds.GetPath(".png"); if (rename(ds.screenshotPath_.c_str(), newScreenshotPath.c_str())) { MYLOGE("rename(%s, %s): %s\n", ds.screenshotPath_.c_str(), newScreenshotPath.c_str(), strerror(errno)); if (!ds.screenshot_path_.empty()) { std::string new_screenshot_path = ds.GetPath(".png"); if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) { MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(), new_screenshot_path.c_str(), strerror(errno)); } else { ds.screenshotPath_ = newScreenshotPath; ds.screenshot_path_ = new_screenshot_path; } } } Loading @@ -1532,36 +1541,36 @@ int main(int argc, char *argv[]) { } else { do_text_file = false; // Since zip file is already created, it needs to be renamed. std::string newPath = ds.GetPath(".zip"); if (ds.path != newPath) { MYLOGD("Renaming zip file from %s to %s\n", ds.path.c_str(), newPath.c_str()); if (rename(ds.path.c_str(), newPath.c_str())) { MYLOGE("rename(%s, %s): %s\n", ds.path.c_str(), newPath.c_str(), std::string new_path = ds.GetPath(".zip"); if (ds.path_ != new_path) { MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str()); if (rename(ds.path_.c_str(), new_path.c_str())) { MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(), strerror(errno)); } else { ds.path = newPath; ds.path_ = new_path; } } } } if (do_text_file) { ds.path = ds.GetPath(".txt"); MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path.c_str(), ds.tmp_path.c_str()); if (rename(ds.tmp_path.c_str(), ds.path.c_str())) { MYLOGE("rename(%s, %s): %s\n", ds.tmp_path.c_str(), ds.path.c_str(), ds.path_ = ds.GetPath(".txt"); MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str()); if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) { MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno)); ds.path.clear(); ds.path_.clear(); } } if (use_control_socket) { if (do_text_file) { dprintf(ds.controlSocketFd_, dprintf(ds.control_socket_fd_, "FAIL:could not create zip file, check %s " "for more details\n", ds.log_path.c_str()); ds.log_path_.c_str()); } else { dprintf(ds.controlSocketFd_, "OK:%s\n", ds.path.c_str()); dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str()); } } } Loading @@ -1576,27 +1585,27 @@ int main(int argc, char *argv[]) { /* tell activity manager we're done */ if (do_broadcast) { if (!ds.path.empty()) { MYLOGI("Final bugreport path: %s\n", ds.path.c_str()); if (!ds.path_.empty()) { MYLOGI("Final bugreport path: %s\n", ds.path_.c_str()); // clang-format off std::vector<std::string> am_args = { "--receiver-permission", "android.permission.DUMP", "--receiver-foreground", "--ei", "android.intent.extra.ID", std::to_string(ds.id_), "--ei", "android.intent.extra.PID", std::to_string(getpid()), "--ei", "android.intent.extra.MAX", std::to_string(ds.weightTotal_), "--es", "android.intent.extra.BUGREPORT", ds.path, "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path "--ei", "android.intent.extra.MAX", std::to_string(ds.weight_total_), "--es", "android.intent.extra.BUGREPORT", ds.path_, "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_ }; // clang-format on if (do_fb) { am_args.push_back("--es"); am_args.push_back("android.intent.extra.SCREENSHOT"); am_args.push_back(ds.screenshotPath_); am_args.push_back(ds.screenshot_path_); } if (is_remote_mode) { am_args.push_back("--es"); am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH"); am_args.push_back(SHA256_file_hash(ds.path)); am_args.push_back(SHA256_file_hash(ds.path_)); send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args); } else { send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args); Loading @@ -1606,16 +1615,16 @@ int main(int argc, char *argv[]) { } } MYLOGD("Final progress: %d/%d (originally %d)\n", ds.progress_, ds.weightTotal_, WEIGHT_TOTAL); MYLOGD("Final progress: %d/%d (originally %d)\n", ds.progress_, ds.weight_total_, WEIGHT_TOTAL); MYLOGI("done (id %lu)\n", ds.id_); if (is_redirecting) { fclose(stderr); } if (use_control_socket && ds.controlSocketFd_ != -1) { if (use_control_socket && ds.control_socket_fd_ != -1) { MYLOGD("Closing control socket\n"); close(ds.controlSocketFd_); close(ds.control_socket_fd_); } return 0; Loading Loading
cmds/dumpstate/bugreport-format.md +2 −2 Original line number Diff line number Diff line Loading @@ -63,8 +63,8 @@ changes become stable. For example, the initial version during _Android N_ development was **1.0-dev1**. When `dumpsys` was split in 2 sections but not all tools were ready to parse that format, the version was named **1.0-dev2**, which had to be passed do `dumpsys` explicitly (i.e., trhough a `-V 1.0-dev2` argument). Once that format became stable and tools which had to be passed to `dumpsys` explicitly (by setting the `dumpstate.version` system property). Once that format became stable and tools knew how to parse it, the default version became **1.0-dev2**. Similarly, if changes in the file format are made after the initial release of Loading
cmds/dumpstate/dumpstate.cpp +146 −137 Original line number Diff line number Diff line Loading @@ -111,6 +111,7 @@ static const std::string ZIP_ROOT_DIR = "FS"; static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options"; static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id"; static constexpr char PROPERTY_VERSION[] = "dumpstate.version"; /* 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. */ Loading Loading @@ -161,7 +162,7 @@ void add_mountinfo() { if (!ds.IsZipping()) return; std::string title = "MOUNT INFO"; mount_points.clear(); DurationReporter durationReporter(title, nullptr); DurationReporter duration_reporter(title, nullptr); for_each_pid(do_mountinfo, nullptr); MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size()); } Loading Loading @@ -612,8 +613,8 @@ void Dumpstate::PrintHeader() const { JustDumpFile("", "/proc/version"); printf("Command line: %s\n", strtok(cmdline_buf, "\n")); printf("Bugreport format version: %s\n", version_.c_str()); printf("Dumpstate info: id=%lu pid=%d dryRun=%d args=%s extraOptions=%s\n", id_, getpid(), dryRun_, args_.c_str(), extraOptions_.c_str()); printf("Dumpstate info: id=%lu pid=%d dry_run=%d args=%s extra_options=%s\n", id_, getpid(), dry_run_, args_.c_str(), extra_options_.c_str()); printf("\n"); } Loading Loading @@ -705,7 +706,7 @@ void Dumpstate::AddDir(const std::string& dir, bool recursive) { return; } MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive); DurationReporter durationReporter(dir, nullptr); DurationReporter duration_reporter(dir, nullptr); dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd); } Loading Loading @@ -751,7 +752,7 @@ static void dump_iptables() { } static void dumpstate() { DurationReporter durationReporter("DUMPSTATE"); DurationReporter duration_reporter("DUMPSTATE"); unsigned long timeout; dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version"); Loading Loading @@ -797,7 +798,7 @@ static void dumpstate() { /* Dump Bluetooth HCI logs */ ds.AddDir("/data/misc/bluetooth/logs", true); if (!ds.doEarlyScreenshot_) { if (!ds.do_early_screenshot_) { MYLOGI("taking late screenshot\n"); ds.TakeScreenshot(); } Loading Loading @@ -1038,7 +1039,7 @@ static void dumpstate() { printf("========================================================\n"); printf("== Final progress (pid %d): %d/%d (originally %d)\n", getpid(), ds.progress_, ds.weightTotal_, WEIGHT_TOTAL); ds.weight_total_, WEIGHT_TOTAL); printf("========================================================\n"); printf("== dumpstate: done (id %lu)\n", ds.id_); printf("========================================================\n"); Loading @@ -1063,8 +1064,7 @@ static void ShowUsageAndExit(int exitCode = 1) { "progress (requires -o and -B)\n" " -R: take bugreport in remote mode (requires -o, -z, -d and -B, " "shouldn't be used with -P)\n" " -V: sets the bugreport format version (valid values: %s)\n", VERSION_DEFAULT.c_str()); " -v: prints the dumpstate header and exit\n"); exit(exitCode); } Loading Loading @@ -1099,9 +1099,9 @@ static void register_sig_handler() { } bool Dumpstate::FinishZipFile() { std::string entry_name = baseName_ + "-" + name_ + ".txt"; std::string entry_name = base_name_ + "-" + name_ + ".txt"; MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(), tmp_path.c_str()); tmp_path_.c_str()); // Final timestamp char date[80]; time_t the_real_now_please_stand_up = time(nullptr); Loading @@ -1109,7 +1109,7 @@ bool Dumpstate::FinishZipFile() { MYLOGD("dumpstate id %lu finished around %s (%ld s)\n", ds.id_, date, the_real_now_please_stand_up - ds.now_); if (!ds.AddZipEntry(entry_name, tmp_path)) { if (!ds.AddZipEntry(entry_name, tmp_path_)) { MYLOGE("Failed to add text entry to .zip file\n"); return false; } Loading @@ -1120,12 +1120,12 @@ bool Dumpstate::FinishZipFile() { // Add log file (which contains stderr output) to zip... fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n"); if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path.c_str())) { if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) { MYLOGE("Failed to add dumpstate log to .zip file\n"); return false; } // ... and re-opens it for further logging. redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path.c_str())); redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str())); fprintf(stderr, "\n"); int32_t err = zip_writer->Finish(); Loading @@ -1138,12 +1138,12 @@ bool Dumpstate::FinishZipFile() { ds.zip_file.reset(nullptr); if (IsUserBuild()) { MYLOGD("Removing temporary file %s\n", tmp_path.c_str()) if (remove(tmp_path.c_str()) != 0) { ALOGW("remove(%s): %s\n", tmp_path.c_str(), strerror(errno)); MYLOGD("Removing temporary file %s\n", tmp_path_.c_str()) if (remove(tmp_path_.c_str()) != 0) { ALOGW("remove(%s): %s\n", tmp_path_.c_str(), strerror(errno)); } } else { MYLOGD("Keeping temporary file %s on non-user build\n", tmp_path.c_str()) MYLOGD("Keeping temporary file %s on non-user build\n", tmp_path_.c_str()) } return true; Loading Loading @@ -1194,37 +1194,7 @@ int main(int argc, char *argv[]) { int do_fb = 0; int do_broadcast = 0; int is_remote_mode = 0; MYLOGI("begin\n"); if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) { MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno)); } else { MYLOGD("Wake lock acquired.\n"); atexit(wake_lock_releaser); register_sig_handler(); } if (ds.IsDryRun()) { MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n"); } // TODO: use helper function to convert argv into a string for (int i = 0; i < argc; i++) { ds.args_ += argv[i]; if (i < argc - 1) { ds.args_ += " "; } } ds.extraOptions_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, ""); MYLOGI("Dumpstate args: %s (extra options: %s)\n", ds.args_.c_str(), ds.extraOptions_.c_str()); /* gets the sequential id */ int lastId = android::base::GetIntProperty(PROPERTY_LAST_ID, 0); ds.id_ = ++lastId; android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(lastId)); MYLOGI("dumpstate id: %lu\n", ds.id_); bool show_header_only = false; /* set as high priority, and protect from OOM killer */ setpriority(PRIO_PROCESS, 0, -20); Loading Loading @@ -1252,13 +1222,13 @@ int main(int argc, char *argv[]) { case 'o': use_outfile = optarg; break; case 's': use_socket = 1; break; case 'S': use_control_socket = 1; break; case 'v': break; // compatibility no-op case 'v': show_header_only = true; break; case 'q': do_vibrate = 0; break; case 'p': do_fb = 1; break; case 'P': ds.updateProgress_ = true; break; case 'P': ds.update_progress_ = true; break; case 'R': is_remote_mode = 1; break; case 'B': do_broadcast = 1; break; case 'V': ds.version_ = optarg; break; case 'V': break; // compatibility no-op case 'h': ShowUsageAndExit(0); break; Loading @@ -1269,29 +1239,35 @@ int main(int argc, char *argv[]) { } } if (!ds.extraOptions_.empty()) { // TODO: use helper function to convert argv into a string for (int i = 0; i < argc; i++) { ds.args_ += argv[i]; if (i < argc - 1) { ds.args_ += " "; } } ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, ""); if (!ds.extra_options_.empty()) { // Framework uses a system property to override some command-line args. // Currently, it contains the type of the requested bugreport. if (ds.extraOptions_ == "bugreportplus") { MYLOGD("Running as bugreportplus: add -P, remove -p\n"); ds.updateProgress_ = true; if (ds.extra_options_ == "bugreportplus") { ds.update_progress_ = true; do_fb = 0; } else if (ds.extraOptions_ == "bugreportremote") { MYLOGD("Running as bugreportremote: add -q -R, remove -p\n"); } else if (ds.extra_options_ == "bugreportremote") { do_vibrate = 0; is_remote_mode = 1; do_fb = 0; } else if (ds.extraOptions_ == "bugreportwear") { MYLOGD("Running as bugreportwear: add -P\n"); ds.updateProgress_ = true; } else if (ds.extra_options_ == "bugreportwear") { ds.update_progress_ = true; } else { MYLOGE("Unknown extra option: %s\n", ds.extraOptions_.c_str()); MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str()); } // Reset the property android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, ""); } if ((do_zip_file || do_add_date || ds.updateProgress_ || do_broadcast) && !use_outfile) { if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) { ExitOnInvalidArgs(); } Loading @@ -1299,21 +1275,54 @@ int main(int argc, char *argv[]) { ExitOnInvalidArgs(); } if (ds.updateProgress_ && !do_broadcast) { if (ds.update_progress_ && !do_broadcast) { ExitOnInvalidArgs(); } if (is_remote_mode && (ds.updateProgress_ || !do_broadcast || !do_zip_file || !do_add_date)) { if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) { ExitOnInvalidArgs(); } if (ds.version_ != VERSION_DEFAULT) { ShowUsageAndExit(); if (ds.version_ == VERSION_DEFAULT) { ds.version_ = VERSION_CURRENT; } if (ds.version_ != VERSION_CURRENT) { MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s')\n", ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str()); exit(1); } if (show_header_only) { ds.PrintHeader(); exit(0); } /* gets the sequential id */ int last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0); ds.id_ = ++last_id; android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id)); MYLOGI("begin\n"); if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) { MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno)); } else { MYLOGD("Wake lock acquired.\n"); atexit(wake_lock_releaser); register_sig_handler(); } if (ds.IsDryRun()) { MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n"); } MYLOGI("dumpstate info: id=%lu, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(), ds.extra_options_.c_str()); MYLOGI("bugreport format version: %s\n", ds.version_.c_str()); ds.doEarlyScreenshot_ = ds.updateProgress_; ds.do_early_screenshot_ = ds.update_progress_; // If we are going to use a socket, do it as early as possible // to avoid timeouts from bugreport. Loading @@ -1323,16 +1332,16 @@ int main(int argc, char *argv[]) { if (use_control_socket) { MYLOGD("Opening control socket\n"); ds.controlSocketFd_ = open_socket("dumpstate"); ds.updateProgress_ = 1; ds.control_socket_fd_ = open_socket("dumpstate"); ds.update_progress_ = 1; } /* redirect output if needed */ bool is_redirecting = !use_socket && use_outfile; if (is_redirecting) { ds.bugreportDir_ = dirname(use_outfile); ds.baseName_ = basename(use_outfile); ds.bugreport_dir_ = dirname(use_outfile); ds.base_name_ = basename(use_outfile); if (do_add_date) { char date[80]; strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_)); Loading @@ -1341,12 +1350,12 @@ int main(int argc, char *argv[]) { ds.name_ = "undated"; } std::string buildId = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD"); ds.baseName_ = ds.baseName_ + "-" + buildId; ds.base_name_ += "-" + buildId; if (do_fb) { ds.screenshotPath_ = ds.GetPath(".png"); ds.screenshot_path_ = ds.GetPath(".png"); } ds.tmp_path = ds.GetPath(".tmp"); ds.log_path = ds.GetPath("-dumpstate_log-" + std::to_string(getpid()) + ".txt"); ds.tmp_path_ = ds.GetPath(".tmp"); ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(getpid()) + ".txt"); MYLOGD( "Bugreport dir: %s\n" Loading @@ -1355,16 +1364,16 @@ int main(int argc, char *argv[]) { "Log path: %s\n" "Temporary path: %s\n" "Screenshot path: %s\n", ds.bugreportDir_.c_str(), ds.baseName_.c_str(), ds.name_.c_str(), ds.log_path.c_str(), ds.tmp_path.c_str(), ds.screenshotPath_.c_str()); ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str()); if (do_zip_file) { ds.path = ds.GetPath(".zip"); MYLOGD("Creating initial .zip file (%s)\n", ds.path.c_str()); create_parent_dirs(ds.path.c_str()); ds.zip_file.reset(fopen(ds.path.c_str(), "wb")); ds.path_ = ds.GetPath(".zip"); MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str()); create_parent_dirs(ds.path_.c_str()); ds.zip_file.reset(fopen(ds.path_.c_str(), "wb")); if (ds.zip_file == nullptr) { MYLOGE("fopen(%s, 'wb'): %s\n", ds.path.c_str(), strerror(errno)); MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno)); do_zip_file = 0; } else { zip_writer.reset(new ZipWriter(ds.zip_file.get())); Loading @@ -1372,7 +1381,7 @@ int main(int argc, char *argv[]) { ds.AddTextZipEntry("version.txt", ds.version_); } if (ds.updateProgress_) { if (ds.update_progress_) { if (do_broadcast) { // clang-format off std::vector<std::string> am_args = { Loading @@ -1386,7 +1395,7 @@ int main(int argc, char *argv[]) { send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args); } if (use_control_socket) { dprintf(ds.controlSocketFd_, "BEGIN:%s\n", ds.path.c_str()); dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str()); } } } Loading @@ -1407,8 +1416,8 @@ int main(int argc, char *argv[]) { } } if (do_fb && ds.doEarlyScreenshot_) { if (ds.screenshotPath_.empty()) { if (do_fb && ds.do_early_screenshot_) { if (ds.screenshot_path_.empty()) { // should not have happened MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n"); } else { Loading @@ -1418,25 +1427,25 @@ int main(int argc, char *argv[]) { } if (do_zip_file) { if (chown(ds.path.c_str(), AID_SHELL, AID_SHELL)) { MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path.c_str(), if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) { MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(), strerror(errno)); } } if (is_redirecting) { redirect_to_file(stderr, const_cast<char*>(ds.log_path.c_str())); if (chown(ds.log_path.c_str(), AID_SHELL, AID_SHELL)) { MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", ds.log_path.c_str(), strerror(errno)); redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str())); if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) { MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", ds.log_path_.c_str(), strerror(errno)); } /* TODO: rather than generating a text file now and zipping it later, it would be more efficient to redirect stdout to the zip entry directly, but the libziparchive doesn't support that option yet. */ redirect_to_file(stdout, const_cast<char*>(ds.tmp_path.c_str())); if (chown(ds.tmp_path.c_str(), AID_SHELL, AID_SHELL)) { redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str())); if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) { MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n", ds.tmp_path.c_str(), strerror(errno)); ds.tmp_path_.c_str(), strerror(errno)); } } // NOTE: there should be no stdout output until now, otherwise it would break the header. Loading Loading @@ -1513,13 +1522,13 @@ int main(int argc, char *argv[]) { if (change_suffix) { MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str()); ds.name_ = name; if (!ds.screenshotPath_.empty()) { std::string newScreenshotPath = ds.GetPath(".png"); if (rename(ds.screenshotPath_.c_str(), newScreenshotPath.c_str())) { MYLOGE("rename(%s, %s): %s\n", ds.screenshotPath_.c_str(), newScreenshotPath.c_str(), strerror(errno)); if (!ds.screenshot_path_.empty()) { std::string new_screenshot_path = ds.GetPath(".png"); if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) { MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(), new_screenshot_path.c_str(), strerror(errno)); } else { ds.screenshotPath_ = newScreenshotPath; ds.screenshot_path_ = new_screenshot_path; } } } Loading @@ -1532,36 +1541,36 @@ int main(int argc, char *argv[]) { } else { do_text_file = false; // Since zip file is already created, it needs to be renamed. std::string newPath = ds.GetPath(".zip"); if (ds.path != newPath) { MYLOGD("Renaming zip file from %s to %s\n", ds.path.c_str(), newPath.c_str()); if (rename(ds.path.c_str(), newPath.c_str())) { MYLOGE("rename(%s, %s): %s\n", ds.path.c_str(), newPath.c_str(), std::string new_path = ds.GetPath(".zip"); if (ds.path_ != new_path) { MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str()); if (rename(ds.path_.c_str(), new_path.c_str())) { MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(), strerror(errno)); } else { ds.path = newPath; ds.path_ = new_path; } } } } if (do_text_file) { ds.path = ds.GetPath(".txt"); MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path.c_str(), ds.tmp_path.c_str()); if (rename(ds.tmp_path.c_str(), ds.path.c_str())) { MYLOGE("rename(%s, %s): %s\n", ds.tmp_path.c_str(), ds.path.c_str(), ds.path_ = ds.GetPath(".txt"); MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str()); if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) { MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno)); ds.path.clear(); ds.path_.clear(); } } if (use_control_socket) { if (do_text_file) { dprintf(ds.controlSocketFd_, dprintf(ds.control_socket_fd_, "FAIL:could not create zip file, check %s " "for more details\n", ds.log_path.c_str()); ds.log_path_.c_str()); } else { dprintf(ds.controlSocketFd_, "OK:%s\n", ds.path.c_str()); dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str()); } } } Loading @@ -1576,27 +1585,27 @@ int main(int argc, char *argv[]) { /* tell activity manager we're done */ if (do_broadcast) { if (!ds.path.empty()) { MYLOGI("Final bugreport path: %s\n", ds.path.c_str()); if (!ds.path_.empty()) { MYLOGI("Final bugreport path: %s\n", ds.path_.c_str()); // clang-format off std::vector<std::string> am_args = { "--receiver-permission", "android.permission.DUMP", "--receiver-foreground", "--ei", "android.intent.extra.ID", std::to_string(ds.id_), "--ei", "android.intent.extra.PID", std::to_string(getpid()), "--ei", "android.intent.extra.MAX", std::to_string(ds.weightTotal_), "--es", "android.intent.extra.BUGREPORT", ds.path, "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path "--ei", "android.intent.extra.MAX", std::to_string(ds.weight_total_), "--es", "android.intent.extra.BUGREPORT", ds.path_, "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_ }; // clang-format on if (do_fb) { am_args.push_back("--es"); am_args.push_back("android.intent.extra.SCREENSHOT"); am_args.push_back(ds.screenshotPath_); am_args.push_back(ds.screenshot_path_); } if (is_remote_mode) { am_args.push_back("--es"); am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH"); am_args.push_back(SHA256_file_hash(ds.path)); am_args.push_back(SHA256_file_hash(ds.path_)); send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args); } else { send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args); Loading @@ -1606,16 +1615,16 @@ int main(int argc, char *argv[]) { } } MYLOGD("Final progress: %d/%d (originally %d)\n", ds.progress_, ds.weightTotal_, WEIGHT_TOTAL); MYLOGD("Final progress: %d/%d (originally %d)\n", ds.progress_, ds.weight_total_, WEIGHT_TOTAL); MYLOGI("done (id %lu)\n", ds.id_); if (is_redirecting) { fclose(stderr); } if (use_control_socket && ds.controlSocketFd_ != -1) { if (use_control_socket && ds.control_socket_fd_ != -1) { MYLOGD("Closing control socket\n"); close(ds.controlSocketFd_); close(ds.control_socket_fd_); } return 0; Loading