Merge changes from topic "binder_rpc_test_ephermeral_port"

* changes:
  binderRpcTest: pick ephermeral port
  setupInetServer also returns port
diff --git a/libs/binder/RpcConnection.cpp b/libs/binder/RpcConnection.cpp
index f2302f7..2502d1b 100644
--- a/libs/binder/RpcConnection.cpp
+++ b/libs/binder/RpcConnection.cpp
@@ -19,6 +19,7 @@
 #include <binder/RpcConnection.h>
 
 #include <arpa/inet.h>
+#include <inttypes.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <sys/socket.h>
@@ -45,9 +46,55 @@
 
 namespace android {
 
+using base::borrowed_fd;
 using base::unique_fd;
 using AddrInfo = std::unique_ptr<addrinfo, decltype(&freeaddrinfo)>;
 
+namespace {
+bool checkSockaddrSize(const char* name, size_t actual, size_t expected) {
+    if (actual >= expected) return true;
+    ALOGW("getSockaddrPort: family is %s but size is %zu < %zu", name, actual, expected);
+    return false;
+}
+
+// Get the port number of |storage| for certain families. Requires storage->sa_family to be
+// set to a known family; otherwise, return nullopt.
+std::optional<unsigned int> getSockaddrPort(const sockaddr* storage, socklen_t len) {
+    switch (storage->sa_family) {
+        case AF_INET: {
+            if (!checkSockaddrSize("INET", len, sizeof(sockaddr_in))) return std::nullopt;
+            auto inetStorage = reinterpret_cast<const sockaddr_in*>(storage);
+            return ntohs(inetStorage->sin_port);
+        }
+        default: {
+            uint16_t family = storage->sa_family;
+            ALOGW("Don't know how to infer port for family %" PRIu16, family);
+            return std::nullopt;
+        }
+    }
+}
+
+std::optional<unsigned int> getSocketPort(borrowed_fd socketfd,
+                                          const RpcConnection::SocketAddress& socketAddress) {
+    sockaddr_storage storage{};
+    socklen_t len = sizeof(storage);
+    auto storagePtr = reinterpret_cast<sockaddr*>(&storage);
+    if (0 != getsockname(socketfd.get(), storagePtr, &len)) {
+        int savedErrno = errno;
+        ALOGE("Could not getsockname at %s: %s", socketAddress.toString().c_str(),
+              strerror(savedErrno));
+        return std::nullopt;
+    }
+
+    // getsockname does not fill in family, but getSockaddrPort() needs it.
+    if (storage.ss_family == AF_UNSPEC) {
+        storage.ss_family = socketAddress.addr()->sa_family;
+    }
+    return getSockaddrPort(storagePtr, len);
+}
+
+} // namespace
+
 RpcConnection::SocketAddress::~SocketAddress() {}
 
 RpcConnection::RpcConnection() {
@@ -166,14 +213,27 @@
     return AddrInfo(aiStart, &freeaddrinfo);
 }
 
-bool RpcConnection::setupInetServer(unsigned int port) {
+bool RpcConnection::setupInetServer(unsigned int port, unsigned int* assignedPort) {
     const char* kAddr = "127.0.0.1";
 
+    if (assignedPort != nullptr) *assignedPort = 0;
     auto aiStart = GetAddrInfo(kAddr, port);
     if (aiStart == nullptr) return false;
     for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) {
         InetSocketAddress socketAddress(ai->ai_addr, ai->ai_addrlen, kAddr, port);
-        if (setupSocketServer(socketAddress)) return true;
+        if (!setupSocketServer(socketAddress)) {
+            continue;
+        }
+        auto realPort = getSocketPort(mServer.get(), socketAddress);
+        LOG_ALWAYS_FATAL_IF(!realPort.has_value(), "Unable to get port number after setting up %s",
+                            socketAddress.toString().c_str());
+        LOG_ALWAYS_FATAL_IF(port != 0 && *realPort != port,
+                            "Requesting inet server on %s but it is set up on %u.",
+                            socketAddress.toString().c_str(), *realPort);
+        if (assignedPort != nullptr) {
+            *assignedPort = *realPort;
+        }
+        return true;
     }
     ALOGE("None of the socket address resolved for %s:%u can be set up as inet server.", kAddr,
           port);
diff --git a/libs/binder/include/binder/RpcConnection.h b/libs/binder/include/binder/RpcConnection.h
index 2395e78..09aed13 100644
--- a/libs/binder/include/binder/RpcConnection.h
+++ b/libs/binder/include/binder/RpcConnection.h
@@ -74,9 +74,15 @@
 #endif // __BIONIC__
 
     /**
-     * Creates an RPC server at the current port.
+     * Creates an RPC server at the current port using IPv4.
+     *
+     * TODO(b/182914638): IPv6 support
+     *
+     * Set |port| to 0 to pick an ephemeral port; see discussion of
+     * /proc/sys/net/ipv4/ip_local_port_range in ip(7). In this case, |assignedPort|
+     * will be set to the picked port number, if it is not null.
      */
-    [[nodiscard]] bool setupInetServer(unsigned int port);
+    [[nodiscard]] bool setupInetServer(unsigned int port, unsigned int* assignedPort);
 
     /**
      * Connects to an RPC server at the given address and port.
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index dd68fdb..ce69ea2 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -17,6 +17,7 @@
 #include <BnBinderRpcSession.h>
 #include <BnBinderRpcTest.h>
 #include <aidl/IBinderRpcTest.h>
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android/binder_auto_utils.h>
 #include <android/binder_libbinder.h>
@@ -176,14 +177,27 @@
 };
 sp<IBinder> MyBinderRpcTest::mHeldBinder;
 
+class Pipe {
+public:
+    Pipe() { CHECK(android::base::Pipe(&mRead, &mWrite)); }
+    Pipe(Pipe&&) = default;
+    android::base::borrowed_fd readEnd() { return mRead; }
+    android::base::borrowed_fd writeEnd() { return mWrite; }
+
+private:
+    android::base::unique_fd mRead;
+    android::base::unique_fd mWrite;
+};
+
 class Process {
 public:
-    Process(const std::function<void()>& f) {
+    Process(Process&&) = default;
+    Process(const std::function<void(Pipe*)>& f) {
         if (0 == (mPid = fork())) {
             // racey: assume parent doesn't crash before this is set
             prctl(PR_SET_PDEATHSIG, SIGHUP);
 
-            f();
+            f(&mPipe);
         }
     }
     ~Process() {
@@ -191,9 +205,11 @@
             kill(mPid, SIGKILL);
         }
     }
+    Pipe* getPipe() { return &mPipe; }
 
 private:
     pid_t mPid = 0;
+    Pipe mPipe;
 };
 
 static std::string allocateSocketAddress() {
@@ -215,6 +231,7 @@
     // whether connection should be invalidated by end of run
     bool expectInvalid = false;
 
+    ProcessConnection(ProcessConnection&&) = default;
     ~ProcessConnection() {
         rootBinder = nullptr;
         EXPECT_NE(nullptr, connection);
@@ -238,6 +255,7 @@
     // pre-casted root object
     sp<IBinderRpcTest> rootIface;
 
+    BinderRpcTestProcessConnection(BinderRpcTestProcessConnection&&) = default;
     ~BinderRpcTestProcessConnection() {
         if (!proc.expectInvalid) {
             int32_t remoteBinders = 0;
@@ -286,11 +304,11 @@
 
         std::string addr = allocateSocketAddress();
         unlink(addr.c_str());
-        static unsigned int port = 3456;
-        port++;
+        static unsigned int vsockPort = 3456;
+        vsockPort++;
 
         auto ret = ProcessConnection{
-                .host = Process([&] {
+                .host = Process([&](Pipe* pipe) {
                     sp<RpcServer> server = RpcServer::make();
 
                     server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
@@ -304,12 +322,17 @@
                             break;
 #ifdef __BIONIC__
                         case SocketType::VSOCK:
-                            CHECK(connection->setupVsockServer(port));
+                            CHECK(connection->setupVsockServer(vsockPort));
                             break;
 #endif // __BIONIC__
-                        case SocketType::INET:
-                            CHECK(connection->setupInetServer(port));
+                        case SocketType::INET: {
+                            unsigned int outPort = 0;
+                            CHECK(connection->setupInetServer(0, &outPort));
+                            CHECK_NE(0, outPort);
+                            CHECK(android::base::WriteFully(pipe->writeEnd(), &outPort,
+                                                            sizeof(outPort)));
                             break;
+                        }
                         default:
                             LOG_ALWAYS_FATAL("Unknown socket type");
                     }
@@ -327,6 +350,13 @@
                 .connection = RpcConnection::make(),
         };
 
+        unsigned int inetPort = 0;
+        if (socketType == SocketType::INET) {
+            CHECK(android::base::ReadFully(ret.host.getPipe()->readEnd(), &inetPort,
+                                           sizeof(inetPort)));
+            CHECK_NE(0, inetPort);
+        }
+
         // create remainder of connections
         for (size_t i = 0; i < numThreads; i++) {
             for (size_t tries = 0; tries < 5; tries++) {
@@ -337,11 +367,12 @@
                         break;
 #ifdef __BIONIC__
                     case SocketType::VSOCK:
-                        if (ret.connection->addVsockClient(VMADDR_CID_LOCAL, port)) goto success;
+                        if (ret.connection->addVsockClient(VMADDR_CID_LOCAL, vsockPort))
+                            goto success;
                         break;
 #endif // __BIONIC__
                     case SocketType::INET:
-                        if (ret.connection->addInetClient("127.0.0.1", port)) goto success;
+                        if (ret.connection->addInetClient("127.0.0.1", inetPort)) goto success;
                         break;
                     default:
                         LOG_ALWAYS_FATAL("Unknown socket type");