Fix a race conditon in `incident`.

`incident` may exit too early, which leads to data lost. This commit
fixes it.

Bug: 144821874
Test: atest com.android.server.cts.IncidentdTest
Change-Id: Ib73118cb690a8247049b5685ed0b227dad63f752
diff --git a/cmds/incident/main.cpp b/cmds/incident/main.cpp
index eb2b98a..d6c6c39 100644
--- a/cmds/incident/main.cpp
+++ b/cmds/incident/main.cpp
@@ -52,9 +52,13 @@
     virtual Status onReportServiceStatus(const String16& service, int32_t status);
     virtual Status onReportFinished();
     virtual Status onReportFailed();
+
+    int getExitCodeOrElse(int defaultCode);
+ private:
+    int mExitCode;
 };
 
-StatusListener::StatusListener()
+StatusListener::StatusListener(): mExitCode(-1)
 {
 }
 
@@ -89,7 +93,7 @@
 {
     fprintf(stderr, "done\n");
     ALOGD("done\n");
-    exit(0);
+    mExitCode = 0;
     return Status::ok();
 }
 
@@ -98,10 +102,15 @@
 {
     fprintf(stderr, "failed\n");
     ALOGD("failed\n");
-    exit(1);
+    mExitCode = 1;
     return Status::ok();
 }
 
+int
+StatusListener::getExitCodeOrElse(int defaultCode) {
+    return mExitCode == -1 ? defaultCode : mExitCode;
+}
+
 // ================================================================================
 static void section_list(FILE* out) {
     IncidentSection sections[INCIDENT_SECTION_COUNT];
@@ -201,20 +210,13 @@
 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)));
+        int amt = splice(read_fd, NULL, write_fd, NULL, 4096, 0);
         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;
+        } else if (amt == 0) {
+            return 0;
         }
     }
-    return 0;
 }
 
 // ================================================================================
@@ -384,7 +386,7 @@
 
         // Wait for the result and print out the data they send.
         //IPCThreadState::self()->joinThreadPool();
-        return stream_output(fds[0], STDOUT_FILENO);
+        return listener->getExitCodeOrElse(stream_output(fds[0], STDOUT_FILENO));
     } else if (destination == DEST_DUMPSTATE) {
         // Call into the service
         sp<StatusListener> listener(new StatusListener());
@@ -393,7 +395,7 @@
             fprintf(stderr, "reportIncident returned \"%s\"\n", status.toString8().string());
             return 1;
         }
-        return stream_output(fds[0], STDOUT_FILENO);
+        return listener->getExitCodeOrElse(stream_output(fds[0], STDOUT_FILENO));
     } else {
         status = service->reportIncident(args);
         if (!status.isOk()) {