pdx: Rework error reporting when transfering file and channel handles

There is a lot of confusion about reporting errors when passing file
and channel handles over PDX transport between client and service.

Methods like Message::PushFileHandle return an integer which means
both a file handle reference value (if positive) and a possible error
code (if negative). But file handles could contain negative values too
(when they are empty). This is used frequently when passing buffer
fences around (when a fence is not being used, its fd is set to -1).

This results in a special case of when PushFileHandle is called with
a file handle with value of -1, the return value is actually "-errno"
which becomes dependent on a global state (errno is not set by
PushFileHandle itself in case file handle value is negative) and results
in unpredicted behavior (sometimes errno is 0, sometimes its >0).

Cleaned this all up by using Status<T> everywhere we used an int to
pass value payload along with possible error code.

Now the semantics of the calls are more clear.

Bug: 36866492
Test: `m -j32` for sailfish-eng succeeds
      Ran unit tests on device (pdx_tests, libpdx_uds_tests, bufferhub_tests,
      buffer_hub_queue-test, buffer_hub_queue_producer-test), all pass
      Ran CubeSea, NativeTreasureHunt and Ithaca on Sailfish with vrflinger
      enabled, was able to use controller and screen rendered correctly.

Change-Id: I0f40c3f356fcba8bc217d5219a0ddf9685e57fd7
diff --git a/libs/vr/libpdx/client.cpp b/libs/vr/libpdx/client.cpp
index c318628..bfa2d87 100644
--- a/libs/vr/libpdx/client.cpp
+++ b/libs/vr/libpdx/client.cpp
@@ -4,7 +4,6 @@
 #include <log/log.h>
 
 #include <pdx/trace.h>
