Merge "Temporarily disable a test."
diff --git a/Android.bp b/Android.bp
index 461abb4..c44423f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -189,7 +189,7 @@
         android: {
             shared_libs: ["libcrypto"],
         },
-        linux_glibc: {
+        host_linux: {
             static_libs: ["libcrypto_static"],
         },
         recovery: {
diff --git a/README.md b/README.md
index 5f37bf2..3f2acac 100644
--- a/README.md
+++ b/README.md
@@ -89,6 +89,6 @@
 
 ## adbd <-> APPPLICATION communication
 
-This pipeline is detailed in [services.cpp](services.cpp). The JDWP extension implemented by Dalvik/ART are documented in:
+This pipeline is detailed in [daemon/jdwp_service.cpp](daemon/jdwp_service.cpp) with ASCII drawings! The JDWP extension implemented by Dalvik/ART are documented in:
 - platform/dalvik/+/master/docs/debugmon.html
 - platform/dalvik/+/master/docs/debugger.html
diff --git a/client/bugreport.cpp b/client/bugreport.cpp
index 1bee2f8..626dfbb 100644
--- a/client/bugreport.cpp
+++ b/client/bugreport.cpp
@@ -53,8 +53,8 @@
         SetLineMessage("generating");
     }
 
-    void OnStdout(const char* buffer, int length) {
-        for (int i = 0; i < length; i++) {
+    bool OnStdout(const char* buffer, size_t length) {
+        for (size_t i = 0; i < length; i++) {
             char c = buffer[i];
             if (c == '\n') {
                 ProcessLine(line_);
@@ -63,10 +63,11 @@
                 line_.append(1, c);
             }
         }
+        return true;
     }
 
-    void OnStderr(const char* buffer, int length) {
-        OnStream(nullptr, stderr, buffer, length);
+    bool OnStderr(const char* buffer, size_t length) {
+      return OnStream(nullptr, stderr, buffer, length, false);
     }
 
     int Done(int unused_) {
diff --git a/client/commandline.cpp b/client/commandline.cpp
index 37a92ea..018bfd7 100644
--- a/client/commandline.cpp
+++ b/client/commandline.cpp
@@ -44,10 +44,12 @@
 #include <android-base/strings.h>
 
 #if !defined(_WIN32)
-#include <signal.h>
 #include <sys/ioctl.h>
 #include <termios.h>
 #include <unistd.h>
+#else
+#define _POSIX
+#include <signal.h>
 #endif
 
 #include <google/protobuf/text_format.h>
@@ -98,6 +100,7 @@
         " --one-device SERIAL|USB  only allowed with 'start-server' or 'server nodaemon', server"
         " will only connect to one USB device, specified by a serial number or USB device"
         " address.\n"
+        " --exit-on-write-error    exit if stdout is closed\n"
         "\n"
         "general commands:\n"
         " devices [-l]             list connected devices (-l for long output)\n"
@@ -283,57 +286,55 @@
 }
 #endif
 
+int read_and_dump_protocol(borrowed_fd fd, StandardStreamsCallbackInterface* callback) {
+    int exit_code = 0;
+    std::unique_ptr<ShellProtocol> protocol = std::make_unique<ShellProtocol>(fd);
+    if (!protocol) {
+      LOG(ERROR) << "failed to allocate memory for ShellProtocol object";
+      return 1;
+    }
+    while (protocol->Read()) {
+      if (protocol->id() == ShellProtocol::kIdStdout) {
+        if (!callback->OnStdout(protocol->data(), protocol->data_length())) {
+          exit_code = SIGPIPE + 128;
+          break;
+        }
+      } else if (protocol->id() == ShellProtocol::kIdStderr) {
+        if (!callback->OnStderr(protocol->data(), protocol->data_length())) {
+          exit_code = SIGPIPE + 128;
+          break;
+        }
+      } else if (protocol->id() == ShellProtocol::kIdExit) {
+        // data() returns a char* which doesn't have defined signedness.
+        // Cast to uint8_t to prevent 255 from being sign extended to INT_MIN,
+        // which doesn't get truncated on Windows.
+        exit_code = static_cast<uint8_t>(protocol->data()[0]);
+      }
+    }
+    return exit_code;
+}
+
 int read_and_dump(borrowed_fd fd, bool use_shell_protocol,
                   StandardStreamsCallbackInterface* callback) {
     int exit_code = 0;
     if (fd < 0) return exit_code;
 
-    std::unique_ptr<ShellProtocol> protocol;
-    int length = 0;
-
-    char raw_buffer[BUFSIZ];
-    char* buffer_ptr = raw_buffer;
     if (use_shell_protocol) {
-        protocol = std::make_unique<ShellProtocol>(fd);
-        if (!protocol) {
-            LOG(ERROR) << "failed to allocate memory for ShellProtocol object";
-            return 1;
+      exit_code = read_and_dump_protocol(fd, callback);
+    } else {
+      char raw_buffer[BUFSIZ];
+      char* buffer_ptr = raw_buffer;
+      while (true) {
+        D("read_and_dump(): pre adb_read(fd=%d)", fd.get());
+        int length = adb_read(fd, raw_buffer, sizeof(raw_buffer));
+        D("read_and_dump(): post adb_read(fd=%d): length=%d", fd.get(), length);
+        if (length <= 0) {
+          break;
         }
-        buffer_ptr = protocol->data();
-    }
-
-    while (true) {
-        if (use_shell_protocol) {
-            if (!protocol->Read()) {
-                break;
-            }
-            length = protocol->data_length();
-            switch (protocol->id()) {
-                case ShellProtocol::kIdStdout:
-                    callback->OnStdout(buffer_ptr, length);
-                    break;
-                case ShellProtocol::kIdStderr:
-                    callback->OnStderr(buffer_ptr, length);
-                    break;
-                case ShellProtocol::kIdExit:
-                    // data() returns a char* which doesn't have defined signedness.
-                    // Cast to uint8_t to prevent 255 from being sign extended to INT_MIN,
-                    // which doesn't get truncated on Windows.
-                    exit_code = static_cast<uint8_t>(protocol->data()[0]);
-                    continue;
-                default:
-                    continue;
-            }
-            length = protocol->data_length();
-        } else {
-            D("read_and_dump(): pre adb_read(fd=%d)", fd.get());
-            length = adb_read(fd, raw_buffer, sizeof(raw_buffer));
-            D("read_and_dump(): post adb_read(fd=%d): length=%d", fd.get(), length);
-            if (length <= 0) {
-                break;
-            }
-            callback->OnStdout(buffer_ptr, length);
+        if (!callback->OnStdout(buffer_ptr, length)) {
+          break;
         }
+      }
     }
 
     return callback->Done(exit_code);
@@ -1405,8 +1406,8 @@
     TrackAppStreamsCallback() : DefaultStandardStreamsCallback(nullptr, nullptr) {}
 
     // Assume the buffer contains at least 4 bytes of valid data.
-    void OnStdout(const char* buffer, int length) override {
-        if (length < 4) return;  // Unexpected length received. Do nothing.
+    bool OnStdout(const char* buffer, size_t length) override {
+        if (length < 4) return true;  // Unexpected length received. Do nothing.
 
         adb::proto::AppProcesses binary_proto;
         // The first 4 bytes are the length of remaining content in hexadecimal format.
@@ -1414,11 +1415,13 @@
         char summary[24];  // The following string includes digits and 16 fixed characters.
         int written = snprintf(summary, sizeof(summary), "Process count: %d\n",
                                binary_proto.process_size());
-        OnStream(nullptr, stdout, summary, written);
+        if (!OnStream(nullptr, stdout, summary, written, false)) {
+          return false;
+        }
 
         std::string string_proto;
         google::protobuf::TextFormat::PrintToString(binary_proto, &string_proto);
-        OnStream(nullptr, stdout, string_proto.data(), string_proto.length());
+        return OnStream(nullptr, stdout, string_proto.data(), string_proto.length(), false);
     }
 
   private:
@@ -1626,6 +1629,8 @@
             server_socket_str = argv[1];
             --argc;
             ++argv;
+        } else if (strcmp(argv[0], "--exit-on-write-error") == 0) {
+            DEFAULT_STANDARD_STREAMS_CALLBACK.ReturnErrors(true);
         } else {
             /* out of recognized modifiers and flags */
             break;
diff --git a/client/commandline.h b/client/commandline.h
index c41f063..a0bba06 100644
--- a/client/commandline.h
+++ b/client/commandline.h
@@ -35,10 +35,12 @@
     StandardStreamsCallbackInterface() {
     }
     // Handles the stdout output from devices supporting the Shell protocol.
-    virtual void OnStdout(const char* buffer, int length) = 0;
+    // Returns true on success and false on failure.
+    virtual bool OnStdout(const char* buffer, size_t length) = 0;
 
     // Handles the stderr output from devices supporting the Shell protocol.
-    virtual void OnStderr(const char* buffer, int length) = 0;
+    // Returns true on success and false on failure.
+    virtual bool OnStderr(const char* buffer, size_t length) = 0;
 
     // Indicates the communication is finished and returns the appropriate error
     // code.
@@ -48,12 +50,15 @@
     virtual int Done(int status) = 0;
 
   protected:
-    static void OnStream(std::string* string, FILE* stream, const char* buffer, int length) {
+    static bool OnStream(std::string* string, FILE* stream, const char* buffer, size_t length,
+                         bool returnErrors) {
         if (string != nullptr) {
             string->append(buffer, length);
+            return true;
         } else {
-            fwrite(buffer, 1, length, stream);
+            bool okay = (fwrite(buffer, 1, length, stream) == length);
             fflush(stream);
+            return returnErrors ? okay : true;
         }
     }
 
@@ -61,32 +66,40 @@
     DISALLOW_COPY_AND_ASSIGN(StandardStreamsCallbackInterface);
 };
 
-// Default implementation that redirects the streams to the equilavent host
-// stream or to a string
-// passed to the constructor.
+// Default implementation that redirects the streams to the equivalent host
+// stream or to a string passed to the constructor.
 class DefaultStandardStreamsCallback : public StandardStreamsCallbackInterface {
   public:
     // If |stdout_str| is non-null, OnStdout will append to it.
     // If |stderr_str| is non-null, OnStderr will append to it.
     DefaultStandardStreamsCallback(std::string* stdout_str, std::string* stderr_str)
-        : stdout_str_(stdout_str), stderr_str_(stderr_str) {
+        : stdout_str_(stdout_str), stderr_str_(stderr_str), returnErrors_(false) {
+    }
+    DefaultStandardStreamsCallback(std::string* stdout_str, std::string* stderr_str,
+                                   bool returnErrors)
+        : stdout_str_(stdout_str), stderr_str_(stderr_str), returnErrors_(returnErrors) {
     }
 
-    void OnStdout(const char* buffer, int length) {
-        OnStream(stdout_str_, stdout, buffer, length);
+    bool OnStdout(const char* buffer, size_t length) {
+        return OnStream(stdout_str_, stdout, buffer, length, returnErrors_);
     }
 
-    void OnStderr(const char* buffer, int length) {
-        OnStream(stderr_str_, stderr, buffer, length);
+    bool OnStderr(const char* buffer, size_t length) {
+        return OnStream(stderr_str_, stderr, buffer, length, returnErrors_);
     }
 
     int Done(int status) {
         return status;
     }
 
+    void ReturnErrors(bool returnErrors) {
+        returnErrors_ = returnErrors;
+    }
+
   private:
     std::string* stdout_str_;
     std::string* stderr_str_;
+    bool returnErrors_;
 
     DISALLOW_COPY_AND_ASSIGN(DefaultStandardStreamsCallback);
 };
@@ -94,8 +107,8 @@
 class SilentStandardStreamsCallbackInterface : public StandardStreamsCallbackInterface {
   public:
     SilentStandardStreamsCallbackInterface() = default;
-    void OnStdout(const char*, int) override final {}
-    void OnStderr(const char*, int) override final {}
+    bool OnStdout(const char*, size_t) override final { return true; }
+    bool OnStderr(const char*, size_t) override final { return true; }
     int Done(int status) override final { return status; }
 };
 
diff --git a/client/fastdeploycallbacks.cpp b/client/fastdeploycallbacks.cpp
index 86ceaa1..7cebe0c 100644
--- a/client/fastdeploycallbacks.cpp
+++ b/client/fastdeploycallbacks.cpp
@@ -37,8 +37,8 @@
   public:
     DeployAgentBufferCallback(std::vector<char>* outBuffer, std::vector<char>* errBuffer);
 
-    virtual void OnStdout(const char* buffer, int length);
-    virtual void OnStderr(const char* buffer, int length);
+    virtual bool OnStdout(const char* buffer, size_t length);
+    virtual bool OnStderr(const char* buffer, size_t length);
     virtual int Done(int status);
 
   private:
@@ -58,12 +58,14 @@
     mpErrBuffer = errBuffer;
 }
 
-void DeployAgentBufferCallback::OnStdout(const char* buffer, int length) {
+bool DeployAgentBufferCallback::OnStdout(const char* buffer, size_t length) {
     appendBuffer(mpOutBuffer, buffer, length);
+    return true;
 }
 
-void DeployAgentBufferCallback::OnStderr(const char* buffer, int length) {
+bool DeployAgentBufferCallback::OnStderr(const char* buffer, size_t length) {
     appendBuffer(mpErrBuffer, buffer, length);
+    return true;
 }
 
 int DeployAgentBufferCallback::Done(int status) {