1*38e8c45fSAndroid Build Coastguard Worker /**
2*38e8c45fSAndroid Build Coastguard Worker * Copyright (c) 2016, The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "dumpstate"
18*38e8c45fSAndroid Build Coastguard Worker
19*38e8c45fSAndroid Build Coastguard Worker #include "DumpstateService.h"
20*38e8c45fSAndroid Build Coastguard Worker
21*38e8c45fSAndroid Build Coastguard Worker #include <memory>
22*38e8c45fSAndroid Build Coastguard Worker
23*38e8c45fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
24*38e8c45fSAndroid Build Coastguard Worker #include "android/os/BnDumpstate.h"
25*38e8c45fSAndroid Build Coastguard Worker
26*38e8c45fSAndroid Build Coastguard Worker #include "DumpstateInternal.h"
27*38e8c45fSAndroid Build Coastguard Worker
28*38e8c45fSAndroid Build Coastguard Worker using android::base::StringPrintf;
29*38e8c45fSAndroid Build Coastguard Worker
30*38e8c45fSAndroid Build Coastguard Worker namespace android {
31*38e8c45fSAndroid Build Coastguard Worker namespace os {
32*38e8c45fSAndroid Build Coastguard Worker
33*38e8c45fSAndroid Build Coastguard Worker namespace {
34*38e8c45fSAndroid Build Coastguard Worker
35*38e8c45fSAndroid Build Coastguard Worker struct DumpstateInfo {
36*38e8c45fSAndroid Build Coastguard Worker public:
37*38e8c45fSAndroid Build Coastguard Worker Dumpstate* ds = nullptr;
38*38e8c45fSAndroid Build Coastguard Worker int32_t calling_uid = -1;
39*38e8c45fSAndroid Build Coastguard Worker std::string calling_package;
40*38e8c45fSAndroid Build Coastguard Worker int32_t user_id = -1;
41*38e8c45fSAndroid Build Coastguard Worker bool keep_bugreport_on_retrieval = false;
42*38e8c45fSAndroid Build Coastguard Worker bool skip_user_consent = false;
43*38e8c45fSAndroid Build Coastguard Worker };
44*38e8c45fSAndroid Build Coastguard Worker
exception(uint32_t code,const std::string & msg,const std::string & extra_msg="")45*38e8c45fSAndroid Build Coastguard Worker static binder::Status exception(uint32_t code, const std::string& msg,
46*38e8c45fSAndroid Build Coastguard Worker const std::string& extra_msg = "") {
47*38e8c45fSAndroid Build Coastguard Worker if (extra_msg.empty()) {
48*38e8c45fSAndroid Build Coastguard Worker MYLOGE("%s (%d) ", msg.c_str(), code);
49*38e8c45fSAndroid Build Coastguard Worker } else {
50*38e8c45fSAndroid Build Coastguard Worker MYLOGE("%s %s (%d) ", msg.c_str(), extra_msg.c_str(), code);
51*38e8c45fSAndroid Build Coastguard Worker }
52*38e8c45fSAndroid Build Coastguard Worker return binder::Status::fromExceptionCode(code, String8(msg.c_str()));
53*38e8c45fSAndroid Build Coastguard Worker }
54*38e8c45fSAndroid Build Coastguard Worker
55*38e8c45fSAndroid Build Coastguard Worker // Creates a bugreport and exits, thus preserving the oneshot nature of the service.
56*38e8c45fSAndroid Build Coastguard Worker // Note: takes ownership of data.
dumpstate_thread_bugreport(void * data)57*38e8c45fSAndroid Build Coastguard Worker [[noreturn]] static void* dumpstate_thread_bugreport(void* data) {
58*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<DumpstateInfo> ds_info(static_cast<DumpstateInfo*>(data));
59*38e8c45fSAndroid Build Coastguard Worker ds_info->ds->Run(ds_info->calling_uid, ds_info->calling_package);
60*38e8c45fSAndroid Build Coastguard Worker MYLOGD("Finished taking a bugreport. Exiting.\n");
61*38e8c45fSAndroid Build Coastguard Worker exit(0);
62*38e8c45fSAndroid Build Coastguard Worker }
63*38e8c45fSAndroid Build Coastguard Worker
dumpstate_thread_retrieve(void * data)64*38e8c45fSAndroid Build Coastguard Worker [[noreturn]] static void* dumpstate_thread_retrieve(void* data) {
65*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<DumpstateInfo> ds_info(static_cast<DumpstateInfo*>(data));
66*38e8c45fSAndroid Build Coastguard Worker ds_info->ds->Retrieve(ds_info->calling_uid, ds_info->calling_package,
67*38e8c45fSAndroid Build Coastguard Worker ds_info->keep_bugreport_on_retrieval, ds_info->skip_user_consent);
68*38e8c45fSAndroid Build Coastguard Worker MYLOGD("Finished retrieving a bugreport. Exiting.\n");
69*38e8c45fSAndroid Build Coastguard Worker exit(0);
70*38e8c45fSAndroid Build Coastguard Worker }
71*38e8c45fSAndroid Build Coastguard Worker
signalErrorAndExit(sp<IDumpstateListener> listener,int error_code)72*38e8c45fSAndroid Build Coastguard Worker [[noreturn]] static void signalErrorAndExit(sp<IDumpstateListener> listener, int error_code) {
73*38e8c45fSAndroid Build Coastguard Worker listener->onError(error_code);
74*38e8c45fSAndroid Build Coastguard Worker exit(0);
75*38e8c45fSAndroid Build Coastguard Worker }
76*38e8c45fSAndroid Build Coastguard Worker
77*38e8c45fSAndroid Build Coastguard Worker } // namespace
78*38e8c45fSAndroid Build Coastguard Worker
DumpstateService()79*38e8c45fSAndroid Build Coastguard Worker DumpstateService::DumpstateService() : ds_(nullptr), calling_uid_(-1), calling_package_() {
80*38e8c45fSAndroid Build Coastguard Worker }
81*38e8c45fSAndroid Build Coastguard Worker
getServiceName()82*38e8c45fSAndroid Build Coastguard Worker char const* DumpstateService::getServiceName() {
83*38e8c45fSAndroid Build Coastguard Worker return "dumpstate";
84*38e8c45fSAndroid Build Coastguard Worker }
85*38e8c45fSAndroid Build Coastguard Worker
Start()86*38e8c45fSAndroid Build Coastguard Worker status_t DumpstateService::Start() {
87*38e8c45fSAndroid Build Coastguard Worker IPCThreadState::self()->disableBackgroundScheduling(true);
88*38e8c45fSAndroid Build Coastguard Worker status_t ret = BinderService<DumpstateService>::publish();
89*38e8c45fSAndroid Build Coastguard Worker if (ret != android::OK) {
90*38e8c45fSAndroid Build Coastguard Worker return ret;
91*38e8c45fSAndroid Build Coastguard Worker }
92*38e8c45fSAndroid Build Coastguard Worker sp<ProcessState> ps(ProcessState::self());
93*38e8c45fSAndroid Build Coastguard Worker ps->startThreadPool();
94*38e8c45fSAndroid Build Coastguard Worker ps->giveThreadPoolName();
95*38e8c45fSAndroid Build Coastguard Worker return android::OK;
96*38e8c45fSAndroid Build Coastguard Worker }
97*38e8c45fSAndroid Build Coastguard Worker
preDumpUiData(const std::string &)98*38e8c45fSAndroid Build Coastguard Worker binder::Status DumpstateService::preDumpUiData(const std::string&) {
99*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(lock_);
100*38e8c45fSAndroid Build Coastguard Worker MYLOGI("preDumpUiData()");
101*38e8c45fSAndroid Build Coastguard Worker
102*38e8c45fSAndroid Build Coastguard Worker if (ds_ != nullptr) {
103*38e8c45fSAndroid Build Coastguard Worker MYLOGE("Error! DumpstateService is currently already being used. Returning.");
104*38e8c45fSAndroid Build Coastguard Worker return exception(binder::Status::EX_SERVICE_SPECIFIC,
105*38e8c45fSAndroid Build Coastguard Worker "DumpstateService is already being used");
106*38e8c45fSAndroid Build Coastguard Worker }
107*38e8c45fSAndroid Build Coastguard Worker
108*38e8c45fSAndroid Build Coastguard Worker ds_ = &(Dumpstate::GetInstance());
109*38e8c45fSAndroid Build Coastguard Worker ds_->PreDumpUiData();
110*38e8c45fSAndroid Build Coastguard Worker
111*38e8c45fSAndroid Build Coastguard Worker return binder::Status::ok();
112*38e8c45fSAndroid Build Coastguard Worker }
113*38e8c45fSAndroid Build Coastguard Worker
startBugreport(int32_t calling_uid,const std::string & calling_package,android::base::unique_fd bugreport_fd,android::base::unique_fd screenshot_fd,int bugreport_mode,int bugreport_flags,const sp<IDumpstateListener> & listener,bool is_screenshot_requested,bool skip_user_consent)114*38e8c45fSAndroid Build Coastguard Worker binder::Status DumpstateService::startBugreport(int32_t calling_uid,
115*38e8c45fSAndroid Build Coastguard Worker const std::string& calling_package,
116*38e8c45fSAndroid Build Coastguard Worker android::base::unique_fd bugreport_fd,
117*38e8c45fSAndroid Build Coastguard Worker android::base::unique_fd screenshot_fd,
118*38e8c45fSAndroid Build Coastguard Worker int bugreport_mode,
119*38e8c45fSAndroid Build Coastguard Worker int bugreport_flags,
120*38e8c45fSAndroid Build Coastguard Worker const sp<IDumpstateListener>& listener,
121*38e8c45fSAndroid Build Coastguard Worker bool is_screenshot_requested,
122*38e8c45fSAndroid Build Coastguard Worker bool skip_user_consent) {
123*38e8c45fSAndroid Build Coastguard Worker MYLOGI("startBugreport() with mode: %d\n", bugreport_mode);
124*38e8c45fSAndroid Build Coastguard Worker
125*38e8c45fSAndroid Build Coastguard Worker // Ensure there is only one bugreport in progress at a time.
126*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(lock_);
127*38e8c45fSAndroid Build Coastguard Worker if (ds_ != nullptr) {
128*38e8c45fSAndroid Build Coastguard Worker MYLOGE("Error! DumpstateService is currently already being used. Returning.");
129*38e8c45fSAndroid Build Coastguard Worker if (listener != nullptr) {
130*38e8c45fSAndroid Build Coastguard Worker listener->onError(IDumpstateListener::BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS);
131*38e8c45fSAndroid Build Coastguard Worker }
132*38e8c45fSAndroid Build Coastguard Worker return exception(binder::Status::EX_SERVICE_SPECIFIC,
133*38e8c45fSAndroid Build Coastguard Worker "DumpstateService is already being used");
134*38e8c45fSAndroid Build Coastguard Worker }
135*38e8c45fSAndroid Build Coastguard Worker
136*38e8c45fSAndroid Build Coastguard Worker // From here on, all conditions that indicate we are done with this incoming request should
137*38e8c45fSAndroid Build Coastguard Worker // result in exiting the service to free it up for next invocation.
138*38e8c45fSAndroid Build Coastguard Worker if (listener == nullptr) {
139*38e8c45fSAndroid Build Coastguard Worker MYLOGE("Invalid input: no listener");
140*38e8c45fSAndroid Build Coastguard Worker exit(0);
141*38e8c45fSAndroid Build Coastguard Worker }
142*38e8c45fSAndroid Build Coastguard Worker
143*38e8c45fSAndroid Build Coastguard Worker if (bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_FULL &&
144*38e8c45fSAndroid Build Coastguard Worker bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE &&
145*38e8c45fSAndroid Build Coastguard Worker bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_REMOTE &&
146*38e8c45fSAndroid Build Coastguard Worker bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_WEAR &&
147*38e8c45fSAndroid Build Coastguard Worker bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_TELEPHONY &&
148*38e8c45fSAndroid Build Coastguard Worker bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_WIFI &&
149*38e8c45fSAndroid Build Coastguard Worker bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_ONBOARDING &&
150*38e8c45fSAndroid Build Coastguard Worker bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_DEFAULT) {
151*38e8c45fSAndroid Build Coastguard Worker MYLOGE("Invalid input: bad bugreport mode: %d", bugreport_mode);
152*38e8c45fSAndroid Build Coastguard Worker signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
153*38e8c45fSAndroid Build Coastguard Worker }
154*38e8c45fSAndroid Build Coastguard Worker
155*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
156*38e8c45fSAndroid Build Coastguard Worker options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_flags,
157*38e8c45fSAndroid Build Coastguard Worker bugreport_fd, screenshot_fd, is_screenshot_requested, skip_user_consent);
158*38e8c45fSAndroid Build Coastguard Worker
159*38e8c45fSAndroid Build Coastguard Worker if (bugreport_fd.get() == -1 || (options->do_screenshot && screenshot_fd.get() == -1)) {
160*38e8c45fSAndroid Build Coastguard Worker MYLOGE("Invalid filedescriptor");
161*38e8c45fSAndroid Build Coastguard Worker signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
162*38e8c45fSAndroid Build Coastguard Worker }
163*38e8c45fSAndroid Build Coastguard Worker
164*38e8c45fSAndroid Build Coastguard Worker
165*38e8c45fSAndroid Build Coastguard Worker ds_ = &(Dumpstate::GetInstance());
166*38e8c45fSAndroid Build Coastguard Worker ds_->SetOptions(std::move(options));
167*38e8c45fSAndroid Build Coastguard Worker ds_->listener_ = listener;
168*38e8c45fSAndroid Build Coastguard Worker
169*38e8c45fSAndroid Build Coastguard Worker // Track caller info for cancellation purposes.
170*38e8c45fSAndroid Build Coastguard Worker calling_uid_ = calling_uid;
171*38e8c45fSAndroid Build Coastguard Worker calling_package_ = calling_package;
172*38e8c45fSAndroid Build Coastguard Worker
173*38e8c45fSAndroid Build Coastguard Worker DumpstateInfo* ds_info = new DumpstateInfo();
174*38e8c45fSAndroid Build Coastguard Worker ds_info->ds = ds_;
175*38e8c45fSAndroid Build Coastguard Worker ds_info->calling_uid = calling_uid;
176*38e8c45fSAndroid Build Coastguard Worker ds_info->calling_package = calling_package;
177*38e8c45fSAndroid Build Coastguard Worker
178*38e8c45fSAndroid Build Coastguard Worker pthread_t thread;
179*38e8c45fSAndroid Build Coastguard Worker // Initialize dumpstate
180*38e8c45fSAndroid Build Coastguard Worker ds_->Initialize();
181*38e8c45fSAndroid Build Coastguard Worker status_t err = pthread_create(&thread, nullptr, dumpstate_thread_bugreport, ds_info);
182*38e8c45fSAndroid Build Coastguard Worker if (err != 0) {
183*38e8c45fSAndroid Build Coastguard Worker delete ds_info;
184*38e8c45fSAndroid Build Coastguard Worker MYLOGE("Could not create a thread");
185*38e8c45fSAndroid Build Coastguard Worker signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
186*38e8c45fSAndroid Build Coastguard Worker }
187*38e8c45fSAndroid Build Coastguard Worker return binder::Status::ok();
188*38e8c45fSAndroid Build Coastguard Worker }
189*38e8c45fSAndroid Build Coastguard Worker
cancelBugreport(int32_t calling_uid,const std::string & calling_package)190*38e8c45fSAndroid Build Coastguard Worker binder::Status DumpstateService::cancelBugreport(int32_t calling_uid,
191*38e8c45fSAndroid Build Coastguard Worker const std::string& calling_package) {
192*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(lock_);
193*38e8c45fSAndroid Build Coastguard Worker if (calling_uid != calling_uid_ || calling_package != calling_package_) {
194*38e8c45fSAndroid Build Coastguard Worker // Note: we use a SecurityException to prevent BugreportManagerServiceImpl from killing the
195*38e8c45fSAndroid Build Coastguard Worker // report in progress (from another caller).
196*38e8c45fSAndroid Build Coastguard Worker return exception(
197*38e8c45fSAndroid Build Coastguard Worker binder::Status::EX_SECURITY,
198*38e8c45fSAndroid Build Coastguard Worker StringPrintf("Cancellation requested by %d/%s does not match report in "
199*38e8c45fSAndroid Build Coastguard Worker "progress",
200*38e8c45fSAndroid Build Coastguard Worker calling_uid, calling_package.c_str()),
201*38e8c45fSAndroid Build Coastguard Worker // Sharing the owner of the BR is a (minor) leak, so leave it out of the app's exception
202*38e8c45fSAndroid Build Coastguard Worker StringPrintf("started by %d/%s", calling_uid_, calling_package_.c_str()));
203*38e8c45fSAndroid Build Coastguard Worker }
204*38e8c45fSAndroid Build Coastguard Worker ds_->Cancel();
205*38e8c45fSAndroid Build Coastguard Worker return binder::Status::ok();
206*38e8c45fSAndroid Build Coastguard Worker }
207*38e8c45fSAndroid Build Coastguard Worker
retrieveBugreport(int32_t calling_uid,const std::string & calling_package,int32_t user_id,android::base::unique_fd bugreport_fd,const std::string & bugreport_file,const bool keep_bugreport_on_retrieval,const bool skip_user_consent,const sp<IDumpstateListener> & listener)208*38e8c45fSAndroid Build Coastguard Worker binder::Status DumpstateService::retrieveBugreport(
209*38e8c45fSAndroid Build Coastguard Worker int32_t calling_uid, const std::string& calling_package, int32_t user_id,
210*38e8c45fSAndroid Build Coastguard Worker android::base::unique_fd bugreport_fd,
211*38e8c45fSAndroid Build Coastguard Worker const std::string& bugreport_file,
212*38e8c45fSAndroid Build Coastguard Worker const bool keep_bugreport_on_retrieval,
213*38e8c45fSAndroid Build Coastguard Worker const bool skip_user_consent,
214*38e8c45fSAndroid Build Coastguard Worker const sp<IDumpstateListener>& listener) {
215*38e8c45fSAndroid Build Coastguard Worker
216*38e8c45fSAndroid Build Coastguard Worker ds_ = &(Dumpstate::GetInstance());
217*38e8c45fSAndroid Build Coastguard Worker DumpstateInfo* ds_info = new DumpstateInfo();
218*38e8c45fSAndroid Build Coastguard Worker ds_info->ds = ds_;
219*38e8c45fSAndroid Build Coastguard Worker ds_info->calling_uid = calling_uid;
220*38e8c45fSAndroid Build Coastguard Worker ds_info->calling_package = calling_package;
221*38e8c45fSAndroid Build Coastguard Worker ds_info->user_id = user_id;
222*38e8c45fSAndroid Build Coastguard Worker ds_info->keep_bugreport_on_retrieval = keep_bugreport_on_retrieval;
223*38e8c45fSAndroid Build Coastguard Worker ds_info->skip_user_consent = skip_user_consent;
224*38e8c45fSAndroid Build Coastguard Worker ds_->listener_ = listener;
225*38e8c45fSAndroid Build Coastguard Worker std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
226*38e8c45fSAndroid Build Coastguard Worker // Use a /dev/null FD when initializing options since none is provided.
227*38e8c45fSAndroid Build Coastguard Worker android::base::unique_fd devnull_fd(
228*38e8c45fSAndroid Build Coastguard Worker TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY | O_CLOEXEC)));
229*38e8c45fSAndroid Build Coastguard Worker
230*38e8c45fSAndroid Build Coastguard Worker options->Initialize(Dumpstate::BugreportMode::BUGREPORT_DEFAULT,
231*38e8c45fSAndroid Build Coastguard Worker 0, bugreport_fd, devnull_fd, false, skip_user_consent);
232*38e8c45fSAndroid Build Coastguard Worker
233*38e8c45fSAndroid Build Coastguard Worker if (bugreport_fd.get() == -1) {
234*38e8c45fSAndroid Build Coastguard Worker MYLOGE("Invalid filedescriptor");
235*38e8c45fSAndroid Build Coastguard Worker signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
236*38e8c45fSAndroid Build Coastguard Worker }
237*38e8c45fSAndroid Build Coastguard Worker ds_->SetOptions(std::move(options));
238*38e8c45fSAndroid Build Coastguard Worker ds_->path_ = bugreport_file;
239*38e8c45fSAndroid Build Coastguard Worker pthread_t thread;
240*38e8c45fSAndroid Build Coastguard Worker status_t err = pthread_create(&thread, nullptr, dumpstate_thread_retrieve, ds_info);
241*38e8c45fSAndroid Build Coastguard Worker if (err != 0) {
242*38e8c45fSAndroid Build Coastguard Worker MYLOGE("Could not create a thread");
243*38e8c45fSAndroid Build Coastguard Worker signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
244*38e8c45fSAndroid Build Coastguard Worker }
245*38e8c45fSAndroid Build Coastguard Worker return binder::Status::ok();
246*38e8c45fSAndroid Build Coastguard Worker }
247*38e8c45fSAndroid Build Coastguard Worker
dump(int fd,const Vector<String16> &)248*38e8c45fSAndroid Build Coastguard Worker status_t DumpstateService::dump(int fd, const Vector<String16>&) {
249*38e8c45fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lock(lock_);
250*38e8c45fSAndroid Build Coastguard Worker if (ds_ == nullptr) {
251*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "Bugreport not in progress yet");
252*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
253*38e8c45fSAndroid Build Coastguard Worker }
254*38e8c45fSAndroid Build Coastguard Worker std::string destination = ds_->options_->bugreport_fd.get() != -1
255*38e8c45fSAndroid Build Coastguard Worker ? StringPrintf("[fd:%d]", ds_->options_->bugreport_fd.get())
256*38e8c45fSAndroid Build Coastguard Worker : ds_->bugreport_internal_dir_.c_str();
257*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "id: %d\n", ds_->id_);
258*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "pid: %d\n", ds_->pid_);
259*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "update_progress: %s\n", ds_->options_->do_progress_updates ? "true" : "false");
260*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "last_percent_progress: %d\n", ds_->last_reported_percent_progress_);
261*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "progress:\n");
262*38e8c45fSAndroid Build Coastguard Worker ds_->progress_->Dump(fd, " ");
263*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "args: %s\n", ds_->options_->args.c_str());
264*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "bugreport_mode: %s\n", ds_->options_->bugreport_mode_string.c_str());
265*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "version: %s\n", ds_->version_.c_str());
266*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "bugreport_dir: %s\n", destination.c_str());
267*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "screenshot_path: %s\n", ds_->screenshot_path_.c_str());
268*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "log_path: %s\n", ds_->log_path_.c_str());
269*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "tmp_path: %s\n", ds_->tmp_path_.c_str());
270*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "path: %s\n", ds_->path_.c_str());
271*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "base_name: %s\n", ds_->base_name_.c_str());
272*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "name: %s\n", ds_->name_.c_str());
273*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "now: %ld\n", ds_->now_);
274*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "notification title: %s\n", ds_->options_->notification_title.c_str());
275*38e8c45fSAndroid Build Coastguard Worker dprintf(fd, "notification description: %s\n", ds_->options_->notification_description.c_str());
276*38e8c45fSAndroid Build Coastguard Worker
277*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
278*38e8c45fSAndroid Build Coastguard Worker }
279*38e8c45fSAndroid Build Coastguard Worker } // namespace os
280*38e8c45fSAndroid Build Coastguard Worker } // namespace android
281