Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ffb12091 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "[rpc_binder] Implement RPC binder over init-managed Unix domain socket" am: 21345446

parents 68258abb 21345446
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -501,6 +501,7 @@ cc_library {
        "libbase",
        "libbinder",
        "libbinder_ndk",
        "libcutils_sockets",
        "liblog",
        "libutils",
    ],
+23 −0
Original line number Diff line number Diff line
@@ -564,6 +564,29 @@ status_t RpcServer::setupSocketServer(const RpcSocketAddress& addr) {
    return OK;
}

status_t RpcServer::setupRawSocketServer(base::unique_fd socket_fd) {
    RpcTransportFd transportFd(std::move(socket_fd));
    if (!transportFd.fd.ok()) {
        int savedErrno = errno;
        ALOGE("Could not get initialized Unix socket: %s", strerror(savedErrno));
        return -savedErrno;
    }
    // Right now, we create all threads at once, making accept4 slow. To avoid hanging the client,
    // the backlog is increased to a large number.
    // TODO(b/189955605): Once we create threads dynamically & lazily, the backlog can be reduced
    //  to 1.
    if (0 != TEMP_FAILURE_RETRY(listen(transportFd.fd.get(), 50 /*backlog*/))) {
        int savedErrno = errno;
        ALOGE("Could not listen initialized Unix socket: %s", strerror(savedErrno));
        return -savedErrno;
    }
    if (status_t status = setupExternalServer(std::move(transportFd.fd)); status != OK) {
        ALOGE("Another thread has set up server while calling setupSocketServer. Race?");
        return status;
    }
    return OK;
}

void RpcServer::onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) {
    const std::vector<uint8_t>& id = session->mId;
    LOG_ALWAYS_FATAL_IF(id.empty(), "Server sessions must be initialized with ID");
+10 −0
Original line number Diff line number Diff line
@@ -70,6 +70,16 @@ public:
     */
    [[nodiscard]] status_t setupUnixDomainServer(const char* path);

    /**
     * Sets up an RPC server with a raw socket file descriptor.
     * The socket should be created and bound to a socket address already, e.g.
     * the socket can be created in init.rc.
     *
     * This method is used in the libbinder_rpc_unstable API
     * RunInitUnixDomainRpcServer().
     */
    [[nodiscard]] status_t setupRawSocketServer(base::unique_fd socket_fd);

    /**
     * Creates an RPC server at the current port.
     */
+14 −0
Original line number Diff line number Diff line
@@ -42,6 +42,20 @@ bool RunVsockRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* c

AIBinder* VsockRpcClient(unsigned int cid, unsigned int port);

// Starts a Unix domain RPC server with a given init-managed Unix domain `name` and
// a given root IBinder object.
// The socket should be created in init.rc with the same `name`.
//
// This function sets up the server, calls readyCallback with a given param, and
// then joins before returning.
bool RunInitUnixDomainRpcServer(AIBinder* service, const char* name,
                                void (*readyCallback)(void* param), void* param);

// Gets the service via the RPC binder with Unix domain socket with the given
// Unix socket `name`.
// The final Unix domain socket path name is /dev/socket/`name`.
AIBinder* UnixDomainRpcClient(const char* name);

// Connect to an RPC server with preconnected file descriptors.
//
// requestFd should connect to the server and return a valid file descriptor, or
+38 −7
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <android/binder_libbinder.h>
#include <binder/RpcServer.h>
#include <binder/RpcSession.h>
#include <cutils/sockets.h>
#include <linux/vm_sockets.h>

using android::OK;
@@ -30,6 +31,17 @@ using android::base::unique_fd;

extern "C" {

void RunRpcServer(android::sp<RpcServer>& server, AIBinder* service,
                  void (*readyCallback)(void* param), void* param) {
    server->setRootObject(AIBinder_toPlatformBinder(service));

    if (readyCallback) readyCallback(param);
    server->join();

    // Shutdown any open sessions since server failed.
    (void)server->shutdown();
}

bool RunVsockRpcServerWithFactory(AIBinder* (*factory)(unsigned int cid, void* context),
                                  void* factoryContext, unsigned int port) {
    auto server = RpcServer::make();
@@ -60,13 +72,7 @@ bool RunVsockRpcServerCallback(AIBinder* service, unsigned int port,
                   << " error: " << statusToString(status).c_str();
        return false;
    }
    server->setRootObject(AIBinder_toPlatformBinder(service));

    if (readyCallback) readyCallback(param);
    server->join();

    // Shutdown any open sessions since server failed.
    (void)server->shutdown();
    RunRpcServer(server, service, readyCallback, param);
    return true;
}

@@ -84,6 +90,31 @@ AIBinder* VsockRpcClient(unsigned int cid, unsigned int port) {
    return AIBinder_fromPlatformBinder(session->getRootObject());
}

bool RunInitUnixDomainRpcServer(AIBinder* service, const char* name,
                                void (*readyCallback)(void* param), void* param) {
    auto server = RpcServer::make();
    auto fd = unique_fd(android_get_control_socket(name));
    if (status_t status = server->setupRawSocketServer(std::move(fd)); status != OK) {
        LOG(ERROR) << "Failed to set up Unix Domain RPC server with name " << name
                   << " error: " << statusToString(status).c_str();
        return false;
    }
    RunRpcServer(server, service, readyCallback, param);
    return true;
}

AIBinder* UnixDomainRpcClient(const char* name) {
    std::string pathname(name);
    pathname = ANDROID_SOCKET_DIR "/" + pathname;
    auto session = RpcSession::make();
    if (status_t status = session->setupUnixDomainClient(pathname.c_str()); status != OK) {
        LOG(ERROR) << "Failed to set up Unix Domain RPC client with path: " << pathname
                   << " error: " << statusToString(status).c_str();
        return nullptr;
    }
    return AIBinder_fromPlatformBinder(session->getRootObject());
}

AIBinder* RpcPreconnectedClient(int (*requestFd)(void* param), void* param) {
    auto session = RpcSession::make();
    auto request = [=] { return unique_fd{requestFd(param)}; };
Loading