Loading cmds/dumpstate/DumpstateService.cpp +4 −2 Original line number Original line Diff line number Diff line Loading @@ -144,6 +144,9 @@ binder::Status DumpstateService::startBugreport(int32_t /* calling_uid */, } } status_t DumpstateService::dump(int fd, const Vector<String16>&) { status_t DumpstateService::dump(int fd, const Vector<String16>&) { std::string destination = ds_.options_->bugreport_fd.get() != -1 ? StringPrintf("[fd:%d]", ds_.options_->bugreport_fd.get()) : ds_.bugreport_internal_dir_.c_str(); dprintf(fd, "id: %d\n", ds_.id_); dprintf(fd, "id: %d\n", ds_.id_); dprintf(fd, "pid: %d\n", ds_.pid_); dprintf(fd, "pid: %d\n", ds_.pid_); dprintf(fd, "update_progress: %s\n", ds_.options_->do_progress_updates ? "true" : "false"); dprintf(fd, "update_progress: %s\n", ds_.options_->do_progress_updates ? "true" : "false"); Loading @@ -154,8 +157,7 @@ status_t DumpstateService::dump(int fd, const Vector<String16>&) { dprintf(fd, "args: %s\n", ds_.options_->args.c_str()); dprintf(fd, "args: %s\n", ds_.options_->args.c_str()); dprintf(fd, "extra_options: %s\n", ds_.options_->extra_options.c_str()); dprintf(fd, "extra_options: %s\n", ds_.options_->extra_options.c_str()); dprintf(fd, "version: %s\n", ds_.version_.c_str()); dprintf(fd, "version: %s\n", ds_.version_.c_str()); dprintf(fd, "bugreport_dir: %s\n", ds_.bugreport_dir_.c_str()); dprintf(fd, "bugreport_dir: %s\n", destination.c_str()); dprintf(fd, "bugreport_internal_dir_: %s\n", ds_.bugreport_internal_dir_.c_str()); dprintf(fd, "screenshot_path: %s\n", ds_.screenshot_path_.c_str()); dprintf(fd, "screenshot_path: %s\n", ds_.screenshot_path_.c_str()); dprintf(fd, "log_path: %s\n", ds_.log_path_.c_str()); dprintf(fd, "log_path: %s\n", ds_.log_path_.c_str()); dprintf(fd, "tmp_path: %s\n", ds_.tmp_path_.c_str()); dprintf(fd, "tmp_path: %s\n", ds_.tmp_path_.c_str()); Loading cmds/dumpstate/README.md +1 −1 Original line number Original line Diff line number Diff line Loading @@ -49,7 +49,7 @@ adb shell mkdir /data/nativetest64 Then run: Then run: ``` ``` mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest64/dumpstate_test* /data/nativetest64 && adb shell /data/nativetest64/dumpstate_test/dumpstate_test mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest64/dumpstate_* /data/nativetest64 && adb shell /data/nativetest64/dumpstate_test/dumpstate_test ``` ``` And to run just one test (for example, `DumpstateTest.RunCommandNoArgs`): And to run just one test (for example, `DumpstateTest.RunCommandNoArgs`): Loading cmds/dumpstate/dumpstate.cpp +25 −50 Original line number Original line Diff line number Diff line Loading @@ -135,10 +135,6 @@ static int Open(std::string path, int flags, mode_t mode = 0) { return fd; return fd; } } static int OpenForWrite(std::string path) { return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); } static int OpenForRead(std::string path) { static int OpenForRead(std::string path) { return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); Loading Loading @@ -169,17 +165,6 @@ static bool CopyFileToFd(const std::string& input_file, int out_fd) { return false; return false; } } static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) { if (input_file == output_file) { MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n", output_file.c_str()); return false; } MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str()); android::base::unique_fd out_fd(OpenForWrite(output_file)); return CopyFileToFd(input_file, out_fd.get()); } } // namespace } // namespace } // namespace os } // namespace os Loading Loading @@ -1675,6 +1660,7 @@ static void ShowUsage() { "progress (requires -o and -B)\n" "progress (requires -o and -B)\n" " -R: take bugreport in remote mode (requires -o, -z, -d and -B, " " -R: take bugreport in remote mode (requires -o, -z, -d and -B, " "shouldn't be used with -P)\n" "shouldn't be used with -P)\n" " -w: start binder service and make it wait for a call to startBugreport\n" " -v: prints the dumpstate header and exit\n"); " -v: prints the dumpstate header and exit\n"); } } Loading Loading @@ -1806,16 +1792,9 @@ static void MaybeResolveSymlink(std::string* path) { static void PrepareToWriteToFile() { static void PrepareToWriteToFile() { MaybeResolveSymlink(&ds.bugreport_internal_dir_); MaybeResolveSymlink(&ds.bugreport_internal_dir_); std::string base_name_part1 = "bugreport"; if (!ds.options_->use_outfile.empty()) { ds.bugreport_dir_ = dirname(ds.options_->use_outfile.c_str()); base_name_part1 = basename(ds.options_->use_outfile.c_str()); } std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD"); std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD"); std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE"); std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE"); ds.base_name_ = ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str()); StringPrintf("%s-%s-%s", base_name_part1.c_str(), device_name.c_str(), build_id.c_str()); if (ds.options_->do_add_date) { if (ds.options_->do_add_date) { char date[80]; char date[80]; strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_)); strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_)); Loading @@ -1838,17 +1817,16 @@ static void PrepareToWriteToFile() { std::string destination = ds.options_->bugreport_fd.get() != -1 std::string destination = ds.options_->bugreport_fd.get() != -1 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get()) ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get()) : ds.bugreport_dir_.c_str(); : ds.bugreport_internal_dir_.c_str(); MYLOGD( MYLOGD( "Bugreport dir: %s\n" "Bugreport dir: %s\n" "Internal Bugreport dir: %s\n" "Base name: %s\n" "Base name: %s\n" "Suffix: %s\n" "Suffix: %s\n" "Log path: %s\n" "Log path: %s\n" "Temporary path: %s\n" "Temporary path: %s\n" "Screenshot path: %s\n", "Screenshot path: %s\n", destination.c_str(), ds.bugreport_internal_dir_.c_str(), ds.base_name_.c_str(), destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str()); ds.tmp_path_.c_str(), ds.screenshot_path_.c_str()); if (ds.options_->do_zip_file) { if (ds.options_->do_zip_file) { ds.path_ = ds.GetPath(".zip"); ds.path_ = ds.GetPath(".zip"); Loading Loading @@ -1915,18 +1893,13 @@ static void FinalizeFile() { } } } } // The zip file lives in an internal directory. Copy it over to output. // The zip file lives in an internal directory. Copy it over to output. bool copy_succeeded = false; if (ds.options_->bugreport_fd.get() != -1) { if (ds.options_->bugreport_fd.get() != -1) { copy_succeeded = android::os::CopyFileToFd(ds.path_, ds.options_->bugreport_fd.get()); bool copy_succeeded = } else { android::os::CopyFileToFd(ds.path_, ds.options_->bugreport_fd.get()); ds.final_path_ = ds.GetPath(ds.bugreport_dir_, ".zip"); if (!copy_succeeded && remove(ds.path_.c_str())) { copy_succeeded = android::os::CopyFileToFile(ds.path_, ds.final_path_); } if (copy_succeeded) { if (remove(ds.path_.c_str())) { MYLOGE("remove(%s): %s", ds.path_.c_str(), strerror(errno)); MYLOGE("remove(%s): %s", ds.path_.c_str(), strerror(errno)); } } } } // else - the file just remains in the internal directory. } } } } if (do_text_file) { if (do_text_file) { Loading @@ -1952,8 +1925,8 @@ static void FinalizeFile() { /* Broadcasts that we are done with the bugreport */ /* Broadcasts that we are done with the bugreport */ static void SendBugreportFinishedBroadcast() { static void SendBugreportFinishedBroadcast() { // TODO(b/111441001): use callback instead of broadcast. // TODO(b/111441001): use callback instead of broadcast. if (!ds.final_path_.empty()) { if (!ds.path_.empty()) { MYLOGI("Final bugreport path: %s\n", ds.final_path_.c_str()); MYLOGI("Final bugreport path: %s\n", ds.path_.c_str()); // clang-format off // clang-format off std::vector<std::string> am_args = { std::vector<std::string> am_args = { Loading @@ -1961,7 +1934,7 @@ static void SendBugreportFinishedBroadcast() { "--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(ds.pid_), "--ei", "android.intent.extra.PID", std::to_string(ds.pid_), "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()), "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()), "--es", "android.intent.extra.BUGREPORT", ds.final_path_, "--es", "android.intent.extra.BUGREPORT", ds.path_, "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_ "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_ }; }; // clang-format on // clang-format on Loading @@ -1983,7 +1956,7 @@ static void SendBugreportFinishedBroadcast() { if (ds.options_->is_remote_mode) { if (ds.options_->is_remote_mode) { am_args.push_back("--es"); am_args.push_back("--es"); am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH"); am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH"); am_args.push_back(SHA256_file_hash(ds.final_path_)); am_args.push_back(SHA256_file_hash(ds.path_)); SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args); SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args); } else { } else { SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args); SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args); Loading Loading @@ -2121,7 +2094,6 @@ static void LogDumpOptions(const Dumpstate::DumpOptions& options) { MYLOGI("wifi_only: %d\n", options.wifi_only); MYLOGI("wifi_only: %d\n", options.wifi_only); MYLOGI("do_progress_updates: %d\n", options.do_progress_updates); MYLOGI("do_progress_updates: %d\n", options.do_progress_updates); MYLOGI("fd: %d\n", options.bugreport_fd.get()); MYLOGI("fd: %d\n", options.bugreport_fd.get()); MYLOGI("use_outfile: %s\n", options.use_outfile.c_str()); MYLOGI("extra_options: %s\n", options.extra_options.c_str()); MYLOGI("extra_options: %s\n", options.extra_options.c_str()); MYLOGI("args: %s\n", options.args.c_str()); MYLOGI("args: %s\n", options.args.c_str()); MYLOGI("notification_title: %s\n", options.notification_title.c_str()); MYLOGI("notification_title: %s\n", options.notification_title.c_str()); Loading @@ -2147,12 +2119,14 @@ void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode, Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) { Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) { RunStatus status = RunStatus::OK; RunStatus status = RunStatus::OK; int c; int c; while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) { while ((c = getopt(argc, argv, "dho:svqzpPBRSV:w")) != -1) { switch (c) { switch (c) { // clang-format off // clang-format off case 'd': do_add_date = true; break; case 'd': do_add_date = true; break; case 'z': do_zip_file = true; break; case 'z': do_zip_file = true; break; case 'o': use_outfile = optarg; break; // o=use_outfile not supported anymore. // TODO(b/111441001): Remove when all callers have migrated. case 'o': break; case 's': use_socket = true; break; case 's': use_socket = true; break; case 'S': use_control_socket = true; break; case 'S': use_control_socket = true; break; case 'v': show_header_only = true; break; case 'v': show_header_only = true; break; Loading @@ -2162,6 +2136,9 @@ Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) case 'R': is_remote_mode = true; break; case 'R': is_remote_mode = true; break; case 'B': do_broadcast = true; break; case 'B': do_broadcast = true; break; case 'V': break; // compatibility no-op case 'V': break; // compatibility no-op case 'w': // This was already processed break; case 'h': case 'h': status = RunStatus::HELP; status = RunStatus::HELP; break; break; Loading Loading @@ -2193,9 +2170,7 @@ bool Dumpstate::DumpOptions::ValidateOptions() const { return false; return false; } } bool has_out_file_options = !use_outfile.empty() || bugreport_fd.get() != -1; if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !OutputToFile()) { if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !has_out_file_options) { return false; return false; } } Loading Loading @@ -2257,8 +2232,8 @@ Dumpstate::RunStatus Dumpstate::Run() { * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also * gets added to the archive. * gets added to the archive. * * * Bugreports are first generated in a local directory and later copied to the caller's fd or * Bugreports are first generated in a local directory and later copied to the caller's fd if * directory. * supplied. */ */ Dumpstate::RunStatus Dumpstate::RunInternal() { Dumpstate::RunStatus Dumpstate::RunInternal() { LogDumpOptions(*options_); LogDumpOptions(*options_); Loading Loading @@ -2299,7 +2274,7 @@ Dumpstate::RunStatus Dumpstate::RunInternal() { } } // Redirect output if needed // Redirect output if needed bool is_redirecting = !options_->use_socket && !options_->use_outfile.empty(); bool is_redirecting = options_->OutputToFile(); // TODO: temporarily set progress until it's part of the Dumpstate constructor // TODO: temporarily set progress until it's part of the Dumpstate constructor std::string stats_path = std::string stats_path = Loading Loading @@ -2450,7 +2425,7 @@ Dumpstate::RunStatus Dumpstate::RunInternal() { } } /* rename or zip the (now complete) .tmp file to its final location */ /* rename or zip the (now complete) .tmp file to its final location */ if (!options_->use_outfile.empty()) { if (options_->OutputToFile()) { FinalizeFile(); FinalizeFile(); } } Loading cmds/dumpstate/dumpstate.h +9 −10 Original line number Original line Diff line number Diff line Loading @@ -331,6 +331,7 @@ class Dumpstate { bool do_add_date = false; bool do_add_date = false; bool do_zip_file = false; bool do_zip_file = false; bool do_vibrate = true; bool do_vibrate = true; // Writes bugreport content to a socket; only flatfile format is supported. bool use_socket = false; bool use_socket = false; bool use_control_socket = false; bool use_control_socket = false; bool do_fb = false; bool do_fb = false; Loading @@ -342,13 +343,11 @@ class Dumpstate { bool wifi_only = false; bool wifi_only = false; // Whether progress updates should be published. // Whether progress updates should be published. bool do_progress_updates = false; bool do_progress_updates = false; // File descriptor to output zip file. Takes precedence over use_outfile. // File descriptor to output zip file. android::base::unique_fd bugreport_fd; android::base::unique_fd bugreport_fd; // File descriptor to screenshot file. // File descriptor to screenshot file. // TODO(b/111441001): Use this fd. // TODO(b/111441001): Use this fd. android::base::unique_fd screenshot_fd; android::base::unique_fd screenshot_fd; // Partial path to output file. std::string use_outfile; // TODO: rename to MODE. // TODO: rename to MODE. // Extra options passed as system property. // Extra options passed as system property. std::string extra_options; std::string extra_options; Loading @@ -367,6 +366,13 @@ class Dumpstate { /* Returns true if the options set so far are consistent. */ /* Returns true if the options set so far are consistent. */ bool ValidateOptions() const; bool ValidateOptions() const; /* Returns if options specified require writing bugreport to a file */ bool OutputToFile() const { // If we are not writing to socket, we will write to a file. If bugreport_fd is // specified, it is preferred. If not bugreport is written to /bugreports. return !use_socket; } }; }; // TODO: initialize fields on constructor // TODO: initialize fields on constructor Loading Loading @@ -424,13 +430,6 @@ class Dumpstate { // Full path of the temporary file containing the screenshot (when requested). // Full path of the temporary file containing the screenshot (when requested). std::string screenshot_path_; std::string screenshot_path_; // TODO(b/111441001): remove when obsolete. // Full path of the final zip file inside the caller-specified directory, if available. std::string final_path_; // The caller-specified directory, if available. std::string bugreport_dir_; // Pointer to the zipped file. // Pointer to the zipped file. std::unique_ptr<FILE, int (*)(FILE*)> zip_file{nullptr, fclose}; std::unique_ptr<FILE, int (*)(FILE*)> zip_file{nullptr, fclose}; Loading cmds/dumpstate/dumpstate.rc +6 −0 Original line number Original line Diff line number Diff line Loading @@ -17,3 +17,9 @@ service dumpstatez /system/bin/dumpstate -S -d -z \ class main class main disabled disabled oneshot oneshot # bugreportd starts dumpstate binder service and makes it wait for a listener to connect. service bugreportd /system/bin/dumpstate -w class main disabled oneshot Loading
cmds/dumpstate/DumpstateService.cpp +4 −2 Original line number Original line Diff line number Diff line Loading @@ -144,6 +144,9 @@ binder::Status DumpstateService::startBugreport(int32_t /* calling_uid */, } } status_t DumpstateService::dump(int fd, const Vector<String16>&) { status_t DumpstateService::dump(int fd, const Vector<String16>&) { std::string destination = ds_.options_->bugreport_fd.get() != -1 ? StringPrintf("[fd:%d]", ds_.options_->bugreport_fd.get()) : ds_.bugreport_internal_dir_.c_str(); dprintf(fd, "id: %d\n", ds_.id_); dprintf(fd, "id: %d\n", ds_.id_); dprintf(fd, "pid: %d\n", ds_.pid_); dprintf(fd, "pid: %d\n", ds_.pid_); dprintf(fd, "update_progress: %s\n", ds_.options_->do_progress_updates ? "true" : "false"); dprintf(fd, "update_progress: %s\n", ds_.options_->do_progress_updates ? "true" : "false"); Loading @@ -154,8 +157,7 @@ status_t DumpstateService::dump(int fd, const Vector<String16>&) { dprintf(fd, "args: %s\n", ds_.options_->args.c_str()); dprintf(fd, "args: %s\n", ds_.options_->args.c_str()); dprintf(fd, "extra_options: %s\n", ds_.options_->extra_options.c_str()); dprintf(fd, "extra_options: %s\n", ds_.options_->extra_options.c_str()); dprintf(fd, "version: %s\n", ds_.version_.c_str()); dprintf(fd, "version: %s\n", ds_.version_.c_str()); dprintf(fd, "bugreport_dir: %s\n", ds_.bugreport_dir_.c_str()); dprintf(fd, "bugreport_dir: %s\n", destination.c_str()); dprintf(fd, "bugreport_internal_dir_: %s\n", ds_.bugreport_internal_dir_.c_str()); dprintf(fd, "screenshot_path: %s\n", ds_.screenshot_path_.c_str()); dprintf(fd, "screenshot_path: %s\n", ds_.screenshot_path_.c_str()); dprintf(fd, "log_path: %s\n", ds_.log_path_.c_str()); dprintf(fd, "log_path: %s\n", ds_.log_path_.c_str()); dprintf(fd, "tmp_path: %s\n", ds_.tmp_path_.c_str()); dprintf(fd, "tmp_path: %s\n", ds_.tmp_path_.c_str()); Loading
cmds/dumpstate/README.md +1 −1 Original line number Original line Diff line number Diff line Loading @@ -49,7 +49,7 @@ adb shell mkdir /data/nativetest64 Then run: Then run: ``` ``` mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest64/dumpstate_test* /data/nativetest64 && adb shell /data/nativetest64/dumpstate_test/dumpstate_test mmm -j frameworks/native/cmds/dumpstate/ && adb push ${OUT}/data/nativetest64/dumpstate_* /data/nativetest64 && adb shell /data/nativetest64/dumpstate_test/dumpstate_test ``` ``` And to run just one test (for example, `DumpstateTest.RunCommandNoArgs`): And to run just one test (for example, `DumpstateTest.RunCommandNoArgs`): Loading
cmds/dumpstate/dumpstate.cpp +25 −50 Original line number Original line Diff line number Diff line Loading @@ -135,10 +135,6 @@ static int Open(std::string path, int flags, mode_t mode = 0) { return fd; return fd; } } static int OpenForWrite(std::string path) { return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); } static int OpenForRead(std::string path) { static int OpenForRead(std::string path) { return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); Loading Loading @@ -169,17 +165,6 @@ static bool CopyFileToFd(const std::string& input_file, int out_fd) { return false; return false; } } static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) { if (input_file == output_file) { MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n", output_file.c_str()); return false; } MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str()); android::base::unique_fd out_fd(OpenForWrite(output_file)); return CopyFileToFd(input_file, out_fd.get()); } } // namespace } // namespace } // namespace os } // namespace os Loading Loading @@ -1675,6 +1660,7 @@ static void ShowUsage() { "progress (requires -o and -B)\n" "progress (requires -o and -B)\n" " -R: take bugreport in remote mode (requires -o, -z, -d and -B, " " -R: take bugreport in remote mode (requires -o, -z, -d and -B, " "shouldn't be used with -P)\n" "shouldn't be used with -P)\n" " -w: start binder service and make it wait for a call to startBugreport\n" " -v: prints the dumpstate header and exit\n"); " -v: prints the dumpstate header and exit\n"); } } Loading Loading @@ -1806,16 +1792,9 @@ static void MaybeResolveSymlink(std::string* path) { static void PrepareToWriteToFile() { static void PrepareToWriteToFile() { MaybeResolveSymlink(&ds.bugreport_internal_dir_); MaybeResolveSymlink(&ds.bugreport_internal_dir_); std::string base_name_part1 = "bugreport"; if (!ds.options_->use_outfile.empty()) { ds.bugreport_dir_ = dirname(ds.options_->use_outfile.c_str()); base_name_part1 = basename(ds.options_->use_outfile.c_str()); } std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD"); std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD"); std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE"); std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE"); ds.base_name_ = ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str()); StringPrintf("%s-%s-%s", base_name_part1.c_str(), device_name.c_str(), build_id.c_str()); if (ds.options_->do_add_date) { if (ds.options_->do_add_date) { char date[80]; char date[80]; strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_)); strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_)); Loading @@ -1838,17 +1817,16 @@ static void PrepareToWriteToFile() { std::string destination = ds.options_->bugreport_fd.get() != -1 std::string destination = ds.options_->bugreport_fd.get() != -1 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get()) ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get()) : ds.bugreport_dir_.c_str(); : ds.bugreport_internal_dir_.c_str(); MYLOGD( MYLOGD( "Bugreport dir: %s\n" "Bugreport dir: %s\n" "Internal Bugreport dir: %s\n" "Base name: %s\n" "Base name: %s\n" "Suffix: %s\n" "Suffix: %s\n" "Log path: %s\n" "Log path: %s\n" "Temporary path: %s\n" "Temporary path: %s\n" "Screenshot path: %s\n", "Screenshot path: %s\n", destination.c_str(), ds.bugreport_internal_dir_.c_str(), ds.base_name_.c_str(), destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str()); ds.tmp_path_.c_str(), ds.screenshot_path_.c_str()); if (ds.options_->do_zip_file) { if (ds.options_->do_zip_file) { ds.path_ = ds.GetPath(".zip"); ds.path_ = ds.GetPath(".zip"); Loading Loading @@ -1915,18 +1893,13 @@ static void FinalizeFile() { } } } } // The zip file lives in an internal directory. Copy it over to output. // The zip file lives in an internal directory. Copy it over to output. bool copy_succeeded = false; if (ds.options_->bugreport_fd.get() != -1) { if (ds.options_->bugreport_fd.get() != -1) { copy_succeeded = android::os::CopyFileToFd(ds.path_, ds.options_->bugreport_fd.get()); bool copy_succeeded = } else { android::os::CopyFileToFd(ds.path_, ds.options_->bugreport_fd.get()); ds.final_path_ = ds.GetPath(ds.bugreport_dir_, ".zip"); if (!copy_succeeded && remove(ds.path_.c_str())) { copy_succeeded = android::os::CopyFileToFile(ds.path_, ds.final_path_); } if (copy_succeeded) { if (remove(ds.path_.c_str())) { MYLOGE("remove(%s): %s", ds.path_.c_str(), strerror(errno)); MYLOGE("remove(%s): %s", ds.path_.c_str(), strerror(errno)); } } } } // else - the file just remains in the internal directory. } } } } if (do_text_file) { if (do_text_file) { Loading @@ -1952,8 +1925,8 @@ static void FinalizeFile() { /* Broadcasts that we are done with the bugreport */ /* Broadcasts that we are done with the bugreport */ static void SendBugreportFinishedBroadcast() { static void SendBugreportFinishedBroadcast() { // TODO(b/111441001): use callback instead of broadcast. // TODO(b/111441001): use callback instead of broadcast. if (!ds.final_path_.empty()) { if (!ds.path_.empty()) { MYLOGI("Final bugreport path: %s\n", ds.final_path_.c_str()); MYLOGI("Final bugreport path: %s\n", ds.path_.c_str()); // clang-format off // clang-format off std::vector<std::string> am_args = { std::vector<std::string> am_args = { Loading @@ -1961,7 +1934,7 @@ static void SendBugreportFinishedBroadcast() { "--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(ds.pid_), "--ei", "android.intent.extra.PID", std::to_string(ds.pid_), "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()), "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()), "--es", "android.intent.extra.BUGREPORT", ds.final_path_, "--es", "android.intent.extra.BUGREPORT", ds.path_, "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_ "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_ }; }; // clang-format on // clang-format on Loading @@ -1983,7 +1956,7 @@ static void SendBugreportFinishedBroadcast() { if (ds.options_->is_remote_mode) { if (ds.options_->is_remote_mode) { am_args.push_back("--es"); am_args.push_back("--es"); am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH"); am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH"); am_args.push_back(SHA256_file_hash(ds.final_path_)); am_args.push_back(SHA256_file_hash(ds.path_)); SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args); SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args); } else { } else { SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args); SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args); Loading Loading @@ -2121,7 +2094,6 @@ static void LogDumpOptions(const Dumpstate::DumpOptions& options) { MYLOGI("wifi_only: %d\n", options.wifi_only); MYLOGI("wifi_only: %d\n", options.wifi_only); MYLOGI("do_progress_updates: %d\n", options.do_progress_updates); MYLOGI("do_progress_updates: %d\n", options.do_progress_updates); MYLOGI("fd: %d\n", options.bugreport_fd.get()); MYLOGI("fd: %d\n", options.bugreport_fd.get()); MYLOGI("use_outfile: %s\n", options.use_outfile.c_str()); MYLOGI("extra_options: %s\n", options.extra_options.c_str()); MYLOGI("extra_options: %s\n", options.extra_options.c_str()); MYLOGI("args: %s\n", options.args.c_str()); MYLOGI("args: %s\n", options.args.c_str()); MYLOGI("notification_title: %s\n", options.notification_title.c_str()); MYLOGI("notification_title: %s\n", options.notification_title.c_str()); Loading @@ -2147,12 +2119,14 @@ void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode, Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) { Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) { RunStatus status = RunStatus::OK; RunStatus status = RunStatus::OK; int c; int c; while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) { while ((c = getopt(argc, argv, "dho:svqzpPBRSV:w")) != -1) { switch (c) { switch (c) { // clang-format off // clang-format off case 'd': do_add_date = true; break; case 'd': do_add_date = true; break; case 'z': do_zip_file = true; break; case 'z': do_zip_file = true; break; case 'o': use_outfile = optarg; break; // o=use_outfile not supported anymore. // TODO(b/111441001): Remove when all callers have migrated. case 'o': break; case 's': use_socket = true; break; case 's': use_socket = true; break; case 'S': use_control_socket = true; break; case 'S': use_control_socket = true; break; case 'v': show_header_only = true; break; case 'v': show_header_only = true; break; Loading @@ -2162,6 +2136,9 @@ Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) case 'R': is_remote_mode = true; break; case 'R': is_remote_mode = true; break; case 'B': do_broadcast = true; break; case 'B': do_broadcast = true; break; case 'V': break; // compatibility no-op case 'V': break; // compatibility no-op case 'w': // This was already processed break; case 'h': case 'h': status = RunStatus::HELP; status = RunStatus::HELP; break; break; Loading Loading @@ -2193,9 +2170,7 @@ bool Dumpstate::DumpOptions::ValidateOptions() const { return false; return false; } } bool has_out_file_options = !use_outfile.empty() || bugreport_fd.get() != -1; if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !OutputToFile()) { if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !has_out_file_options) { return false; return false; } } Loading Loading @@ -2257,8 +2232,8 @@ Dumpstate::RunStatus Dumpstate::Run() { * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also * gets added to the archive. * gets added to the archive. * * * Bugreports are first generated in a local directory and later copied to the caller's fd or * Bugreports are first generated in a local directory and later copied to the caller's fd if * directory. * supplied. */ */ Dumpstate::RunStatus Dumpstate::RunInternal() { Dumpstate::RunStatus Dumpstate::RunInternal() { LogDumpOptions(*options_); LogDumpOptions(*options_); Loading Loading @@ -2299,7 +2274,7 @@ Dumpstate::RunStatus Dumpstate::RunInternal() { } } // Redirect output if needed // Redirect output if needed bool is_redirecting = !options_->use_socket && !options_->use_outfile.empty(); bool is_redirecting = options_->OutputToFile(); // TODO: temporarily set progress until it's part of the Dumpstate constructor // TODO: temporarily set progress until it's part of the Dumpstate constructor std::string stats_path = std::string stats_path = Loading Loading @@ -2450,7 +2425,7 @@ Dumpstate::RunStatus Dumpstate::RunInternal() { } } /* rename or zip the (now complete) .tmp file to its final location */ /* rename or zip the (now complete) .tmp file to its final location */ if (!options_->use_outfile.empty()) { if (options_->OutputToFile()) { FinalizeFile(); FinalizeFile(); } } Loading
cmds/dumpstate/dumpstate.h +9 −10 Original line number Original line Diff line number Diff line Loading @@ -331,6 +331,7 @@ class Dumpstate { bool do_add_date = false; bool do_add_date = false; bool do_zip_file = false; bool do_zip_file = false; bool do_vibrate = true; bool do_vibrate = true; // Writes bugreport content to a socket; only flatfile format is supported. bool use_socket = false; bool use_socket = false; bool use_control_socket = false; bool use_control_socket = false; bool do_fb = false; bool do_fb = false; Loading @@ -342,13 +343,11 @@ class Dumpstate { bool wifi_only = false; bool wifi_only = false; // Whether progress updates should be published. // Whether progress updates should be published. bool do_progress_updates = false; bool do_progress_updates = false; // File descriptor to output zip file. Takes precedence over use_outfile. // File descriptor to output zip file. android::base::unique_fd bugreport_fd; android::base::unique_fd bugreport_fd; // File descriptor to screenshot file. // File descriptor to screenshot file. // TODO(b/111441001): Use this fd. // TODO(b/111441001): Use this fd. android::base::unique_fd screenshot_fd; android::base::unique_fd screenshot_fd; // Partial path to output file. std::string use_outfile; // TODO: rename to MODE. // TODO: rename to MODE. // Extra options passed as system property. // Extra options passed as system property. std::string extra_options; std::string extra_options; Loading @@ -367,6 +366,13 @@ class Dumpstate { /* Returns true if the options set so far are consistent. */ /* Returns true if the options set so far are consistent. */ bool ValidateOptions() const; bool ValidateOptions() const; /* Returns if options specified require writing bugreport to a file */ bool OutputToFile() const { // If we are not writing to socket, we will write to a file. If bugreport_fd is // specified, it is preferred. If not bugreport is written to /bugreports. return !use_socket; } }; }; // TODO: initialize fields on constructor // TODO: initialize fields on constructor Loading Loading @@ -424,13 +430,6 @@ class Dumpstate { // Full path of the temporary file containing the screenshot (when requested). // Full path of the temporary file containing the screenshot (when requested). std::string screenshot_path_; std::string screenshot_path_; // TODO(b/111441001): remove when obsolete. // Full path of the final zip file inside the caller-specified directory, if available. std::string final_path_; // The caller-specified directory, if available. std::string bugreport_dir_; // Pointer to the zipped file. // Pointer to the zipped file. std::unique_ptr<FILE, int (*)(FILE*)> zip_file{nullptr, fclose}; std::unique_ptr<FILE, int (*)(FILE*)> zip_file{nullptr, fclose}; Loading
cmds/dumpstate/dumpstate.rc +6 −0 Original line number Original line Diff line number Diff line Loading @@ -17,3 +17,9 @@ service dumpstatez /system/bin/dumpstate -S -d -z \ class main class main disabled disabled oneshot oneshot # bugreportd starts dumpstate binder service and makes it wait for a listener to connect. service bugreportd /system/bin/dumpstate -w class main disabled oneshot