diff options
Diffstat (limited to 'cmds/incident/main.cpp')
-rw-r--r-- | cmds/incident/main.cpp | 58 |
1 files changed, 41 insertions, 17 deletions
diff --git a/cmds/incident/main.cpp b/cmds/incident/main.cpp index dfb4f994b866..6c3d19715c2e 100644 --- a/cmds/incident/main.cpp +++ b/cmds/incident/main.cpp @@ -198,6 +198,26 @@ parse_receiver_arg(const string& arg, string* pkg, string* cls) } // ================================================================================ +static int +stream_output(const int read_fd, const int write_fd) { + while (true) { + uint8_t buf[4096]; + ssize_t amt = TEMP_FAILURE_RETRY(read(read_fd, buf, sizeof(buf))); + if (amt < 0) { + break; + } else if (amt == 0) { + break; + } + + ssize_t wamt = TEMP_FAILURE_RETRY(write(write_fd, buf, amt)); + if (wamt != amt) { + return errno; + } + } + return 0; +} + +// ================================================================================ static void usage(FILE* out) { @@ -208,11 +228,13 @@ usage(FILE* out) fprintf(out, "OPTIONS\n"); fprintf(out, " -l list available sections\n"); fprintf(out, " -p privacy spec, LOCAL, EXPLICIT or AUTOMATIC. Default AUTOMATIC.\n"); + fprintf(out, " -r REASON human readable description of why the report is taken.\n"); fprintf(out, "\n"); fprintf(out, "and one of these destinations:\n"); fprintf(out, " -b (default) print the report to stdout (in proto format)\n"); fprintf(out, " -d send the report into dropbox\n"); - fprintf(out, " -r REASON human readable description of why the report is taken.\n"); + fprintf(out, " -u print a full report to stdout for dumpstate to zip as a bug\n"); + fprintf(out, " report. SECTION is ignored. Should only be called by dumpstate.\n"); fprintf(out, " -s PKG/CLS send broadcast to the broadcast receiver.\n"); fprintf(out, "\n"); fprintf(out, " SECTION the field numbers of the incident report fields to include\n"); @@ -224,14 +246,14 @@ main(int argc, char** argv) { Status status; IncidentReportArgs args; - enum { DEST_UNSET, DEST_DROPBOX, DEST_STDOUT, DEST_BROADCAST } destination = DEST_UNSET; + enum { DEST_UNSET, DEST_DROPBOX, DEST_STDOUT, DEST_BROADCAST, DEST_DUMPSTATE } destination = DEST_UNSET; int privacyPolicy = PRIVACY_POLICY_AUTOMATIC; string reason; string receiverArg; // Parse the args int opt; - while ((opt = getopt(argc, argv, "bhdlp:r:s:")) != -1) { + while ((opt = getopt(argc, argv, "bhdlp:r:s:u")) != -1) { switch (opt) { case 'h': usage(stdout); @@ -253,6 +275,13 @@ main(int argc, char** argv) } destination = DEST_DROPBOX; break; + case 'u': + if (!(destination == DEST_UNSET || destination == DEST_DUMPSTATE)) { + usage(stderr); + return 1; + } + destination = DEST_DUMPSTATE; + break; case 'p': privacyPolicy = get_privacy_policy(optarg); break; @@ -355,21 +384,16 @@ main(int argc, char** argv) // Wait for the result and print out the data they send. //IPCThreadState::self()->joinThreadPool(); - - while (true) { - uint8_t buf[4096]; - ssize_t amt = TEMP_FAILURE_RETRY(read(fds[0], buf, sizeof(buf))); - if (amt < 0) { - break; - } else if (amt == 0) { - break; - } - - ssize_t wamt = TEMP_FAILURE_RETRY(write(STDOUT_FILENO, buf, amt)); - if (wamt != amt) { - return errno; - } + return stream_output(fds[0], STDOUT_FILENO); + } else if (destination == DEST_DUMPSTATE) { + // Call into the service + sp<StatusListener> listener(new StatusListener()); + status = service->reportIncidentToDumpstate(writeEnd, listener); + if (!status.isOk()) { + fprintf(stderr, "reportIncident returned \"%s\"\n", status.toString8().string()); + return 1; } + return stream_output(fds[0], STDOUT_FILENO); } else { status = service->reportIncident(args); if (!status.isOk()) { |