-#include "errno_guard.h"
 
 namespace android {
 namespace pdx {
@@ -84,7 +83,6 @@
 
 Status<void> Client::SendImpulse(int opcode) {
   PDX_TRACE_NAME("Client::SendImpulse");
-  ErrnoGuard errno_guard;
 
   auto status = CheckReconnect();
   if (!status)
@@ -98,7 +96,6 @@
 Status<void> Client::SendImpulse(int opcode, const void* buffer,
                                  size_t length) {
   PDX_TRACE_NAME("Client::SendImpulse");
-  ErrnoGuard errno_guard;
 
   auto status = CheckReconnect();
   if (!status)
@@ -110,7 +107,6 @@
 }
 
 void Client::Close(int error) {
-  ErrnoGuard errno_guard;
   channel_.reset();
   // Normalize error codes to negative integer space.
   error_ = error <= 0 ? error : -error;
@@ -228,37 +224,38 @@
   CheckDisconnect(*ret);
 }
 
-FileReference Transaction::PushFileHandle(const LocalHandle& handle) {
-  return client_.CheckReconnect() && EnsureStateAllocated()
-             ? client_.GetChannel()->PushFileHandle(state_, handle)
-             : -1;
+Status<FileReference> Transaction::PushFileHandle(const LocalHandle& handle) {
+  if (client_.CheckReconnect() && EnsureStateAllocated())
+    return client_.GetChannel()->PushFileHandle(state_, handle);
+  return ErrorStatus{ESHUTDOWN};
 }
 
-FileReference Transaction::PushFileHandle(const BorrowedHandle& handle) {
-  return client_.CheckReconnect() && EnsureStateAllocated()
-             ? client_.GetChannel()->PushFileHandle(state_, handle)
-             : -1;
+Status<FileReference> Transaction::PushFileHandle(
+    const BorrowedHandle& handle) {
+  if (client_.CheckReconnect() && EnsureStateAllocated())
+    return client_.GetChannel()->PushFileHandle(state_, handle);
+  return ErrorStatus{ESHUTDOWN};
 }
 
-FileReference Transaction::PushFileHandle(const RemoteHandle& handle) {
+Status<FileReference> Transaction::PushFileHandle(const RemoteHandle& handle) {
   return handle.Get();
 }
 
-ChannelReference Transaction::PushChannelHandle(
+Status<ChannelReference> Transaction::PushChannelHandle(
     const LocalChannelHandle& handle) {
-  return client_.CheckReconnect() && EnsureStateAllocated()
-             ? client_.GetChannel()->PushChannelHandle(state_, handle)
-             : -1;
+  if (client_.CheckReconnect() && EnsureStateAllocated())
+    return client_.GetChannel()->PushChannelHandle(state_, handle);
+  return ErrorStatus{ESHUTDOWN};
 }
 
-ChannelReference Transaction::PushChannelHandle(
+Status<ChannelReference> Transaction::PushChannelHandle(
     const BorrowedChannelHandle& handle) {
-  return client_.CheckReconnect() && EnsureStateAllocated()
-             ? client_.GetChannel()->PushChannelHandle(state_, handle)
-             : -1;
+  if (client_.CheckReconnect() && EnsureStateAllocated())
+    return client_.GetChannel()->PushChannelHandle(state_, handle);
+  return ErrorStatus{ESHUTDOWN};
 }
 
-ChannelReference Transaction::PushChannelHandle(
+Status<ChannelReference> Transaction::PushChannelHandle(
     const RemoteChannelHandle& handle) {
   return handle.value();
 }
diff --git a/libs/vr/libpdx/client_tests.cpp b/libs/vr/libpdx/client_tests.cpp
index f1fb6d1..99ccc69 100644
--- a/libs/vr/libpdx/client_tests.cpp
+++ b/libs/vr/libpdx/client_tests.cpp
@@ -518,28 +518,29 @@
   EXPECT_CALL(*mock_channel(),
               PushFileHandle(kTransactionState, A<const LocalHandle&>()))
       .WillOnce(Return(1));
-  EXPECT_EQ(1, transaction_.PushFileHandle(LocalHandle{-1}));
+  EXPECT_EQ(1, transaction_.PushFileHandle(LocalHandle{-1}).get());
 
   EXPECT_CALL(*mock_channel(),
               PushFileHandle(kTransactionState, A<const BorrowedHandle&>()))
       .WillOnce(Return(2));
-  EXPECT_EQ(2, transaction_.PushFileHandle(BorrowedHandle{-1}));
+  EXPECT_EQ(2, transaction_.PushFileHandle(BorrowedHandle{-1}).get());
 
-  EXPECT_EQ(3, transaction_.PushFileHandle(RemoteHandle{3}));
+  EXPECT_EQ(3, transaction_.PushFileHandle(RemoteHandle{3}).get());
 
   EXPECT_CALL(
       *mock_channel(),
       PushChannelHandle(kTransactionState, A<const LocalChannelHandle&>()))
       .WillOnce(Return(11));
-  EXPECT_EQ(11, transaction_.PushChannelHandle(LocalChannelHandle{nullptr, 1}));
+  EXPECT_EQ(
+      11, transaction_.PushChannelHandle(LocalChannelHandle{nullptr, 1}).get());
 
   EXPECT_CALL(
       *mock_channel(),
       PushChannelHandle(kTransactionState, A<const BorrowedChannelHandle&>()))
       .WillOnce(Return(12));
-  EXPECT_EQ(12, transaction_.PushChannelHandle(BorrowedChannelHandle{2}));
+  EXPECT_EQ(12, transaction_.PushChannelHandle(BorrowedChannelHandle{2}).get());
 
-  EXPECT_EQ(13, transaction_.PushChannelHandle(RemoteChannelHandle{13}));
+  EXPECT_EQ(13, transaction_.PushChannelHandle(RemoteChannelHandle{13}).get());
 }
 
 TEST_F(ClientTransactionTest, GetHandle) {
diff --git a/libs/vr/libpdx/errno_guard.h b/libs/vr/libpdx/errno_guard.h
deleted file mode 100644
index fc7dfdf..0000000
--- a/libs/vr/libpdx/errno_guard.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef ANDROID_PDX_ERRNO_GUARD_H_
-#define ANDROID_PDX_ERRNO_GUARD_H_
-
-#include <errno.h>
-
-namespace android {
-namespace pdx {
-
-// Automatically saves and restores the system errno for API implementations to
-// prevent internal use errno from affecting API callers.
-class ErrnoGuard {
- public:
-  ErrnoGuard() : saved_errno_(errno) {}
-  ~ErrnoGuard() { errno = saved_errno_; }
-
-  int saved_errno() const { return saved_errno_; }
-
- private:
-  int saved_errno_;
-
-  ErrnoGuard(const ErrnoGuard&) = delete;
-  void operator=(const ErrnoGuard&) = delete;
-};
-
-// Checks |return_code| and returns either it or the negated system errno based
-// on the return code value.
-inline int ReturnCodeOrError(int return_code) {
-  return return_code < 0 ? -errno : return_code;
-}
-
-}  // namespace pdx
-}  // namespace android
-
-#endif  // ANDROID_PDX_ERRNO_GUARD_H_
diff --git a/libs/vr/libpdx/private/pdx/client.h b/libs/vr/libpdx/private/pdx/client.h
index a590087..656de7e 100644
--- a/libs/vr/libpdx/private/pdx/client.h
+++ b/libs/vr/libpdx/private/pdx/client.h
@@ -253,13 +253,14 @@
   }
 
   // OutputResourceMapper
-  FileReference PushFileHandle(const LocalHandle& handle) override;
-  FileReference PushFileHandle(const BorrowedHandle& handle) override;
-  FileReference PushFileHandle(const RemoteHandle& handle) override;
-  ChannelReference PushChannelHandle(const LocalChannelHandle& handle) override;
-  ChannelReference PushChannelHandle(
+  Status<FileReference> PushFileHandle(const LocalHandle& handle) override;
+  Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override;
+  Status<FileReference> PushFileHandle(const RemoteHandle& handle) override;
+  Status<ChannelReference> PushChannelHandle(
+      const LocalChannelHandle& handle) override;
+  Status<ChannelReference> PushChannelHandle(
       const BorrowedChannelHandle& handle) override;
-  ChannelReference PushChannelHandle(
+  Status<ChannelReference> PushChannelHandle(
       const RemoteChannelHandle& handle) override;
 
   // InputResourceMapper
diff --git a/libs/vr/libpdx/private/pdx/message_writer.h b/libs/vr/libpdx/private/pdx/message_writer.h
index 0cb6e40..4a101d6 100644
--- a/libs/vr/libpdx/private/pdx/message_writer.h
+++ b/libs/vr/libpdx/private/pdx/message_writer.h
@@ -3,20 +3,22 @@
 
 #include <pdx/channel_handle.h>
 #include <pdx/file_handle.h>
+#include <pdx/status.h>
 
 namespace android {
 namespace pdx {
 
 class OutputResourceMapper {
  public:
-  virtual FileReference PushFileHandle(const LocalHandle& handle) = 0;
-  virtual FileReference PushFileHandle(const BorrowedHandle& handle) = 0;
-  virtual FileReference PushFileHandle(const RemoteHandle& handle) = 0;
-  virtual ChannelReference PushChannelHandle(
+  virtual Status<FileReference> PushFileHandle(const LocalHandle& handle) = 0;
+  virtual Status<FileReference> PushFileHandle(
+      const BorrowedHandle& handle) = 0;
+  virtual Status<FileReference> PushFileHandle(const RemoteHandle& handle) = 0;
+  virtual Status<ChannelReference> PushChannelHandle(
       const LocalChannelHandle& handle) = 0;
-  virtual ChannelReference PushChannelHandle(
+  virtual Status<ChannelReference> PushChannelHandle(
       const BorrowedChannelHandle& handle) = 0;
-  virtual ChannelReference PushChannelHandle(
+  virtual Status<ChannelReference> PushChannelHandle(
       const RemoteChannelHandle& handle) = 0;
 
  protected:
diff --git a/libs/vr/libpdx/private/pdx/mock_message_writer.h b/libs/vr/libpdx/private/pdx/mock_message_writer.h
index 3c513d7..e06e5bb 100644
--- a/libs/vr/libpdx/private/pdx/mock_message_writer.h
+++ b/libs/vr/libpdx/private/pdx/mock_message_writer.h
@@ -9,15 +9,18 @@
 
 class MockOutputResourceMapper : public OutputResourceMapper {
  public:
-  MOCK_METHOD1(PushFileHandle, FileReference(const LocalHandle& handle));
-  MOCK_METHOD1(PushFileHandle, FileReference(const BorrowedHandle& handle));
-  MOCK_METHOD1(PushFileHandle, FileReference(const RemoteHandle& handle));
+  MOCK_METHOD1(PushFileHandle,
+               Status<FileReference>(const LocalHandle& handle));
+  MOCK_METHOD1(PushFileHandle,
+               Status<FileReference>(const BorrowedHandle& handle));
+  MOCK_METHOD1(PushFileHandle,
+               Status<FileReference>(const RemoteHandle& handle));
   MOCK_METHOD1(PushChannelHandle,
-               ChannelReference(const LocalChannelHandle& handle));
+               Status<ChannelReference>(const LocalChannelHandle& handle));
   MOCK_METHOD1(PushChannelHandle,
-               ChannelReference(const BorrowedChannelHandle& handle));
+               Status<ChannelReference>(const BorrowedChannelHandle& handle));
   MOCK_METHOD1(PushChannelHandle,
-               ChannelReference(const RemoteChannelHandle& handle));
+               Status<ChannelReference>(const RemoteChannelHandle& handle));
 };
 
 class MockMessageWriter : public MessageWriter {
diff --git a/libs/vr/libpdx/private/pdx/mock_service_endpoint.h b/libs/vr/libpdx/private/pdx/mock_service_endpoint.h
index ead74d5..e741d4a 100644
--- a/libs/vr/libpdx/private/pdx/mock_service_endpoint.h
+++ b/libs/vr/libpdx/private/pdx/mock_service_endpoint.h
@@ -10,46 +10,54 @@
 class MockEndpoint : public Endpoint {
  public:
   MOCK_CONST_METHOD0(GetIpcTag, uint32_t());
-  MOCK_METHOD1(SetService, int(Service* service));
-  MOCK_METHOD2(SetChannel, int(int channel_id, Channel* channel));
-  MOCK_METHOD1(CloseChannel, int(int channel_id));
+  MOCK_METHOD1(SetService, Status<void>(Service* service));
+  MOCK_METHOD2(SetChannel, Status<void>(int channel_id, Channel* channel));
+  MOCK_METHOD1(CloseChannel, Status<void>(int channel_id));
   MOCK_METHOD3(ModifyChannelEvents,
-               int(int channel_id, int clear_mask, int set_mask));
+               Status<void>(int channel_id, int clear_mask, int set_mask));
   MOCK_METHOD4(PushChannel,
                Status<RemoteChannelHandle>(Message* message, int flags,
                                            Channel* channel, int* channel_id));
   MOCK_METHOD3(CheckChannel,
                Status<int>(const Message* message, ChannelReference ref,
                            Channel** channel));
-  MOCK_METHOD1(DefaultHandleMessage, int(const MessageInfo& info));
-  MOCK_METHOD1(MessageReceive, int(Message* message));
-  MOCK_METHOD2(MessageReply, int(Message* message, int return_code));
-  MOCK_METHOD2(MessageReplyFd, int(Message* message, unsigned int push_fd));
+  MOCK_METHOD1(MessageReceive, Status<void>(Message* message));
+  MOCK_METHOD2(MessageReply, Status<void>(Message* message, int return_code));
+  MOCK_METHOD2(MessageReplyFd,
+               Status<void>(Message* message, unsigned int push_fd));
   MOCK_METHOD2(MessageReplyChannelHandle,
-               int(Message* message, const LocalChannelHandle& handle));
+               Status<void>(Message* message,
+                            const LocalChannelHandle& handle));
   MOCK_METHOD2(MessageReplyChannelHandle,
-               int(Message* message, const BorrowedChannelHandle& handle));
+               Status<void>(Message* message,
+                            const BorrowedChannelHandle& handle));
   MOCK_METHOD2(MessageReplyChannelHandle,
-               int(Message* message, const RemoteChannelHandle& handle));
-  MOCK_METHOD3(ReadMessageData, ssize_t(Message* message, const iovec* vector,
-                                        size_t vector_length));
-  MOCK_METHOD3(WriteMessageData, ssize_t(Message* message, const iovec* vector,
-                                         size_t vector_length));
+               Status<void>(Message* message,
+                            const RemoteChannelHandle& handle));
+  MOCK_METHOD3(ReadMessageData,
+               Status<size_t>(Message* message, const iovec* vector,
+                              size_t vector_length));
+  MOCK_METHOD3(WriteMessageData,
+               Status<size_t>(Message* message, const iovec* vector,
+                              size_t vector_length));
   MOCK_METHOD2(PushFileHandle,
-               FileReference(Message* message, const LocalHandle& handle));
+               Status<FileReference>(Message* message,
+                                     const LocalHandle& handle));
   MOCK_METHOD2(PushFileHandle,
-               FileReference(Message* message, const BorrowedHandle& handle));
+               Status<FileReference>(Message* message,
+                                     const BorrowedHandle& handle));
   MOCK_METHOD2(PushFileHandle,
-               FileReference(Message* message, const RemoteHandle& handle));
+               Status<FileReference>(Message* message,
+                                     const RemoteHandle& handle));
   MOCK_METHOD2(PushChannelHandle,
-               ChannelReference(Message* message,
-                                const LocalChannelHandle& handle));
+               Status<ChannelReference>(Message* message,
+                                        const LocalChannelHandle& handle));
   MOCK_METHOD2(PushChannelHandle,
-               ChannelReference(Message* message,
-                                const BorrowedChannelHandle& handle));
+               Status<ChannelReference>(Message* message,
+                                        const BorrowedChannelHandle& handle));
   MOCK_METHOD2(PushChannelHandle,
-               ChannelReference(Message* message,
-                                const RemoteChannelHandle& handle));
+               Status<ChannelReference>(Message* message,
+                                        const RemoteChannelHandle& handle));
   MOCK_CONST_METHOD2(GetFileHandle,
                      LocalHandle(Message* message, FileReference ref));
   MOCK_CONST_METHOD2(GetChannelHandle,
@@ -57,7 +65,7 @@
                                         ChannelReference ref));
   MOCK_METHOD0(AllocateMessageState, void*());
   MOCK_METHOD1(FreeMessageState, void(void* state));
-  MOCK_METHOD0(Cancel, int());
+  MOCK_METHOD0(Cancel, Status<void>());
 };
 
 }  // namespace pdx
diff --git a/libs/vr/libpdx/private/pdx/rpc/remote_method.h b/libs/vr/libpdx/private/pdx/rpc/remote_method.h
index 3eca9e5..505c63b 100644
--- a/libs/vr/libpdx/private/pdx/rpc/remote_method.h
+++ b/libs/vr/libpdx/private/pdx/rpc/remote_method.h
@@ -121,9 +121,9 @@
 // either during dispatch of the remote method handler or at a later time if the
 // message is moved for delayed response.
 inline void RemoteMethodError(Message& message, int error_code) {
-  const int ret = message.ReplyError(error_code);
-  ALOGE_IF(ret < 0, "RemoteMethodError: Failed to reply to message: %s",
-           strerror(-ret));
+  const auto status = message.ReplyError(error_code);
+  ALOGE_IF(!status, "RemoteMethodError: Failed to reply to message: %s",
+           status.GetErrorMessage().c_str());
 }
 
 // Returns a value from a remote method to the client. The usual method to
@@ -135,9 +135,9 @@
 template <typename RemoteMethodType, typename Return>
 EnableIfDirectReturn<typename RemoteMethodType::Return> RemoteMethodReturn(
     Message& message, const Return& return_value) {
-  const int ret = message.Reply(return_value);
-  ALOGE_IF(ret < 0, "RemoteMethodReturn: Failed to reply to message: %s",
-           strerror(-ret));
+  const auto status = message.Reply(return_value);
+  ALOGE_IF(!status, "RemoteMethodReturn: Failed to reply to message: %s",
+           status.GetErrorMessage().c_str());
 }
 
 // Overload for non-direct return types.
@@ -148,14 +148,10 @@
   rpc::ServicePayload<ReplyBuffer> payload(message);
   MakeArgumentEncoder<Signature>(&payload).EncodeReturn(return_value);
 
-  int ret;
-  auto size = message.Write(payload.Data(), payload.Size());
-  if (size < static_cast<decltype(size)>(payload.Size()))
-    ret = message.ReplyError(EIO);
-  else
-    ret = message.Reply(0);
-  ALOGE_IF(ret < 0, "RemoteMethodReturn: Failed to reply to message: %s",
-           strerror(-ret));
+  auto ret = message.WriteAll(payload.Data(), payload.Size());
+  auto status = message.Reply(ret);
+  ALOGE_IF(!status, "RemoteMethodReturn: Failed to reply to message: %s",
+           status.GetErrorMessage().c_str());
 }
 
 // Overload for Status<void> return types.
@@ -189,13 +185,13 @@
   rpc::ServicePayload<ReceiveBuffer> payload(message);
   payload.Resize(max_capacity);
 
-  auto size = message.Read(payload.Data(), payload.Size());
-  if (size < 0) {
-    RemoteMethodError(message, -size);
+  Status<size_t> read_status = message.Read(payload.Data(), payload.Size());
+  if (!read_status) {
+    RemoteMethodError(message, read_status.error());
     return;
   }
 
-  payload.Resize(size);
+  payload.Resize(read_status.get());
 
   ErrorType error;
   auto decoder = MakeArgumentDecoder<Signature>(&payload);
@@ -225,13 +221,13 @@
   rpc::ServicePayload<ReceiveBuffer> payload(message);
   payload.Resize(max_capacity);
 
-  auto size = message.Read(payload.Data(), payload.Size());
-  if (size < 0) {
-    RemoteMethodError(message, -size);
+  Status<size_t> read_status = message.Read(payload.Data(), payload.Size());
+  if (!read_status) {
+    RemoteMethodError(message, read_status.error());
     return;
   }
 
-  payload.Resize(size);
+  payload.Resize(read_status.get());
 
   ErrorType error;
   auto decoder = MakeArgumentDecoder<Signature>(&payload);
@@ -265,13 +261,13 @@
   rpc::ServicePayload<ReceiveBuffer> payload(message);
   payload.Resize(max_capacity);
 
-  auto size = message.Read(payload.Data(), payload.Size());
-  if (size < 0) {
-    RemoteMethodError(message, -size);
+  Status<size_t> read_status = message.Read(payload.Data(), payload.Size());
+  if (!read_status) {
+    RemoteMethodError(message, read_status.error());
     return;
   }
 
-  payload.Resize(size);
+  payload.Resize(read_status.get());
 
   ErrorType error;
   auto decoder = MakeArgumentDecoder<Signature>(&payload);
diff --git a/libs/vr/libpdx/private/pdx/rpc/serialization.h b/libs/vr/libpdx/private/pdx/rpc/serialization.h
index fccd028..9a012ed 100644
--- a/libs/vr/libpdx/private/pdx/rpc/serialization.h
+++ b/libs/vr/libpdx/private/pdx/rpc/serialization.h
@@ -905,8 +905,9 @@
 inline void SerializeObject(const FileHandle<Mode>& fd, MessageWriter* writer,
                             void*& buffer) {
   SerializeType(fd, buffer);
-  const FileReference value =
+  const Status<FileReference> status =
       writer->GetOutputResourceMapper()->PushFileHandle(fd);
+  FileReference value = status ? status.get() : -status.error();
   SerializeRaw(value, buffer);
 }
 
@@ -915,8 +916,9 @@
 inline void SerializeObject(const ChannelHandle<Mode>& handle,
                             MessageWriter* writer, void*& buffer) {
   SerializeType(handle, buffer);
-  const ChannelReference value =
+  const Status<ChannelReference> status =
       writer->GetOutputResourceMapper()->PushChannelHandle(handle);
+  ChannelReference value = status ? status.get() : -status.error();
   SerializeRaw(value, buffer);
 }
 
diff --git a/libs/vr/libpdx/private/pdx/service.h b/libs/vr/libpdx/private/pdx/service.h
index 175cedf..0d30614 100644
--- a/libs/vr/libpdx/private/pdx/service.h
+++ b/libs/vr/libpdx/private/pdx/service.h
@@ -98,29 +98,62 @@
   /*
    * Read/write payload, in either single buffer or iovec form.
    */
-  ssize_t ReadVector(const iovec* vector, size_t vector_length);
-  ssize_t Read(void* buffer, size_t length);
-  ssize_t WriteVector(const iovec* vector, size_t vector_length);
-  ssize_t Write(const void* buffer, size_t length);
+  Status<size_t> ReadVector(const iovec* vector, size_t vector_length);
+  Status<size_t> Read(void* buffer, size_t length);
+  Status<size_t> WriteVector(const iovec* vector, size_t vector_length);
+  Status<size_t> Write(const void* buffer, size_t length);
 
   template <size_t N>
-  inline ssize_t ReadVector(const iovec (&vector)[N]) {
+  inline Status<size_t> ReadVector(const iovec (&vector)[N]) {
     return ReadVector(vector, N);
   }
 
   template <size_t N>
-  inline ssize_t WriteVector(const iovec (&vector)[N]) {
+  inline Status<size_t> WriteVector(const iovec (&vector)[N]) {
     return WriteVector(vector, N);
   }
 
+  // Helper functions to read/write all requested bytes, and return EIO if not
+  // all were read/written.
+  Status<void> ReadVectorAll(const iovec* vector, size_t vector_length);
+  Status<void> WriteVectorAll(const iovec* vector, size_t vector_length);
+
+  inline Status<void> ReadAll(void* buffer, size_t length) {
+    Status<size_t> status = Read(buffer, length);
+    if (status && status.get() < length)
+      status.SetError(EIO);
+    Status<void> ret;
+    ret.PropagateError(status);
+    return ret;
+  }
+  inline Status<void> WriteAll(const void* buffer, size_t length) {
+    Status<size_t> status = Write(buffer, length);
+    if (status && status.get() < length)
+      status.SetError(EIO);
+    Status<void> ret;
+    ret.PropagateError(status);
+    return ret;
+  }
+
+  template <size_t N>
+  inline Status<void> ReadVectorAll(const iovec (&vector)[N]) {
+    return ReadVectorAll(vector, N);
+  }
+
+  template <size_t N>
+  inline Status<void> WriteVectorAll(const iovec (&vector)[N]) {
+    return WriteVectorAll(vector, N);
+  }
+
   // OutputResourceMapper
-  FileReference PushFileHandle(const LocalHandle& handle) override;
-  FileReference PushFileHandle(const BorrowedHandle& handle) override;
-  FileReference PushFileHandle(const RemoteHandle& handle) override;
-  ChannelReference PushChannelHandle(const LocalChannelHandle& handle) override;
-  ChannelReference PushChannelHandle(
+  Status<FileReference> PushFileHandle(const LocalHandle& handle) override;
+  Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override;
+  Status<FileReference> PushFileHandle(const RemoteHandle& handle) override;
+  Status<ChannelReference> PushChannelHandle(
+      const LocalChannelHandle& handle) override;
+  Status<ChannelReference> PushChannelHandle(
       const BorrowedChannelHandle& handle) override;
-  ChannelReference PushChannelHandle(
+  Status<ChannelReference> PushChannelHandle(
       const RemoteChannelHandle& handle) override;
 
   // InputResourceMapper
@@ -131,25 +164,29 @@
   /*
    * Various ways to reply to a message.
    */
-  int Reply(int return_code);
-  int ReplyError(unsigned error);
-  int ReplyFileDescriptor(unsigned int fd);
-  int Reply(const LocalHandle& handle);
-  int Reply(const BorrowedHandle& handle);
-  int Reply(const RemoteHandle& handle);
-  int Reply(const LocalChannelHandle& handle);
-  int Reply(const BorrowedChannelHandle& handle);
-  int Reply(const RemoteChannelHandle& handle);
+  Status<void> Reply(int return_code);
+  Status<void> ReplyError(unsigned int error);
+  Status<void> ReplyFileDescriptor(unsigned int fd);
+  Status<void> Reply(const LocalHandle& handle);
+  Status<void> Reply(const BorrowedHandle& handle);
+  Status<void> Reply(const RemoteHandle& handle);
+  Status<void> Reply(const LocalChannelHandle& handle);
+  Status<void> Reply(const BorrowedChannelHandle& handle);
+  Status<void> Reply(const RemoteChannelHandle& handle);
 
   template <typename T>
-  inline int Reply(const Status<T>& status) {
+  inline Status<void> Reply(const Status<T>& status) {
     return status ? Reply(status.get()) : ReplyError(status.error());
   }
 
+  inline Status<void> Reply(const Status<void>& status) {
+    return status ? Reply(0) : ReplyError(status.error());
+  }
+
   /*
    * Update the channel event bits with the given clear and set masks.
    */
-  int ModifyChannelEvents(int clear_mask, int set_mask);
+  Status<void> ModifyChannelEvents(int clear_mask, int set_mask);
 
   /*
    * Create a new channel and push it as a file descriptor to the client. See
@@ -264,7 +301,7 @@
    * these in multi-threaded services.
    */
   std::shared_ptr<Channel> GetChannel() const;
-  void SetChannel(const std::shared_ptr<Channel>& channnel);
+  Status<void> SetChannel(const std::shared_ptr<Channel>& channnel);
 
   /*
    * Get the Channel object for the channel associated with this message,
@@ -355,7 +392,8 @@
    * the Channel object until the channel is closed or another call replaces
    * the current value.
    */
-  int SetChannel(int channel_id, const std::shared_ptr<Channel>& channel);
+  Status<void> SetChannel(int channel_id,
+                          const std::shared_ptr<Channel>& channel);
 
   /*
    * Get the channel context for the given channel id. This method should be
@@ -404,7 +442,7 @@
    *
    * OnChannelClosed is not called in response to this method call.
    */
-  int CloseChannel(int channel_id);
+  Status<void> CloseChannel(int channel_id);
 
   /*
    * Update the event bits for the given channel (given by id), using the
@@ -413,7 +451,8 @@
    * This is useful for asynchronously signaling events that clients may be
    * waiting for using select/poll/epoll.
    */
-  int ModifyChannelEvents(int channel_id, int clear_mask, int set_mask);
+  Status<void> ModifyChannelEvents(int channel_id, int clear_mask,
+                                   int set_mask);
 
   /*
    * Create a new channel and push it as a file descriptor to the process
@@ -478,7 +517,7 @@
    * The default implementation simply calls defaultHandleMessage().
    * Subclasses should call the same for any unrecognized message opcodes.
    */
-  virtual int HandleMessage(Message& message);
+  virtual Status<void> HandleMessage(Message& message);
 
   /*
    * Handle an asynchronous message. Subclasses override this to receive
@@ -496,9 +535,9 @@
    * Provides default handling of CHANNEL_OPEN and CHANNEL_CLOSE, calling
    * OnChannelOpen() and OnChannelClose(), respectively.
    *
-   * For all other message opcodes, this method replies with -ENOTSUP.
+   * For all other message opcodes, this method replies with ENOTSUP.
    */
-  int DefaultHandleMessage(Message& message);
+  Status<void> DefaultHandleMessage(Message& message);
 
   /*
    * Called when system properties have changed. Subclasses should implement
@@ -515,7 +554,7 @@
    * Cancels the endpoint, unblocking any receiver threads waiting in
    * ReceiveAndDispatch().
    */
-  int Cancel();
+  Status<void> Cancel();
 
   /*
    * Iterator type for Channel map iterators.
@@ -564,14 +603,14 @@
    * If the endpoint is in blocking mode this call blocks until a message is
    * received, a signal is delivered to this thread, or the service is canceled.
    * If the endpoint is in non-blocking mode and a message is not pending this
-   * call returns immediately with -ETIMEDOUT.
+   * call returns immediately with ETIMEDOUT.
    */
-  int ReceiveAndDispatch();
+  Status<void> ReceiveAndDispatch();
 
  private:
   friend class Message;
 
-  bool HandleSystemMessage(Message& message);
+  Status<void> HandleSystemMessage(Message& message);
 
   Service(const Service&);
   void operator=(const Service&) = delete;
@@ -639,28 +678,28 @@
 
 #define REPLY_ERROR(message, error, error_label)                              \
   do {                                                                        \
-    int __ret = message.ReplyError(error);                                    \
-    CHECK_ERROR(__ret < 0, error_label,                                       \
+    auto __status = message.ReplyError(error);                                \
+    CHECK_ERROR(!__status, error_label,                                       \
                 PDX_ERROR_PREFIX " Failed to reply to message because: %s\n", \
-                strerror(-__ret));                                            \
+                __status.GetErrorMessage().c_str());                          \
     goto error_label;                                                         \
   } while (0)
 
 #define REPLY_ERROR_RETURN(message, error, ...)                          \
   do {                                                                   \
-    int __ret = message.ReplyError(error);                               \
-    ALOGE_IF(__ret < 0,                                                  \
+    auto __status = message.ReplyError(error);                           \
+    ALOGE_IF(!__status,                                                  \
              PDX_ERROR_PREFIX " Failed to reply to message because: %s", \
-             strerror(-__ret));                                          \
+             __status.GetErrorMessage().c_str());                        \
     return __VA_ARGS__;                                                  \
   } while (0)
 
 #define REPLY_MESSAGE(message, message_return_code, error_label)              \
   do {                                                                        \
-    int __ret = message.Reply(message_return_code);                           \
-    CHECK_ERROR(__ret < 0, error_label,                                       \
+    auto __status = message.Reply(message_return_code);                       \
+    CHECK_ERROR(!__status, error_label,                                       \
                 PDX_ERROR_PREFIX " Failed to reply to message because: %s\n", \
-                strerror(-__ret));                                            \
+                __status.GetErrorMessage().c_str());                          \
     goto error_label;                                                         \
   } while (0)
 
@@ -669,10 +708,10 @@
 
 #define REPLY_MESSAGE_RETURN(message, message_return_code, ...)          \
   do {                                                                   \
-    int __ret = message.Reply(message_return_code);                      \
-    ALOGE_IF(__ret < 0,                                                  \
+    auto __status = message.Reply(message_return_code);                  \
+    ALOGE_IF(!__status,                                                  \
              PDX_ERROR_PREFIX " Failed to reply to message because: %s", \
-             strerror(-__ret));                                          \
+             __status.GetErrorMessage().c_str());                        \
     return __VA_ARGS__;                                                  \
   } while (0)
 
@@ -681,19 +720,19 @@
 
 #define REPLY_FD(message, push_fd, error_label)                               \
   do {                                                                        \
-    int __ret = message.ReplyFileDescriptor(push_fd);                         \
-    CHECK_ERROR(__ret < 0, error_label,                                       \
+    auto __status = message.ReplyFileDescriptor(push_fd);                     \
+    CHECK_ERROR(!__status, error_label,                                       \
                 PDX_ERROR_PREFIX " Failed to reply to message because: %s\n", \
-                strerror(-__ret));                                            \
+                __status.GetErrorMessage().c_str());                          \
     goto error_label;                                                         \
   } while (0)
 
 #define REPLY_FD_RETURN(message, push_fd, ...)                           \
   do {                                                                   \
-    int __ret = message.ReplyFileDescriptor(push_fd);                    \
-    ALOGE_IF(__ret < 0,                                                  \
+    auto __status = message.ReplyFileDescriptor(push_fd);                \
+    ALOGE_IF(__status < 0,                                               \
              PDX_ERROR_PREFIX " Failed to reply to message because: %s", \
-             strerror(-__ret));                                          \
+             __status.GetErrorMessage().c_str());                        \
     return __VA_ARGS__;                                                  \
   } while (0)
 
diff --git a/libs/vr/libpdx/private/pdx/service_endpoint.h b/libs/vr/libpdx/private/pdx/service_endpoint.h
index 613be7c..28bd6bc 100644
--- a/libs/vr/libpdx/private/pdx/service_endpoint.h
+++ b/libs/vr/libpdx/private/pdx/service_endpoint.h
@@ -44,20 +44,20 @@
   // Associates a Service instance with an endpoint by setting the service
   // context pointer to the address of the Service. Only one Service may be
   // associated with a given endpoint.
-  virtual int SetService(Service* service) = 0;
+  virtual Status<void> SetService(Service* service) = 0;
 
   // Set the channel context for the given channel.
-  virtual int SetChannel(int channel_id, Channel* channel) = 0;
+  virtual Status<void> SetChannel(int channel_id, Channel* channel) = 0;
 
   // Close a channel, signaling the client file object and freeing the channel
   // id. Once closed, the client side of the channel always returns the error
   // ESHUTDOWN and signals the poll/epoll events POLLHUP and POLLFREE.
-  virtual int CloseChannel(int channel_id) = 0;
+  virtual Status<void> CloseChannel(int channel_id) = 0;
 
   // Update the event bits for the given channel (given by id), using the
   // given clear and set masks.
-  virtual int ModifyChannelEvents(int channel_id, int clear_mask,
-                                  int set_mask) = 0;
+  virtual Status<void> ModifyChannelEvents(int channel_id, int clear_mask,
+                                           int set_mask) = 0;
 
   // Create a new channel and push it as a file descriptor to the process
   // sending the |message|. |flags| may be set to O_NONBLOCK and/or
@@ -77,54 +77,49 @@
   virtual Status<int> CheckChannel(const Message* message, ChannelReference ref,
                                    Channel** channel) = 0;
 
-  // The default message handler. It is important that all messages
-  // (eventually) get a reply. This method should be called for any unrecognized
-  // opcodes or otherwise unhandled messages to prevent erroneous requests from
-  // blocking indefinitely.
-  virtual int DefaultHandleMessage(const MessageInfo& info) = 0;
-
   // Receives a message on the given endpoint file descriptor.
-  virtual int MessageReceive(Message* message) = 0;
+  virtual Status<void> MessageReceive(Message* message) = 0;
 
   // Replies to the message with a return code.
-  virtual int MessageReply(Message* message, int return_code) = 0;
+  virtual Status<void> MessageReply(Message* message, int return_code) = 0;
 
   // Replies to the message with a file descriptor.
-  virtual int MessageReplyFd(Message* message, unsigned int push_fd) = 0;
+  virtual Status<void> MessageReplyFd(Message* message,
+                                      unsigned int push_fd) = 0;
 
   // Replies to the message with a local channel handle.
-  virtual int MessageReplyChannelHandle(Message* message,
-                                        const LocalChannelHandle& handle) = 0;
+  virtual Status<void> MessageReplyChannelHandle(
+      Message* message, const LocalChannelHandle& handle) = 0;
 
   // Replies to the message with a borrowed local channel handle.
-  virtual int MessageReplyChannelHandle(
+  virtual Status<void> MessageReplyChannelHandle(
       Message* message, const BorrowedChannelHandle& handle) = 0;
 
   // Replies to the message with a remote channel handle.
-  virtual int MessageReplyChannelHandle(Message* message,
-                                        const RemoteChannelHandle& handle) = 0;
+  virtual Status<void> MessageReplyChannelHandle(
+      Message* message, const RemoteChannelHandle& handle) = 0;
 
   // Reads message data into an array of memory buffers.
-  virtual ssize_t ReadMessageData(Message* message, const iovec* vector,
-                                  size_t vector_length) = 0;
+  virtual Status<size_t> ReadMessageData(Message* message, const iovec* vector,
+                                         size_t vector_length) = 0;
 
   // Sends reply data for message.
-  virtual ssize_t WriteMessageData(Message* message, const iovec* vector,
-                                   size_t vector_length) = 0;
+  virtual Status<size_t> WriteMessageData(Message* message, const iovec* vector,
+                                          size_t vector_length) = 0;
 
   // Records a file descriptor into the message buffer and returns the remapped
   // reference to be sent to the remote process.
-  virtual FileReference PushFileHandle(Message* message,
-                                       const LocalHandle& handle) = 0;
-  virtual FileReference PushFileHandle(Message* message,
-                                       const BorrowedHandle& handle) = 0;
-  virtual FileReference PushFileHandle(Message* message,
-                                       const RemoteHandle& handle) = 0;
-  virtual ChannelReference PushChannelHandle(
+  virtual Status<FileReference> PushFileHandle(Message* message,
+                                               const LocalHandle& handle) = 0;
+  virtual Status<FileReference> PushFileHandle(
+      Message* message, const BorrowedHandle& handle) = 0;
+  virtual Status<FileReference> PushFileHandle(Message* message,
+                                               const RemoteHandle& handle) = 0;
+  virtual Status<ChannelReference> PushChannelHandle(
       Message* message, const LocalChannelHandle& handle) = 0;
-  virtual ChannelReference PushChannelHandle(
+  virtual Status<ChannelReference> PushChannelHandle(
       Message* message, const BorrowedChannelHandle& handle) = 0;
-  virtual ChannelReference PushChannelHandle(
+  virtual Status<ChannelReference> PushChannelHandle(
       Message* message, const RemoteChannelHandle& handle) = 0;
 
   // Obtains a file descriptor/channel handle from a message for the given
@@ -140,7 +135,7 @@
 
   // Cancels the endpoint, unblocking any receiver threads waiting for a
   // message.
-  virtual int Cancel() = 0;
+  virtual Status<void> Cancel() = 0;
 };
 
 }  // namespace pdx
diff --git a/libs/vr/libpdx/private/pdx/status.h b/libs/vr/libpdx/private/pdx/status.h
index ca2832c..067fe25 100644
--- a/libs/vr/libpdx/private/pdx/status.h
+++ b/libs/vr/libpdx/private/pdx/status.h
@@ -103,6 +103,17 @@
   // is not empty nor containing a valid value).
   int error() const { return std::max(error_, 0); }
 
+  // Returns the error code as ErrorStatus object. This is a helper method
+  // to aid in propagation of error codes between Status<T> of different types
+  // as in the following example:
+  //    Status<int> foo() {
+  //      Status<void> status = bar();
+  //      if(!status)
+  //        return status.error_status();
+  //      return 12;
+  //    }
+  inline ErrorStatus error_status() const { return ErrorStatus{error()}; }
+
   // Returns the error message associated with error code stored in the object.
   // The message is the same as the string returned by strerror(status.error()).
   // Can be called only when an error is actually stored (that is, the object
@@ -142,6 +153,7 @@
   bool empty() const { return false; }
   explicit operator bool() const { return ok(); }
   int error() const { return std::max(error_, 0); }
+  inline ErrorStatus error_status() const { return ErrorStatus{error()}; }
   std::string GetErrorMessage() const {
     std::string message;
     if (error_ > 0)
diff --git a/libs/vr/libpdx/private/pdx/utility.h b/libs/vr/libpdx/private/pdx/utility.h
index c8c717c..305c3b8 100644
--- a/libs/vr/libpdx/private/pdx/utility.h
+++ b/libs/vr/libpdx/private/pdx/utility.h
@@ -150,29 +150,29 @@
 
 class NoOpOutputResourceMapper : public OutputResourceMapper {
  public:
-  FileReference PushFileHandle(const LocalHandle& handle) override {
+  Status<FileReference> PushFileHandle(const LocalHandle& handle) override {
     return handle.Get();
   }
 
-  FileReference PushFileHandle(const BorrowedHandle& handle) override {
+  Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override {
     return handle.Get();
   }
 
-  FileReference PushFileHandle(const RemoteHandle& handle) override {
+  Status<FileReference> PushFileHandle(const RemoteHandle& handle) override {
     return handle.Get();
   }
 
-  ChannelReference PushChannelHandle(
+  Status<ChannelReference> PushChannelHandle(
       const LocalChannelHandle& handle) override {
     return handle.value();
   }
 
-  ChannelReference PushChannelHandle(
+  Status<ChannelReference> PushChannelHandle(
       const BorrowedChannelHandle& handle) override {
     return handle.value();
   }
 
-  ChannelReference PushChannelHandle(
+  Status<ChannelReference> PushChannelHandle(
       const RemoteChannelHandle& handle) override {
     return handle.value();
   }
@@ -278,7 +278,7 @@
   OutputResourceMapper* GetOutputResourceMapper() override { return this; }
 
   // OutputResourceMapper
-  FileReference PushFileHandle(const LocalHandle& handle) override {
+  Status<FileReference> PushFileHandle(const LocalHandle& handle) override {
     if (handle) {
       const int ref = file_handles_.size();
       file_handles_.push_back(handle.Get());
@@ -288,7 +288,7 @@
     }
   }
 
-  FileReference PushFileHandle(const BorrowedHandle& handle) override {
+  Status<FileReference> PushFileHandle(const BorrowedHandle& handle) override {
     if (handle) {
       const int ref = file_handles_.size();
       file_handles_.push_back(handle.Get());
@@ -298,11 +298,11 @@
     }
   }
 
-  FileReference PushFileHandle(const RemoteHandle& handle) override {
+  Status<FileReference> PushFileHandle(const RemoteHandle& handle) override {
     return handle.Get();
   }
 
-  ChannelReference PushChannelHandle(
+  Status<ChannelReference> PushChannelHandle(
       const LocalChannelHandle& handle) override {
     if (handle) {
       const int ref = file_handles_.size();
@@ -313,7 +313,7 @@
     }
   }
 
-  ChannelReference PushChannelHandle(
+  Status<ChannelReference> PushChannelHandle(
       const BorrowedChannelHandle& handle) override {
     if (handle) {
       const int ref = file_handles_.size();
@@ -324,7 +324,7 @@
     }
   }
 
-  ChannelReference PushChannelHandle(
+  Status<ChannelReference> PushChannelHandle(
       const RemoteChannelHandle& handle) override {
     return handle.value();
   }
diff --git a/libs/vr/libpdx/service.cpp b/libs/vr/libpdx/service.cpp
index daf9af8..fab4770 100644
--- a/libs/vr/libpdx/service.cpp
+++ b/libs/vr/libpdx/service.cpp
@@ -9,7 +9,6 @@
 #include <cstdint>
 
 #include <pdx/trace.h>
-#include "errno_guard.h"
 
 #define TRACE 0
 
@@ -60,7 +59,7 @@
           "ERROR: Service \"%s\" failed to reply to message: op=%d pid=%d "
           "cid=%d\n",
           svc->name_.c_str(), info_.op, info_.pid, info_.cid);
-      svc->endpoint()->DefaultHandleMessage(info_);
+      svc->DefaultHandleMessage(*this);
     }
     svc->endpoint()->FreeMessageState(state_);
   }
@@ -77,112 +76,138 @@
   return ImpulseBegin() + (IsImpulse() ? GetSendLength() : 0);
 }
 
-ssize_t Message::ReadVector(const struct iovec* vector, size_t vector_length) {
+Status<size_t> Message::ReadVector(const struct iovec* vector,
+                                   size_t vector_length) {
   PDX_TRACE_NAME("Message::ReadVector");
   if (auto svc = service_.lock()) {
-    ErrnoGuard errno_guard;
-    const ssize_t ret =
-        svc->endpoint()->ReadMessageData(this, vector, vector_length);
-    return ReturnCodeOrError(ret);
+    return svc->endpoint()->ReadMessageData(this, vector, vector_length);
   } else {
-    return -ESHUTDOWN;
+    return ErrorStatus{ESHUTDOWN};
   }
 }
 
-ssize_t Message::Read(void* buffer, size_t length) {
+Status<void> Message::ReadVectorAll(const struct iovec* vector,
+                                    size_t vector_length) {
+  PDX_TRACE_NAME("Message::ReadVectorAll");
+  if (auto svc = service_.lock()) {
+    const auto status =
+        svc->endpoint()->ReadMessageData(this, vector, vector_length);
+    if (!status)
+      return status.error_status();
+    size_t size_to_read = 0;
+    for (size_t i = 0; i < vector_length; i++)
+      size_to_read += vector[i].iov_len;
+    if (status.get() < size_to_read)
+      return ErrorStatus{EIO};
+    return {};
+  } else {
+    return ErrorStatus{ESHUTDOWN};
+  }
+}
+
+Status<size_t> Message::Read(void* buffer, size_t length) {
   PDX_TRACE_NAME("Message::Read");
   if (auto svc = service_.lock()) {
-    ErrnoGuard errno_guard;
     const struct iovec vector = {buffer, length};
-    const ssize_t ret = svc->endpoint()->ReadMessageData(this, &vector, 1);
-    return ReturnCodeOrError(ret);
+    return svc->endpoint()->ReadMessageData(this, &vector, 1);
   } else {
-    return -ESHUTDOWN;
+    return ErrorStatus{ESHUTDOWN};
   }
 }
 
-ssize_t Message::WriteVector(const struct iovec* vector, size_t vector_length) {
+Status<size_t> Message::WriteVector(const struct iovec* vector,
+                                    size_t vector_length) {
   PDX_TRACE_NAME("Message::WriteVector");
   if (auto svc = service_.lock()) {
-    ErrnoGuard errno_guard;
-    const ssize_t ret =
-        svc->endpoint()->WriteMessageData(this, vector, vector_length);
-    return ReturnCodeOrError(ret);
+    return svc->endpoint()->WriteMessageData(this, vector, vector_length);
   } else {
-    return -ESHUTDOWN;
+    return ErrorStatus{ESHUTDOWN};
   }
 }
 
-ssize_t Message::Write(const void* buffer, size_t length) {
+Status<void> Message::WriteVectorAll(const struct iovec* vector,
+                                     size_t vector_length) {
+  PDX_TRACE_NAME("Message::WriteVector");
+  if (auto svc = service_.lock()) {
+    const auto status =
+        svc->endpoint()->WriteMessageData(this, vector, vector_length);
+    if (!status)
+      return status.error_status();
+    size_t size_to_write = 0;
+    for (size_t i = 0; i < vector_length; i++)
+      size_to_write += vector[i].iov_len;
+    if (status.get() < size_to_write)
+      return ErrorStatus{EIO};
+    return {};
+  } else {
+    return ErrorStatus{ESHUTDOWN};
+  }
+}
+
+Status<size_t> Message::Write(const void* buffer, size_t length) {
   PDX_TRACE_NAME("Message::Write");
   if (auto svc = service_.lock()) {
-    ErrnoGuard errno_guard;
     const struct iovec vector = {const_cast<void*>(buffer), length};
-    const ssize_t ret = svc->endpoint()->WriteMessageData(this, &vector, 1);
-    return ReturnCodeOrError(ret);
+    return svc->endpoint()->WriteMessageData(this, &vector, 1);
   } else {
-    return -ESHUTDOWN;
+    return ErrorStatus{ESHUTDOWN};
   }
 }
 
-FileReference Message::PushFileHandle(const LocalHandle& handle) {
+Status<FileReference> Message::PushFileHandle(const LocalHandle& handle) {
   PDX_TRACE_NAME("Message::PushFileHandle");
   if (auto svc = service_.lock()) {
-    ErrnoGuard errno_guard;
-    return ReturnCodeOrError(svc->endpoint()->PushFileHandle(this, handle));
+    return svc->endpoint()->PushFileHandle(this, handle);
   } else {
-    return -ESHUTDOWN;
+    return ErrorStatus{ESHUTDOWN};
   }
 }
 
-FileReference Message::PushFileHandle(const BorrowedHandle& handle) {
+Status<FileReference> Message::PushFileHandle(const BorrowedHandle& handle) {
   PDX_TRACE_NAME("Message::PushFileHandle");
   if (auto svc = service_.lock()) {
-    ErrnoGuard errno_guard;
-    return ReturnCodeOrError(svc->endpoint()->PushFileHandle(this, handle));
+    return svc->endpoint()->PushFileHandle(this, handle);
   } else {
-    return -ESHUTDOWN;
+    return ErrorStatus{ESHUTDOWN};
   }
 }
 
-FileReference Message::PushFileHandle(const RemoteHandle& handle) {
+Status<FileReference> Message::PushFileHandle(const RemoteHandle& handle) {
   PDX_TRACE_NAME("Message::PushFileHandle");
   if (auto svc = service_.lock()) {
-    ErrnoGuard errno_guard;
-    return ReturnCodeOrError(svc->endpoint()->PushFileHandle(this, handle));
+    return svc->endpoint()->PushFileHandle(this, handle);
   } else {
-    return -ESHUTDOWN;
+    return ErrorStatus{ESHUTDOWN};
   }
 }
 
-ChannelReference Message::PushChannelHandle(const LocalChannelHandle& handle) {
+Status<ChannelReference> Message::PushChannelHandle(
+    const LocalChannelHandle& handle) {
   PDX_TRACE_NAME("Message::PushChannelHandle");
   if (auto svc = service_.lock()) {
-    ErrnoGuard errno_guard;
-    return ReturnCodeOrError(svc->endpoint()->PushChannelHandle(this, handle));
+    return svc->endpoint()->PushChannelHandle(this, handle);
   } else {
-    return -ESHUTDOWN;
+    return ErrorStatus{ESHUTDOWN};
   }
 }
 
-ChannelReference Message::PushChannelHandle(
+Status<ChannelReference> Message::PushChannelHandle(
     const BorrowedChannelHandle& handle) {
   PDX_TRACE_NAME("Message::PushChannelHandle");
   if (auto svc = service_.lock()) {
-    ErrnoGuard errno_guard;
-    return ReturnCodeOrError(svc->endpoint()->PushChannelHandle(this, handle));
+    return svc->endpoint()->PushChannelHandle(this, handle);
   } else {
-    return -ESHUTDOWN;
+    return ErrorStatus{ESHUTDOWN};
   }
 }
 
-ChannelReference Message::PushChannelHandle(const RemoteChannelHandle& handle) {
+Status<ChannelReference> Message::PushChannelHandle(
+    const RemoteChannelHandle& handle) {
   PDX_TRACE_NAME("Message::PushChannelHandle");
   if (auto svc = service_.lock()) {
-    ErrnoGuard errno_guard;
-    return ReturnCodeOrError(svc->endpoint()->PushChannelHandle(this, handle));
+    return svc->endpoint()->PushChannelHandle(this, handle);
   } else {
-    return -ESHUTDOWN;
+    return ErrorStatus{ESHUTDOWN};
   }
 }
 
@@ -193,7 +218,6 @@
     return false;
 
   if (ref >= 0) {
-    ErrnoGuard errno_guard;
     *handle = svc->endpoint()->GetFileHandle(this, ref);
     if (!handle->IsValid())
       return false;
@@ -211,7 +235,6 @@
     return false;
 
   if (ref >= 0) {
-    ErrnoGuard errno_guard;
     *handle = svc->endpoint()->GetChannelHandle(this, ref);
     if (!handle->valid())
       return false;
@@ -221,141 +244,137 @@
   return true;
 }
 
-int Message::Reply(int return_code) {
+Status<void> Message::Reply(int return_code) {
   PDX_TRACE_NAME("Message::Reply");
   auto svc = service_.lock();
   if (!replied_ && svc) {
-    ErrnoGuard errno_guard;
-    const int ret = svc->endpoint()->MessageReply(this, return_code);
-    replied_ = ret == 0;
-    return ReturnCodeOrError(ret);
+    const auto ret = svc->endpoint()->MessageReply(this, return_code);
+    replied_ = ret.ok();
+    return ret;
   } else {
-    return -EINVAL;
+    return ErrorStatus{EINVAL};
   }
 }
 
-int Message::ReplyFileDescriptor(unsigned int fd) {
+Status<void> Message::ReplyFileDescriptor(unsigned int fd) {
   PDX_TRACE_NAME("Message::ReplyFileDescriptor");
   auto svc = service_.lock();
   if (!replied_ && svc) {
-    ErrnoGuard errno_guard;
-    const int ret = svc->endpoint()->MessageReplyFd(this, fd);
-    replied_ = ret == 0;
-    return ReturnCodeOrError(ret);
+    const auto ret = svc->endpoint()->MessageReplyFd(this, fd);
+    replied_ = ret.ok();
+    return ret;
   } else {
-    return -EINVAL;
+    return ErrorStatus{EINVAL};
   }
 }
 
-int Message::ReplyError(unsigned error) {
+Status<void> Message::ReplyError(unsigned int error) {
   PDX_TRACE_NAME("Message::ReplyError");
   auto svc = service_.lock();
   if (!replied_ && svc) {
-    ErrnoGuard errno_guard;
-    const int ret = svc->endpoint()->MessageReply(this, -error);
-    replied_ = ret == 0;
-    return ReturnCodeOrError(ret);
+    const auto ret =
+        svc->endpoint()->MessageReply(this, -static_cast<int>(error));
+    replied_ = ret.ok();
+    return ret;
   } else {
-    return -EINVAL;
+    return ErrorStatus{EINVAL};
   }
 }
 
-int Message::Reply(const LocalHandle& handle) {
+Status<void> Message::Reply(const LocalHandle& handle) {
   PDX_TRACE_NAME("Message::ReplyFileHandle");
   auto svc = service_.lock();
   if (!replied_ && svc) {
-    ErrnoGuard errno_guard;
-    int ret;
+    Status<void> ret;
 
     if (handle)
       ret = svc->endpoint()->MessageReplyFd(this, handle.Get());
     else
       ret = svc->endpoint()->MessageReply(this, handle.Get());
 
-    replied_ = ret == 0;
-    return ReturnCodeOrError(ret);
+    replied_ = ret.ok();
+    return ret;
   } else {
-    return -EINVAL;
+    return ErrorStatus{EINVAL};
   }
 }
 
-int Message::Reply(const BorrowedHandle& handle) {
+Status<void> Message::Reply(const BorrowedHandle& handle) {
   PDX_TRACE_NAME("Message::ReplyFileHandle");
   auto svc = service_.lock();
   if (!replied_ && svc) {
-    ErrnoGuard errno_guard;
-    int ret;
+    Status<void> ret;
 
     if (handle)
       ret = svc->endpoint()->MessageReplyFd(this, handle.Get());
     else
       ret = svc->endpoint()->MessageReply(this, handle.Get());
 
-    replied_ = ret == 0;
-    return ReturnCodeOrError(ret);
+    replied_ = ret.ok();
+    return ret;
   } else {
-    return -EINVAL;
+    return ErrorStatus{EINVAL};
   }
 }
 
-int Message::Reply(const RemoteHandle& handle) {
+Status<void> Message::Reply(const RemoteHandle& handle) {
   PDX_TRACE_NAME("Message::ReplyFileHandle");
   auto svc = service_.lock();
   if (!replied_ && svc) {
-    ErrnoGuard errno_guard;
-    const int ret = svc->endpoint()->MessageReply(this, handle.Get());
-    replied_ = ret == 0;
-    return ReturnCodeOrError(ret);
+    Status<void> ret;
+
+    if (handle)
+      ret = svc->endpoint()->MessageReply(this, handle.Get());
+    else
+      ret = svc->endpoint()->MessageReply(this, handle.Get());
+
+    replied_ = ret.ok();
+    return ret;
   } else {
-    return -EINVAL;
+    return ErrorStatus{EINVAL};
   }
 }
 
-int Message::Reply(const LocalChannelHandle& handle) {
+Status<void> Message::Reply(const LocalChannelHandle& handle) {
   auto svc = service_.lock();
   if (!replied_ && svc) {
-    ErrnoGuard errno_guard;
-    const int ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
-    replied_ = ret == 0;
-    return ReturnCodeOrError(ret);
+    const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
+    replied_ = ret.ok();
+    return ret;
   } else {
-    return -EINVAL;
+    return ErrorStatus{EINVAL};
   }
 }
 
-int Message::Reply(const BorrowedChannelHandle& handle) {
+Status<void> Message::Reply(const BorrowedChannelHandle& handle) {
   auto svc = service_.lock();
   if (!replied_ && svc) {
-    ErrnoGuard errno_guard;
-    const int ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
-    replied_ = ret == 0;
-    return ReturnCodeOrError(ret);
+    const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
+    replied_ = ret.ok();
+    return ret;
   } else {
-    return -EINVAL;
+    return ErrorStatus{EINVAL};
   }
 }
 
-int Message::Reply(const RemoteChannelHandle& handle) {
+Status<void> Message::Reply(const RemoteChannelHandle& handle) {
   auto svc = service_.lock();
   if (!replied_ && svc) {
-    ErrnoGuard errno_guard;
-    const int ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
-    replied_ = ret == 0;
-    return ReturnCodeOrError(ret);
+    const auto ret = svc->endpoint()->MessageReplyChannelHandle(this, handle);
+    replied_ = ret.ok();
+    return ret;
   } else {
-    return -EINVAL;
+    return ErrorStatus{EINVAL};
   }
 }
 
-int Message::ModifyChannelEvents(int clear_mask, int set_mask) {
+Status<void> Message::ModifyChannelEvents(int clear_mask, int set_mask) {
   PDX_TRACE_NAME("Message::ModifyChannelEvents");
   if (auto svc = service_.lock()) {
-    ErrnoGuard errno_guard;
-    const int ret =
-        svc->endpoint()->ModifyChannelEvents(info_.cid, clear_mask, set_mask);
-    return ReturnCodeOrError(ret);
+    return svc->endpoint()->ModifyChannelEvents(info_.cid, clear_mask,
+                                                set_mask);
   } else {
-    return -ESHUTDOWN;
+    return ErrorStatus{ESHUTDOWN};
   }
 }
 
@@ -416,11 +435,12 @@
 
 std::shared_ptr<Channel> Message::GetChannel() const { return channel_.lock(); }
 
-void Message::SetChannel(const std::shared_ptr<Channel>& chan) {
+Status<void> Message::SetChannel(const std::shared_ptr<Channel>& chan) {
   channel_ = chan;
-
+  Status<void> status;
   if (auto svc = service_.lock())
-    svc->SetChannel(info_.cid, chan);
+    status = svc->SetChannel(info_.cid, chan);
+  return status;
 }
 
 std::shared_ptr<Service> Message::GetService() const { return service_.lock(); }
@@ -432,16 +452,16 @@
   if (!endpoint_)
     return;
 
-  const int ret = endpoint_->SetService(this);
-  ALOGE_IF(ret < 0, "Failed to set service context because: %s",
-           strerror(-ret));
+  const auto status = endpoint_->SetService(this);
+  ALOGE_IF(!status, "Failed to set service context because: %s",
+           status.GetErrorMessage().c_str());
 }
 
 Service::~Service() {
   if (endpoint_) {
-    const int ret = endpoint_->SetService(nullptr);
-    ALOGE_IF(ret < 0, "Failed to clear service context because: %s",
-             strerror(-ret));
+    const auto status = endpoint_->SetService(nullptr);
+    ALOGE_IF(!status, "Failed to clear service context because: %s",
+             status.GetErrorMessage().c_str());
   }
 }
 
@@ -459,32 +479,28 @@
 void Service::OnChannelClose(Message& /*message*/,
                              const std::shared_ptr<Channel>& /*channel*/) {}
 
-int Service::SetChannel(int channel_id,
-                        const std::shared_ptr<Channel>& channel) {
+Status<void> Service::SetChannel(int channel_id,
+                                 const std::shared_ptr<Channel>& channel) {
   PDX_TRACE_NAME("Service::SetChannel");
-  ErrnoGuard errno_guard;
   std::lock_guard<std::mutex> autolock(channels_mutex_);
 
-  const int ret = endpoint_->SetChannel(channel_id, channel.get());
-  if (ret == -1) {
+  const auto status = endpoint_->SetChannel(channel_id, channel.get());
+  if (!status) {
     ALOGE("%s::SetChannel: Failed to set channel context: %s\n", name_.c_str(),
-          strerror(errno));
+          status.GetErrorMessage().c_str());
 
     // It's possible someone mucked with things behind our back by calling the C
     // API directly. Since we know the channel id isn't valid, make sure we
     // don't have it in the channels map.
-    if (errno == ENOENT)
+    if (status.error() == ENOENT)
       channels_.erase(channel_id);
-
-    return ReturnCodeOrError(ret);
+  } else {
+    if (channel != nullptr)
+      channels_[channel_id] = channel;
+    else
+      channels_.erase(channel_id);
   }
-
-  if (channel != nullptr)
-    channels_[channel_id] = channel;
-  else
-    channels_.erase(channel_id);
-
-  return ret;
+  return status;
 }
 
 std::shared_ptr<Channel> Service::GetChannel(int channel_id) const {
@@ -498,21 +514,21 @@
     return nullptr;
 }
 
-int Service::CloseChannel(int channel_id) {
+Status<void> Service::CloseChannel(int channel_id) {
   PDX_TRACE_NAME("Service::CloseChannel");
-  ErrnoGuard errno_guard;
   std::lock_guard<std::mutex> autolock(channels_mutex_);
 
-  const int ret = endpoint_->CloseChannel(channel_id);
+  const auto status = endpoint_->CloseChannel(channel_id);
 
   // Always erase the map entry, in case someone mucked with things behind our
   // back using the C API directly.
   channels_.erase(channel_id);
 
-  return ReturnCodeOrError(ret);
+  return status;
 }
 
-int Service::ModifyChannelEvents(int channel_id, int clear_mask, int set_mask) {
+Status<void> Service::ModifyChannelEvents(int channel_id, int clear_mask,
+                                          int set_mask) {
   PDX_TRACE_NAME("Service::ModifyChannelEvents");
   return endpoint_->ModifyChannelEvents(channel_id, clear_mask, set_mask);
 }
@@ -521,7 +537,6 @@
     Message* message, int flags, const std::shared_ptr<Channel>& channel,
     int* channel_id) {
   PDX_TRACE_NAME("Service::PushChannel");
-  ErrnoGuard errno_guard;
 
   std::lock_guard<std::mutex> autolock(channels_mutex_);
 
@@ -542,7 +557,6 @@
 Status<int> Service::CheckChannel(const Message* message, ChannelReference ref,
                                   std::shared_ptr<Channel>* channel) const {
   PDX_TRACE_NAME("Service::CheckChannel");
-  ErrnoGuard errno_guard;
 
   // Synchronization to maintain consistency between the kernel's channel
   // context pointer and the userspace channels_ map. Other threads may attempt
@@ -565,13 +579,13 @@
 
 std::string Service::DumpState(size_t /*max_length*/) { return ""; }
 
-int Service::HandleMessage(Message& message) {
+Status<void> Service::HandleMessage(Message& message) {
   return DefaultHandleMessage(message);
 }
 
 void Service::HandleImpulse(Message& /*impulse*/) {}
 
-bool Service::HandleSystemMessage(Message& message) {
+Status<void> Service::HandleSystemMessage(Message& message) {
   const MessageInfo& info = message.GetInfo();
 
   switch (info.op) {
@@ -579,8 +593,7 @@
       ALOGD("%s::OnChannelOpen: pid=%d cid=%d\n", name_.c_str(), info.pid,
             info.cid);
       message.SetChannel(OnChannelOpen(message));
-      message.Reply(0);
-      return true;
+      return message.Reply(0);
     }
 
     case opcodes::CHANNEL_CLOSE: {
@@ -588,8 +601,7 @@
             info.cid);
       OnChannelClose(message, Channel::GetFromMessageInfo(info));
       message.SetChannel(nullptr);
-      message.Reply(0);
-      return true;
+      return message.Reply(0);
     }
 
     case opcodes::REPORT_SYSPROP_CHANGE:
@@ -597,8 +609,7 @@
             info.pid, info.cid);
       OnSysPropChange();
       android::report_sysprop_change();
-      message.Reply(0);
-      return true;
+      return message.Reply(0);
 
     case opcodes::DUMP_STATE: {
       ALOGD("%s:DUMP_STATE: pid=%d cid=%d\n", name_.c_str(), info.pid,
@@ -607,21 +618,20 @@
       const size_t response_size = response.size() < message.GetReceiveLength()
                                        ? response.size()
                                        : message.GetReceiveLength();
-      const ssize_t bytes_written =
+      const Status<size_t> status =
           message.Write(response.data(), response_size);
-      if (bytes_written < static_cast<ssize_t>(response_size))
-        message.ReplyError(EIO);
+      if (status && status.get() < response_size)
+        return message.ReplyError(EIO);
       else
-        message.Reply(bytes_written);
-      return true;
+        return message.Reply(status);
     }
 
     default:
-      return false;
+      return ErrorStatus{EOPNOTSUPP};
   }
 }
 
-int Service::DefaultHandleMessage(Message& message) {
+Status<void> Service::DefaultHandleMessage(Message& message) {
   const MessageInfo& info = message.GetInfo();
 
   ALOGD_IF(TRACE, "Service::DefaultHandleMessage: pid=%d cid=%d op=%d\n",
@@ -632,23 +642,21 @@
     case opcodes::CHANNEL_CLOSE:
     case opcodes::REPORT_SYSPROP_CHANGE:
     case opcodes::DUMP_STATE:
-      HandleSystemMessage(message);
-      return 0;
+      return HandleSystemMessage(message);
 
     default:
-      return message.ReplyError(ENOTSUP);
+      return message.ReplyError(EOPNOTSUPP);
   }
 }
 
 void Service::OnSysPropChange() {}
 
-int Service::ReceiveAndDispatch() {
-  ErrnoGuard errno_guard;
+Status<void> Service::ReceiveAndDispatch() {
   Message message;
-  const int ret = endpoint_->MessageReceive(&message);
-  if (ret < 0) {
-    ALOGE("Failed to receive message: %s\n", strerror(errno));
-    return ReturnCodeOrError(ret);
+  const auto status = endpoint_->MessageReceive(&message);
+  if (!status) {
+    ALOGE("Failed to receive message: %s\n", status.GetErrorMessage().c_str());
+    return status;
   }
 
   std::shared_ptr<Service> service = message.GetService();
@@ -657,24 +665,20 @@
     ALOGE("Service::ReceiveAndDispatch: service context is NULL!!!\n");
     // Don't block the sender indefinitely in this error case.
     endpoint_->MessageReply(&message, -EINVAL);
-    return -EINVAL;
+    return ErrorStatus{EINVAL};
   }
 
   if (message.IsImpulse()) {
     service->HandleImpulse(message);
-    return 0;
+    return {};
   } else if (service->HandleSystemMessage(message)) {
-    return 0;
+    return {};
   } else {
     return service->HandleMessage(message);
   }
 }
 
-int Service::Cancel() {
-  ErrnoGuard errno_guard;
-  const int ret = endpoint_->Cancel();
-  return ReturnCodeOrError(ret);
-}
+Status<void> Service::Cancel() { return endpoint_->Cancel(); }
 
 }  // namespace pdx
 }  // namespace android
diff --git a/libs/vr/libpdx/service_tests.cpp b/libs/vr/libpdx/service_tests.cpp
index fc0c8db..c7412b7 100644
--- a/libs/vr/libpdx/service_tests.cpp
+++ b/libs/vr/libpdx/service_tests.cpp
@@ -30,7 +30,6 @@
 using testing::Ref;
 using testing::Return;
 using testing::SetArgPointee;
-using testing::SetErrnoAndReturn;
 using testing::WithArg;
 using testing::WithoutArgs;
 using testing::_;
@@ -91,7 +90,7 @@
   MOCK_METHOD1(OnChannelOpen, std::shared_ptr<Channel>(Message& message));
   MOCK_METHOD2(OnChannelClose,
                void(Message& message, const std::shared_ptr<Channel>& channel));
-  MOCK_METHOD1(HandleMessage, int(Message& message));
+  MOCK_METHOD1(HandleMessage, Status<void>(Message& message));
   MOCK_METHOD1(HandleImpulse, void(Message& impulse));
   MOCK_METHOD0(OnSysPropChange, void());
   MOCK_METHOD1(DumpState, std::string(size_t max_length));
@@ -101,7 +100,9 @@
  public:
   ServiceTest() {
     auto endpoint = std::make_unique<testing::StrictMock<MockEndpoint>>();
-    EXPECT_CALL(*endpoint, SetService(_)).Times(2).WillRepeatedly(Return(0));
+    EXPECT_CALL(*endpoint, SetService(_))
+        .Times(2)
+        .WillRepeatedly(Return(Status<void>{}));
     service_ = std::make_shared<MockService>("MockSvc", std::move(endpoint));
   }
 
@@ -134,7 +135,8 @@
   }
 
   void ExpectDefaultHandleMessage() {
-    EXPECT_CALL(*endpoint(), DefaultHandleMessage(_));
+    EXPECT_CALL(*endpoint(), MessageReply(_, -EOPNOTSUPP))
+        .WillOnce(Return(Status<void>{}));
   }
 
   std::shared_ptr<MockService> service_;
@@ -222,10 +224,11 @@
   auto channel = std::make_shared<Channel>();
   EXPECT_CALL(*service_, OnChannelOpen(Ref(message))).WillOnce(Return(channel));
   EXPECT_CALL(*endpoint(), SetChannel(kTestCid, channel.get()))
-      .WillOnce(Return(0));
-  EXPECT_CALL(*endpoint(), MessageReply(&message, 0)).WillOnce(Return(0));
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_CALL(*endpoint(), MessageReply(&message, 0))
+      .WillOnce(Return(Status<void>{}));
 
-  EXPECT_EQ(0, service_->Service::HandleMessage(message));
+  EXPECT_TRUE(service_->Service::HandleMessage(message));
 }
 
 TEST_F(ServiceTest, HandleMessageChannelClose) {
@@ -237,10 +240,12 @@
   Message message{info};
 
   EXPECT_CALL(*service_, OnChannelClose(Ref(message), channel));
-  EXPECT_CALL(*endpoint(), SetChannel(kTestCid, nullptr)).WillOnce(Return(0));
-  EXPECT_CALL(*endpoint(), MessageReply(&message, 0)).WillOnce(Return(0));
+  EXPECT_CALL(*endpoint(), SetChannel(kTestCid, nullptr))
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_CALL(*endpoint(), MessageReply(&message, 0))
+      .WillOnce(Return(Status<void>{}));
 
-  EXPECT_EQ(0, service_->Service::HandleMessage(message));
+  EXPECT_TRUE(service_->Service::HandleMessage(message));
 }
 
 TEST_F(ServiceTest, HandleMessageOnSysPropChange) {
@@ -250,9 +255,10 @@
   Message message{info};
 
   EXPECT_CALL(*service_, OnSysPropChange());
-  EXPECT_CALL(*endpoint(), MessageReply(&message, 0)).WillOnce(Return(0));
+  EXPECT_CALL(*endpoint(), MessageReply(&message, 0))
+      .WillOnce(Return(Status<void>{}));
 
-  EXPECT_EQ(0, service_->Service::HandleMessage(message));
+  EXPECT_TRUE(service_->Service::HandleMessage(message));
 }
 
 TEST_F(ServiceTest, HandleMessageOnDumpState) {
@@ -270,9 +276,9 @@
       WriteMessageData(&message, IoVecDataMatcher(IoVecData{kReply}), 1))
       .WillOnce(Return(kReply.size()));
   EXPECT_CALL(*endpoint(), MessageReply(&message, kReply.size()))
-      .WillOnce(Return(0));
+      .WillOnce(Return(Status<void>{}));
 
-  EXPECT_EQ(0, service_->Service::HandleMessage(message));
+  EXPECT_TRUE(service_->Service::HandleMessage(message));
 }
 
 TEST_F(ServiceTest, HandleMessageOnDumpStateTooLarge) {
@@ -291,9 +297,9 @@
       WriteMessageData(&message, IoVecDataMatcher(IoVecData{kActualReply}), 1))
       .WillOnce(Return(kActualReply.size()));
   EXPECT_CALL(*endpoint(), MessageReply(&message, kActualReply.size()))
-      .WillOnce(Return(0));
+      .WillOnce(Return(Status<void>{}));
 
-  EXPECT_EQ(0, service_->Service::HandleMessage(message));
+  EXPECT_TRUE(service_->Service::HandleMessage(message));
 }
 
 TEST_F(ServiceTest, HandleMessageOnDumpStateFail) {
@@ -310,9 +316,10 @@
       *endpoint(),
       WriteMessageData(&message, IoVecDataMatcher(IoVecData{kReply}), 1))
       .WillOnce(Return(1));
-  EXPECT_CALL(*endpoint(), MessageReply(&message, -EIO)).WillOnce(Return(0));
+  EXPECT_CALL(*endpoint(), MessageReply(&message, -EIO))
+      .WillOnce(Return(Status<void>{}));
 
-  EXPECT_EQ(0, service_->Service::HandleMessage(message));
+  EXPECT_TRUE(service_->Service::HandleMessage(message));
 }
 
 TEST_F(ServiceTest, HandleMessageCustom) {
@@ -320,10 +327,10 @@
   SetupMessageInfoAndDefaultExpectations(&info, kTestOp);
   Message message{info};
 
-  EXPECT_CALL(*endpoint(), MessageReply(&message, -ENOTSUP))
-      .WillOnce(Return(0));
+  EXPECT_CALL(*endpoint(), MessageReply(&message, -EOPNOTSUPP))
+      .WillOnce(Return(Status<void>{}));
 
-  EXPECT_EQ(0, service_->Service::HandleMessage(message));
+  EXPECT_TRUE(service_->Service::HandleMessage(message));
 }
 
 TEST_F(ServiceTest, ReplyMessageWithoutService) {
@@ -337,7 +344,7 @@
   service_.reset();
   EXPECT_TRUE(message.IsServiceExpired());
 
-  EXPECT_EQ(-EINVAL, message.Reply(12));
+  EXPECT_EQ(EINVAL, message.Reply(12).error());
 }
 
 TEST_F(ServiceTest, ReceiveAndDispatchMessage) {
@@ -345,33 +352,33 @@
   SetupMessageInfoAndDefaultExpectations(&info, kTestOp);
   ExpectDefaultHandleMessage();
 
-  auto on_receive = [&info](Message* message) {
+  auto on_receive = [&info](Message* message) -> Status<void> {
     *message = Message{info};
-    return 0;
+    return {};
   };
   EXPECT_CALL(*endpoint(), MessageReceive(_)).WillOnce(Invoke(on_receive));
-  EXPECT_CALL(*service_, HandleMessage(_)).WillOnce(Return(0));
+  EXPECT_CALL(*service_, HandleMessage(_)).WillOnce(Return(Status<void>{}));
 
-  EXPECT_EQ(0, service_->ReceiveAndDispatch());
+  EXPECT_TRUE(service_->ReceiveAndDispatch());
 }
 
 TEST_F(ServiceTest, ReceiveAndDispatchImpulse) {
   MessageInfo info;
   SetupMessageInfoAndDefaultExpectations(&info, kTestOp, true);
 
-  auto on_receive = [&info](Message* message) {
+  auto on_receive = [&info](Message* message) -> Status<void> {
     *message = Message{info};
-    return 0;
+    return {};
   };
   EXPECT_CALL(*endpoint(), MessageReceive(_)).WillOnce(Invoke(on_receive));
   EXPECT_CALL(*service_, HandleImpulse(_));
 
-  EXPECT_EQ(0, service_->ReceiveAndDispatch());
+  EXPECT_TRUE(service_->ReceiveAndDispatch());
 }
 
 TEST_F(ServiceTest, Cancel) {
-  EXPECT_CALL(*endpoint(), Cancel()).WillOnce(Return(0));
-  EXPECT_EQ(0, service_->Cancel());
+  EXPECT_CALL(*endpoint(), Cancel()).WillOnce(Return(Status<void>{}));
+  EXPECT_TRUE(service_->Cancel());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -380,85 +387,85 @@
 
 TEST_F(ServiceMessageTest, Reply) {
   EXPECT_CALL(*endpoint(), MessageReply(message_.get(), 12))
-      .WillOnce(Return(0));
+      .WillOnce(Return(Status<void>{}));
   EXPECT_FALSE(message_->replied());
-  EXPECT_EQ(0, message_->Reply(12));
+  EXPECT_TRUE(message_->Reply(12));
   EXPECT_TRUE(message_->replied());
 
-  EXPECT_EQ(-EINVAL, message_->Reply(12));  // Already replied.
+  EXPECT_EQ(EINVAL, message_->Reply(12).error());  // Already replied.
 }
 
 TEST_F(ServiceMessageTest, ReplyFail) {
   EXPECT_CALL(*endpoint(), MessageReply(message_.get(), 12))
-      .WillOnce(SetErrnoAndReturn(EIO, -1));
-  EXPECT_EQ(-EIO, message_->Reply(12));
+      .WillOnce(Return(ErrorStatus{EIO}));
+  EXPECT_EQ(EIO, message_->Reply(12).error());
 
   ExpectDefaultHandleMessage();
 }
 
 TEST_F(ServiceMessageTest, ReplyError) {
   EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -12))
-      .WillOnce(Return(0));
-  EXPECT_EQ(0, message_->ReplyError(12));
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_TRUE(message_->ReplyError(12));
 }
 
 TEST_F(ServiceMessageTest, ReplyFileDescriptor) {
   EXPECT_CALL(*endpoint(), MessageReplyFd(message_.get(), 5))
-      .WillOnce(Return(0));
-  EXPECT_EQ(0, message_->ReplyFileDescriptor(5));
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_TRUE(message_->ReplyFileDescriptor(5));
 }
 
 TEST_F(ServiceMessageTest, ReplyLocalFileHandle) {
   const int kFakeFd = 12345;
   LocalHandle handle{kFakeFd};
   EXPECT_CALL(*endpoint(), MessageReplyFd(message_.get(), kFakeFd))
-      .WillOnce(Return(0));
-  EXPECT_EQ(0, message_->Reply(handle));
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_TRUE(message_->Reply(handle));
   handle.Release();  // Make sure we do not close the fake file descriptor.
 }
 
 TEST_F(ServiceMessageTest, ReplyLocalFileHandleError) {
   LocalHandle handle{-EINVAL};
   EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -EINVAL))
-      .WillOnce(Return(0));
-  EXPECT_EQ(0, message_->Reply(handle));
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_TRUE(message_->Reply(handle));
 }
 
 TEST_F(ServiceMessageTest, ReplyBorrowedFileHandle) {
   const int kFakeFd = 12345;
   BorrowedHandle handle{kFakeFd};
   EXPECT_CALL(*endpoint(), MessageReplyFd(message_.get(), kFakeFd))
-      .WillOnce(Return(0));
-  EXPECT_EQ(0, message_->Reply(handle));
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_TRUE(message_->Reply(handle));
 }
 
 TEST_F(ServiceMessageTest, ReplyBorrowedFileHandleError) {
   BorrowedHandle handle{-EACCES};
   EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -EACCES))
-      .WillOnce(Return(0));
-  EXPECT_EQ(0, message_->Reply(handle));
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_TRUE(message_->Reply(handle));
 }
 
 TEST_F(ServiceMessageTest, ReplyRemoteFileHandle) {
   RemoteHandle handle{123};
   EXPECT_CALL(*endpoint(), MessageReply(message_.get(), handle.Get()))
-      .WillOnce(Return(0));
-  EXPECT_EQ(0, message_->Reply(handle));
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_TRUE(message_->Reply(handle));
 }
 
 TEST_F(ServiceMessageTest, ReplyRemoteFileHandleError) {
   RemoteHandle handle{-EIO};
   EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -EIO))
-      .WillOnce(Return(0));
-  EXPECT_EQ(0, message_->Reply(handle));
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_TRUE(message_->Reply(handle));
 }
 
 TEST_F(ServiceMessageTest, ReplyLocalChannelHandle) {
   LocalChannelHandle handle{nullptr, 12345};
   EXPECT_CALL(*endpoint(), MessageReplyChannelHandle(
                                message_.get(), A<const LocalChannelHandle&>()))
-      .WillOnce(Return(0));
-  EXPECT_EQ(0, message_->Reply(handle));
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_TRUE(message_->Reply(handle));
 }
 
 TEST_F(ServiceMessageTest, ReplyBorrowedChannelHandle) {
@@ -466,30 +473,30 @@
   EXPECT_CALL(*endpoint(),
               MessageReplyChannelHandle(message_.get(),
                                         A<const BorrowedChannelHandle&>()))
-      .WillOnce(Return(0));
-  EXPECT_EQ(0, message_->Reply(handle));
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_TRUE(message_->Reply(handle));
 }
 
 TEST_F(ServiceMessageTest, ReplyRemoteChannelHandle) {
   RemoteChannelHandle handle{12345};
   EXPECT_CALL(*endpoint(), MessageReplyChannelHandle(
                                message_.get(), A<const RemoteChannelHandle&>()))
-      .WillOnce(Return(0));
-  EXPECT_EQ(0, message_->Reply(handle));
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_TRUE(message_->Reply(handle));
 }
 
 TEST_F(ServiceMessageTest, ReplyStatusInt) {
   Status<int> status{123};
   EXPECT_CALL(*endpoint(), MessageReply(message_.get(), status.get()))
-      .WillOnce(Return(0));
-  EXPECT_EQ(0, message_->Reply(status));
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_TRUE(message_->Reply(status));
 }
 
 TEST_F(ServiceMessageTest, ReplyStatusError) {
   Status<int> status{ErrorStatus{EIO}};
   EXPECT_CALL(*endpoint(), MessageReply(message_.get(), -status.error()))
-      .WillOnce(Return(0));
-  EXPECT_EQ(0, message_->Reply(status));
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_TRUE(message_->Reply(status));
 }
 
 TEST_F(ServiceMessageTest, Read) {
@@ -500,9 +507,9 @@
       *endpoint(),
       ReadMessageData(message_.get(), IoVecMatcher(kDataBuffer, kDataSize), 1))
       .WillOnce(Return(50))
-      .WillOnce(SetErrnoAndReturn(EACCES, -1));
-  EXPECT_EQ(50, message_->Read(kDataBuffer, kDataSize));
-  EXPECT_EQ(-EACCES, message_->Read(kDataBuffer, kDataSize));
+      .WillOnce(Return(ErrorStatus{EACCES}));
+  EXPECT_EQ(50u, message_->Read(kDataBuffer, kDataSize).get());
+  EXPECT_EQ(EACCES, message_->Read(kDataBuffer, kDataSize).error());
 }
 
 TEST_F(ServiceMessageTest, ReadVector) {
@@ -516,10 +523,10 @@
                   IoVecMatcher(IoVecArray{std::begin(vec), std::end(vec)}), 2))
       .WillOnce(Return(30))
       .WillOnce(Return(15))
-      .WillOnce(SetErrnoAndReturn(EBADF, -1));
-  EXPECT_EQ(30, message_->ReadVector(vec, 2));
-  EXPECT_EQ(15, message_->ReadVector(vec));
-  EXPECT_EQ(-EBADF, message_->ReadVector(vec));
+      .WillOnce(Return(ErrorStatus{EBADF}));
+  EXPECT_EQ(30u, message_->ReadVector(vec, 2).get());
+  EXPECT_EQ(15u, message_->ReadVector(vec).get());
+  EXPECT_EQ(EBADF, message_->ReadVector(vec).error());
 }
 
 TEST_F(ServiceMessageTest, Write) {
@@ -530,9 +537,9 @@
       *endpoint(),
       WriteMessageData(message_.get(), IoVecMatcher(kDataBuffer, kDataSize), 1))
       .WillOnce(Return(50))
-      .WillOnce(SetErrnoAndReturn(EBADMSG, -1));
-  EXPECT_EQ(50, message_->Write(kDataBuffer, kDataSize));
-  EXPECT_EQ(-EBADMSG, message_->Write(kDataBuffer, kDataSize));
+      .WillOnce(Return(ErrorStatus{EBADMSG}));
+  EXPECT_EQ(50u, message_->Write(kDataBuffer, kDataSize).get());
+  EXPECT_EQ(EBADMSG, message_->Write(kDataBuffer, kDataSize).error());
 }
 
 TEST_F(ServiceMessageTest, WriteVector) {
@@ -546,10 +553,10 @@
                   IoVecMatcher(IoVecArray{std::begin(vec), std::end(vec)}), 2))
       .WillOnce(Return(30))
       .WillOnce(Return(15))
-      .WillOnce(SetErrnoAndReturn(EIO, -1));
-  EXPECT_EQ(30, message_->WriteVector(vec, 2));
-  EXPECT_EQ(15, message_->WriteVector(vec));
-  EXPECT_EQ(-EIO, message_->WriteVector(vec, 2));
+      .WillOnce(Return(ErrorStatus{EIO}));
+  EXPECT_EQ(30u, message_->WriteVector(vec, 2).get());
+  EXPECT_EQ(15u, message_->WriteVector(vec).get());
+  EXPECT_EQ(EIO, message_->WriteVector(vec, 2).error());
 }
 
 TEST_F(ServiceMessageTest, PushLocalFileHandle) {
@@ -560,9 +567,9 @@
               PushFileHandle(message_.get(), Matcher<const LocalHandle&>(
                                                  FileHandleMatcher(kFakeFd))))
       .WillOnce(Return(12))
-      .WillOnce(SetErrnoAndReturn(EIO, -1));
-  EXPECT_EQ(12, message_->PushFileHandle(handle));
-  EXPECT_EQ(-EIO, message_->PushFileHandle(handle));
+      .WillOnce(Return(ErrorStatus{EIO}));
+  EXPECT_EQ(12, message_->PushFileHandle(handle).get());
+  EXPECT_EQ(EIO, message_->PushFileHandle(handle).error());
   handle.Release();  // Make sure we do not close the fake file descriptor.
 }
 
@@ -574,9 +581,9 @@
               PushFileHandle(message_.get(), Matcher<const BorrowedHandle&>(
                                                  FileHandleMatcher(kFakeFd))))
       .WillOnce(Return(13))
-      .WillOnce(SetErrnoAndReturn(EACCES, -1));
-  EXPECT_EQ(13, message_->PushFileHandle(handle));
-  EXPECT_EQ(-EACCES, message_->PushFileHandle(handle));
+      .WillOnce(Return(ErrorStatus{EACCES}));
+  EXPECT_EQ(13, message_->PushFileHandle(handle).get());
+  EXPECT_EQ(EACCES, message_->PushFileHandle(handle).error());
 }
 
 TEST_F(ServiceMessageTest, PushRemoteFileHandle) {
@@ -587,9 +594,9 @@
               PushFileHandle(message_.get(), Matcher<const RemoteHandle&>(
                                                  FileHandleMatcher(kFakeFd))))
       .WillOnce(Return(kFakeFd))
-      .WillOnce(SetErrnoAndReturn(EIO, -1));
-  EXPECT_EQ(kFakeFd, message_->PushFileHandle(handle));
-  EXPECT_EQ(-EIO, message_->PushFileHandle(handle));
+      .WillOnce(Return(ErrorStatus{EIO}));
+  EXPECT_EQ(kFakeFd, message_->PushFileHandle(handle).get());
+  EXPECT_EQ(EIO, message_->PushFileHandle(handle).error());
 }
 
 TEST_F(ServiceMessageTest, PushLocalChannelHandle) {
@@ -600,9 +607,9 @@
                                              Matcher<const LocalChannelHandle&>(
                                                  ChannelHandleMatcher(kValue))))
       .WillOnce(Return(7))
-      .WillOnce(SetErrnoAndReturn(EIO, -1));
-  EXPECT_EQ(7, message_->PushChannelHandle(handle));
-  EXPECT_EQ(-EIO, message_->PushChannelHandle(handle));
+      .WillOnce(Return(ErrorStatus{EIO}));
+  EXPECT_EQ(7, message_->PushChannelHandle(handle).get());
+  EXPECT_EQ(EIO, message_->PushChannelHandle(handle).error());
 }
 
 TEST_F(ServiceMessageTest, PushBorrowedChannelHandle) {
@@ -614,9 +621,9 @@
       PushChannelHandle(message_.get(), Matcher<const BorrowedChannelHandle&>(
                                             ChannelHandleMatcher(kValue))))
       .WillOnce(Return(8))
-      .WillOnce(SetErrnoAndReturn(EIO, -1));
-  EXPECT_EQ(8, message_->PushChannelHandle(handle));
-  EXPECT_EQ(-EIO, message_->PushChannelHandle(handle));
+      .WillOnce(Return(ErrorStatus{EIO}));
+  EXPECT_EQ(8, message_->PushChannelHandle(handle).get());
+  EXPECT_EQ(EIO, message_->PushChannelHandle(handle).error());
 }
 
 TEST_F(ServiceMessageTest, PushRemoteChannelHandle) {
@@ -628,9 +635,9 @@
       PushChannelHandle(message_.get(), Matcher<const RemoteChannelHandle&>(
                                             ChannelHandleMatcher(kValue))))
       .WillOnce(Return(kValue))
-      .WillOnce(SetErrnoAndReturn(EIO, -1));
-  EXPECT_EQ(kValue, message_->PushChannelHandle(handle));
-  EXPECT_EQ(-EIO, message_->PushChannelHandle(handle));
+      .WillOnce(Return(ErrorStatus{EIO}));
+  EXPECT_EQ(kValue, message_->PushChannelHandle(handle).get());
+  EXPECT_EQ(EIO, message_->PushChannelHandle(handle).error());
 }
 
 TEST_F(ServiceMessageTest, GetFileHandle) {
@@ -701,8 +708,8 @@
   int kClearMask = 1;
   int kSetMask = 2;
   EXPECT_CALL(*endpoint(), ModifyChannelEvents(kTestCid, kClearMask, kSetMask))
-      .WillOnce(Return(0));
-  EXPECT_EQ(0, message_->ModifyChannelEvents(kClearMask, kSetMask));
+      .WillOnce(Return(Status<void>{}));
+  EXPECT_TRUE(message_->ModifyChannelEvents(kClearMask, kSetMask));
 }
 
 TEST_F(ServiceMessageTest, PushChannelSameService) {
@@ -733,7 +740,9 @@
 TEST_F(ServiceMessageTest, PushChannelDifferentService) {
   ExpectDefaultHandleMessage();
   auto endpoint2 = std::make_unique<testing::StrictMock<MockEndpoint>>();
-  EXPECT_CALL(*endpoint2, SetService(_)).Times(2).WillRepeatedly(Return(0));
+  EXPECT_CALL(*endpoint2, SetService(_))
+      .Times(2)
+      .WillRepeatedly(Return(Status<void>{}));
   auto service2 =
       std::make_shared<MockService>("MockSvc2", std::move(endpoint2));
 
@@ -779,7 +788,9 @@
 TEST_F(ServiceMessageTest, CheckChannelDifferentService) {
   ExpectDefaultHandleMessage();
   auto endpoint2 = std::make_unique<testing::StrictMock<MockEndpoint>>();
-  EXPECT_CALL(*endpoint2, SetService(_)).Times(2).WillRepeatedly(Return(0));
+  EXPECT_CALL(*endpoint2, SetService(_))
+      .Times(2)
+      .WillRepeatedly(Return(Status<void>{}));
   auto service2 =
       std::make_shared<MockService>("MockSvc2", std::move(endpoint2));