libbinder: move interruptableReadOrWrite to new file

Moves interruptableReadOrWrite to a new RpcTransportUtils.h
file so it can be used by multiple transports.

Bug: 224644083
Test: m
Change-Id: Ife48519ab5c6a99d5fbbcd4ad9e6c3fe517dd0ba
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp
index 7cc58cd..51326f6 100644
--- a/libs/binder/RpcTransportRaw.cpp
+++ b/libs/binder/RpcTransportRaw.cpp
@@ -24,6 +24,7 @@
 
 #include "FdTrigger.h"
 #include "RpcState.h"
+#include "RpcTransportUtils.h"
 
 namespace android {
 
@@ -55,90 +56,6 @@
         return OK;
     }
 
-    template <typename SendOrReceive>
-    status_t interruptableReadOrWrite(
-            FdTrigger* fdTrigger, iovec* iovs, int niovs, SendOrReceive sendOrReceiveFun,
-            const char* funName, int16_t event,
-            const std::optional<android::base::function_ref<status_t()>>& altPoll) {
-        MAYBE_WAIT_IN_FLAKE_MODE;
-
-        if (niovs < 0) {
-            return BAD_VALUE;
-        }
-
-        // Since we didn't poll, we need to manually check to see if it was triggered. Otherwise, we
-        // may never know we should be shutting down.
-        if (fdTrigger->isTriggered()) {
-            return DEAD_OBJECT;
-        }
-
-        // If iovs has one or more empty vectors at the end and
-        // we somehow advance past all the preceding vectors and
-        // pass some or all of the empty ones to sendmsg/recvmsg,
-        // the call will return processSize == 0. In that case
-        // we should be returning OK but instead return DEAD_OBJECT.
-        // To avoid this problem, we make sure here that the last
-        // vector at iovs[niovs - 1] has a non-zero length.
-        while (niovs > 0 && iovs[niovs - 1].iov_len == 0) {
-            niovs--;
-        }
-        if (niovs == 0) {
-            // The vectors are all empty, so we have nothing to send.
-            return OK;
-        }
-
-        bool havePolled = false;
-        while (true) {
-            ssize_t processSize = sendOrReceiveFun(iovs, niovs);
-            if (processSize < 0) {
-                int savedErrno = errno;
-
-                // Still return the error on later passes, since it would expose
-                // a problem with polling
-                if (havePolled || (savedErrno != EAGAIN && savedErrno != EWOULDBLOCK)) {
-                    LOG_RPC_DETAIL("RpcTransport %s(): %s", funName, strerror(savedErrno));
-                    return -savedErrno;
-                }
-            } else if (processSize == 0) {
-                return DEAD_OBJECT;
-            } else {
-                while (processSize > 0 && niovs > 0) {
-                    auto& iov = iovs[0];
-                    if (static_cast<size_t>(processSize) < iov.iov_len) {
-                        // Advance the base of the current iovec
-                        iov.iov_base = reinterpret_cast<char*>(iov.iov_base) + processSize;
-                        iov.iov_len -= processSize;
-                        break;
-                    }
-
-                    // The current iovec was fully written
-                    processSize -= iov.iov_len;
-                    iovs++;
-                    niovs--;
-                }
-                if (niovs == 0) {
-                    LOG_ALWAYS_FATAL_IF(processSize > 0,
-                                        "Reached the end of iovecs "
-                                        "with %zd bytes remaining",
-                                        processSize);
-                    return OK;
-                }
-            }
-
-            if (altPoll) {
-                if (status_t status = (*altPoll)(); status != OK) return status;
-                if (fdTrigger->isTriggered()) {
-                    return DEAD_OBJECT;
-                }
-            } else {
-                if (status_t status = fdTrigger->triggerablePoll(mSocket.get(), event);
-                    status != OK)
-                    return status;
-                if (!havePolled) havePolled = true;
-            }
-        }
-    }
-
     status_t interruptableWriteFully(
             FdTrigger* fdTrigger, iovec* iovs, int niovs,
             const std::optional<android::base::function_ref<status_t()>>& altPoll,
@@ -198,7 +115,8 @@
             };
             return TEMP_FAILURE_RETRY(sendmsg(mSocket.get(), &msg, MSG_NOSIGNAL));
         };
-        return interruptableReadOrWrite(fdTrigger, iovs, niovs, send, "sendmsg", POLLOUT, altPoll);
+        return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, send, "sendmsg",
+                                        POLLOUT, altPoll);
     }
 
     status_t interruptableReadFully(
@@ -255,7 +173,8 @@
             };
             return TEMP_FAILURE_RETRY(recvmsg(mSocket.get(), &msg, MSG_NOSIGNAL));
         };
-        return interruptableReadOrWrite(fdTrigger, iovs, niovs, recv, "recvmsg", POLLIN, altPoll);
+        return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, recv, "recvmsg",
+                                        POLLIN, altPoll);
     }
 
 private: