Loading libs/binder/RpcConnection.cpp +104 −54 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <binder/Parcel.h> #include <binder/Parcel.h> #include <binder/Stability.h> #include <binder/Stability.h> #include <utils/String8.h> #include "RpcState.h" #include "RpcState.h" #include "RpcWireFormat.h" #include "RpcWireFormat.h" Loading @@ -29,14 +30,20 @@ #include <sys/un.h> #include <sys/un.h> #include <unistd.h> #include <unistd.h> #if defined(__GLIBC__) #ifdef __GLIBC__ extern "C" pid_t gettid(); extern "C" pid_t gettid(); #endif #endif #ifdef __BIONIC__ #include <linux/vm_sockets.h> #endif namespace android { namespace android { using base::unique_fd; using base::unique_fd; RpcConnection::SocketAddress::~SocketAddress() {} RpcConnection::RpcConnection() { RpcConnection::RpcConnection() { LOG_RPC_DETAIL("RpcConnection created %p", this); LOG_RPC_DETAIL("RpcConnection created %p", this); Loading @@ -50,65 +57,68 @@ sp<RpcConnection> RpcConnection::make() { return new RpcConnection; return new RpcConnection; } } bool RpcConnection::setupUnixDomainServer(const char* path) { class UnixSocketAddress : public RpcConnection::SocketAddress { LOG_ALWAYS_FATAL_IF(mServer.get() != -1, "Only supports one server now"); public: explicit UnixSocketAddress(const char* path) : mAddr({.sun_family = AF_UNIX}) { unique_fd serverFd(TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0))); unsigned int pathLen = strlen(path) + 1; if (serverFd == -1) { LOG_ALWAYS_FATAL_IF(pathLen > sizeof(mAddr.sun_path), "%u %s", pathLen, path); ALOGE("Could not create socket at %s: %s", path, strerror(errno)); memcpy(mAddr.sun_path, path, pathLen); return false; } virtual ~UnixSocketAddress() {} std::string toString() const override { return String8::format("path '%.*s'", static_cast<int>(sizeof(mAddr.sun_path)), mAddr.sun_path) .c_str(); } } const sockaddr* addr() const override { return reinterpret_cast<const sockaddr*>(&mAddr); } size_t addrSize() const override { return sizeof(mAddr); } struct sockaddr_un addr = { private: .sun_family = AF_UNIX, sockaddr_un mAddr; }; }; unsigned int pathLen = strlen(path) + 1; bool RpcConnection::setupUnixDomainServer(const char* path) { LOG_ALWAYS_FATAL_IF(pathLen > sizeof(addr.sun_path), "%u", pathLen); return addServer(UnixSocketAddress(path)); memcpy(addr.sun_path, path, pathLen); if (0 != TEMP_FAILURE_RETRY(bind(serverFd.get(), (struct sockaddr*)&addr, sizeof(addr)))) { ALOGE("Could not bind socket at %s: %s", path, strerror(errno)); return false; } if (0 != TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/))) { ALOGE("Could not listen socket at %s: %s", path, strerror(errno)); return false; } } mServer = std::move(serverFd); bool RpcConnection::addUnixDomainClient(const char* path) { return true; return addClient(UnixSocketAddress(path)); } } bool RpcConnection::addUnixDomainClient(const char* path) { #ifdef __BIONIC__ LOG_RPC_DETAIL("Connecting on path: %s", path); unique_fd serverFd(TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0))); class VsockSocketAddress : public RpcConnection::SocketAddress { if (serverFd == -1) { public: ALOGE("Could not create socket at %s: %s", path, strerror(errno)); VsockSocketAddress(unsigned int cid, unsigned int port) return false; : mAddr({ .svm_family = AF_VSOCK, .svm_port = port, .svm_cid = cid, }) {} virtual ~VsockSocketAddress() {} std::string toString() const override { return String8::format("cid %du port %du", mAddr.svm_cid, mAddr.svm_port).c_str(); } } const sockaddr* addr() const override { return reinterpret_cast<const sockaddr*>(&mAddr); } size_t addrSize() const override { return sizeof(mAddr); } struct sockaddr_un addr = { private: .sun_family = AF_UNIX, sockaddr_vm mAddr; }; }; unsigned int pathLen = strlen(path) + 1; bool RpcConnection::setupVsockServer(unsigned int port) { LOG_ALWAYS_FATAL_IF(pathLen > sizeof(addr.sun_path), "%u", pathLen); // realizing value w/ this type at compile time to avoid ubsan abort memcpy(addr.sun_path, path, pathLen); constexpr unsigned int kAnyCid = VMADDR_CID_ANY; if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), (struct sockaddr*)&addr, sizeof(addr)))) { return addServer(VsockSocketAddress(kAnyCid, port)); ALOGE("Could not connect socket at %s: %s", path, strerror(errno)); return false; } } LOG_RPC_DETAIL("Unix domain client with fd %d", serverFd.get()); bool RpcConnection::addVsockClient(unsigned int cid, unsigned int port) { return addClient(VsockSocketAddress(cid, port)); addClient(std::move(serverFd)); return true; } } #endif // __BIONIC__ sp<IBinder> RpcConnection::getRootObject() { sp<IBinder> RpcConnection::getRootObject() { ExclusiveSocket socket(this, SocketUse::CLIENT); ExclusiveSocket socket(this, SocketUse::CLIENT); return state()->getRootObject(socket.fd(), this); return state()->getRootObject(socket.fd(), this); Loading @@ -130,11 +140,8 @@ status_t RpcConnection::sendDecStrong(const RpcAddress& address) { void RpcConnection::join() { void RpcConnection::join() { // establish a connection // establish a connection { { struct sockaddr_un clientSa; unique_fd clientFd( socklen_t clientSaLen = sizeof(clientSa); TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, 0 /*length*/, SOCK_CLOEXEC))); unique_fd clientFd(TEMP_FAILURE_RETRY( accept4(mServer.get(), (struct sockaddr*)&clientSa, &clientSaLen, SOCK_CLOEXEC))); if (clientFd < 0) { if (clientFd < 0) { // If this log becomes confusing, should save more state from setupUnixDomainServer // If this log becomes confusing, should save more state from setupUnixDomainServer // in order to output here. // in order to output here. Loading @@ -144,7 +151,7 @@ void RpcConnection::join() { LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get()); LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get()); addServer(std::move(clientFd)); assignServerToThisThread(std::move(clientFd)); } } // We may not use the connection we just established (two threads might // We may not use the connection we just established (two threads might Loading @@ -170,14 +177,57 @@ wp<RpcServer> RpcConnection::server() { return mForServer; return mForServer; } } void RpcConnection::addClient(base::unique_fd&& fd) { bool RpcConnection::addServer(const SocketAddress& addr) { LOG_ALWAYS_FATAL_IF(mServer.get() != -1, "Each RpcConnection can only have one server."); unique_fd serverFd( TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0))); if (serverFd == -1) { ALOGE("Could not create socket: %s", strerror(errno)); return false; } if (0 != TEMP_FAILURE_RETRY(bind(serverFd.get(), addr.addr(), addr.addrSize()))) { int savedErrno = errno; ALOGE("Could not bind socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); return false; } if (0 != TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/))) { int savedErrno = errno; ALOGE("Could not listen socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); return false; } mServer = std::move(serverFd); return true; } bool RpcConnection::addClient(const SocketAddress& addr) { unique_fd serverFd( TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0))); if (serverFd == -1) { int savedErrno = errno; ALOGE("Could not create socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); return false; } if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) { int savedErrno = errno; ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); return false; } LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get()); std::lock_guard<std::mutex> _l(mSocketMutex); std::lock_guard<std::mutex> _l(mSocketMutex); sp<ConnectionSocket> connection = new ConnectionSocket(); sp<ConnectionSocket> connection = new ConnectionSocket(); connection->fd = std::move(fd); connection->fd = std::move(serverFd); mClients.push_back(connection); mClients.push_back(connection); return true; } } void RpcConnection::addServer(base::unique_fd&& fd) { void RpcConnection::assignServerToThisThread(base::unique_fd&& fd) { std::lock_guard<std::mutex> _l(mSocketMutex); std::lock_guard<std::mutex> _l(mSocketMutex); sp<ConnectionSocket> connection = new ConnectionSocket(); sp<ConnectionSocket> connection = new ConnectionSocket(); connection->fd = std::move(fd); connection->fd = std::move(fd); Loading libs/binder/include/binder/RpcConnection.h +23 −2 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,18 @@ public: */ */ [[nodiscard]] bool addUnixDomainClient(const char* path); [[nodiscard]] bool addUnixDomainClient(const char* path); #ifdef __BIONIC__ /** * Creates an RPC server at the current port. */ [[nodiscard]] bool setupVsockServer(unsigned int port); /** * Connects to an RPC server at the CVD & port. */ [[nodiscard]] bool addVsockClient(unsigned int cvd, unsigned int port); #endif // __BIONIC__ /** /** * Query the other side of the connection for the root object hosted by that * Query the other side of the connection for the root object hosted by that * process's RpcServer (if one exists) * process's RpcServer (if one exists) Loading @@ -85,11 +97,20 @@ public: // internal only // internal only const std::unique_ptr<RpcState>& state() { return mState; } const std::unique_ptr<RpcState>& state() { return mState; } class SocketAddress { public: virtual ~SocketAddress(); virtual std::string toString() const = 0; virtual const sockaddr* addr() const = 0; virtual size_t addrSize() const = 0; }; private: private: RpcConnection(); RpcConnection(); void addServer(base::unique_fd&& fd); bool addServer(const SocketAddress& address); void addClient(base::unique_fd&& fd); bool addClient(const SocketAddress& address); void assignServerToThisThread(base::unique_fd&& fd); struct ConnectionSocket : public RefBase { struct ConnectionSocket : public RefBase { base::unique_fd fd; base::unique_fd fd; Loading libs/binder/tests/Android.bp +6 −0 Original line number Original line Diff line number Diff line Loading @@ -106,6 +106,12 @@ cc_test { cc_test { cc_test { name: "binderRpcTest", name: "binderRpcTest", host_supported: true, target: { darwin: { enabled: false, }, }, defaults: ["binder_test_defaults"], defaults: ["binder_test_defaults"], srcs: [ srcs: [ Loading libs/binder/tests/binderRpcTest.cpp +171 −109 Original line number Original line Diff line number Diff line Loading @@ -14,14 +14,6 @@ * limitations under the License. * limitations under the License. */ */ #include <sys/prctl.h> #include <unistd.h> #include <chrono> #include <cstdlib> #include <iostream> #include <thread> #include <BnBinderRpcSession.h> #include <BnBinderRpcSession.h> #include <BnBinderRpcTest.h> #include <BnBinderRpcTest.h> #include <android-base/logging.h> #include <android-base/logging.h> Loading @@ -33,6 +25,18 @@ #include <binder/RpcServer.h> #include <binder/RpcServer.h> #include <gtest/gtest.h> #include <gtest/gtest.h> #include <chrono> #include <cstdlib> #include <iostream> #include <thread> #ifdef __BIONIC__ #include <linux/vm_sockets.h> #endif //__BIONIC__ #include <sys/prctl.h> #include <unistd.h> #include "../RpcState.h" // for debugging #include "../RpcState.h" // for debugging namespace android { namespace android { Loading Loading @@ -185,8 +189,13 @@ private: static std::string allocateSocketAddress() { static std::string allocateSocketAddress() { static size_t id = 0; static size_t id = 0; static bool gUseTmp = access("/tmp/", F_OK) != -1; if (gUseTmp) { return "/tmp/binderRpcTest_" + std::to_string(id++); } else { return "/dev/binderRpcTest_" + std::to_string(id++); return "/dev/binderRpcTest_" + std::to_string(id++); } }; }; struct ProcessConnection { struct ProcessConnection { Loading Loading @@ -214,6 +223,51 @@ struct ProcessConnection { } } }; }; // Process connection where the process hosts IBinderRpcTest, the server used // for most testing here struct BinderRpcTestProcessConnection { ProcessConnection proc; // pre-fetched root object sp<IBinder> rootBinder; // pre-casted root object sp<IBinderRpcTest> rootIface; ~BinderRpcTestProcessConnection() { if (!proc.expectInvalid) { int32_t remoteBinders = 0; EXPECT_OK(rootIface->countBinders(&remoteBinders)); // should only be the root binder object, iface EXPECT_EQ(remoteBinders, 1); } rootIface = nullptr; rootBinder = nullptr; } }; enum class SocketType { UNIX, #ifdef __BIONIC__ VSOCK, #endif // __BIONIC__ }; static inline std::string PrintSocketType(const testing::TestParamInfo<SocketType>& info) { switch (info.param) { case SocketType::UNIX: return "unix_domain_socket"; #ifdef __BIONIC__ case SocketType::VSOCK: return "vm_socket"; #endif // __BIONIC__ default: LOG_ALWAYS_FATAL("Unknown socket type"); return ""; } } class BinderRpc : public ::testing::TestWithParam<SocketType> { public: // This creates a new process serving an interface on a certain number of // This creates a new process serving an interface on a certain number of // threads. // threads. ProcessConnection createRpcTestSocketServerProcess( ProcessConnection createRpcTestSocketServerProcess( Loading @@ -221,8 +275,12 @@ ProcessConnection createRpcTestSocketServerProcess( const std::function<void(const sp<RpcServer>&, const sp<RpcConnection>&)>& configure) { const std::function<void(const sp<RpcServer>&, const sp<RpcConnection>&)>& configure) { CHECK_GT(numThreads, 0); CHECK_GT(numThreads, 0); SocketType socketType = GetParam(); std::string addr = allocateSocketAddress(); std::string addr = allocateSocketAddress(); unlink(addr.c_str()); unlink(addr.c_str()); static unsigned int port = 3456; port++; auto ret = ProcessConnection{ auto ret = ProcessConnection{ .host = Process([&] { .host = Process([&] { Loading @@ -232,7 +290,19 @@ ProcessConnection createRpcTestSocketServerProcess( // server supporting one client on one socket // server supporting one client on one socket sp<RpcConnection> connection = server->addClientConnection(); sp<RpcConnection> connection = server->addClientConnection(); switch (socketType) { case SocketType::UNIX: CHECK(connection->setupUnixDomainServer(addr.c_str())) << addr; CHECK(connection->setupUnixDomainServer(addr.c_str())) << addr; break; #ifdef __BIONIC__ case SocketType::VSOCK: CHECK(connection->setupVsockServer(port)); break; #endif // __BIONIC__ default: LOG_ALWAYS_FATAL("Unknown socket type"); } configure(server, connection); configure(server, connection); Loading @@ -247,48 +317,30 @@ ProcessConnection createRpcTestSocketServerProcess( .connection = RpcConnection::make(), .connection = RpcConnection::make(), }; }; // wait up to 1s for sockets to be created constexpr useconds_t kMaxWaitUs = 1000000; constexpr useconds_t kWaitDivision = 100; for (size_t i = 0; i < kWaitDivision && 0 != access(addr.c_str(), F_OK); i++) { usleep(kMaxWaitUs / kWaitDivision); } // create remainder of connections // create remainder of connections for (size_t i = 0; i < numThreads; i++) { for (size_t i = 0; i < numThreads; i++) { // Connection refused sometimes after file created but before listening. for (size_t tries = 0; tries < 5; tries++) { CHECK(ret.connection->addUnixDomainClient(addr.c_str()) || usleep(10000); (usleep(10000), ret.connection->addUnixDomainClient(addr.c_str()))) switch (socketType) { << i; case SocketType::UNIX: if (ret.connection->addUnixDomainClient(addr.c_str())) goto success; break; #ifdef __BIONIC__ case SocketType::VSOCK: if (ret.connection->addVsockClient(VMADDR_CID_LOCAL, port)) goto success; break; #endif // __BIONIC__ default: LOG_ALWAYS_FATAL("Unknown socket type"); } } ret.rootBinder = ret.connection->getRootObject(); return ret; } } LOG_ALWAYS_FATAL("Could not connect"); // Process connection where the process hosts IBinderRpcTest, the server used success:; // for most testing here struct BinderRpcTestProcessConnection { ProcessConnection proc; // pre-fetched root object sp<IBinder> rootBinder; // pre-casted root object sp<IBinderRpcTest> rootIface; ~BinderRpcTestProcessConnection() { if (!proc.expectInvalid) { int32_t remoteBinders = 0; EXPECT_OK(rootIface->countBinders(&remoteBinders)); // should only be the root binder object, iface EXPECT_EQ(remoteBinders, 1); } } rootIface = nullptr; ret.rootBinder = ret.connection->getRootObject(); rootBinder = nullptr; return ret; } } }; BinderRpcTestProcessConnection createRpcTestSocketServerProcess(size_t numThreads) { BinderRpcTestProcessConnection createRpcTestSocketServerProcess(size_t numThreads) { BinderRpcTestProcessConnection ret{ BinderRpcTestProcessConnection ret{ Loading @@ -308,8 +360,9 @@ BinderRpcTestProcessConnection createRpcTestSocketServerProcess(size_t numThread return ret; return ret; } } }; TEST(BinderRpc, RootObjectIsNull) { TEST_P(BinderRpc, RootObjectIsNull) { auto proc = createRpcTestSocketServerProcess(1, auto proc = createRpcTestSocketServerProcess(1, [](const sp<RpcServer>& server, [](const sp<RpcServer>& server, const sp<RpcConnection>&) { const sp<RpcConnection>&) { Loading @@ -324,20 +377,20 @@ TEST(BinderRpc, RootObjectIsNull) { EXPECT_EQ(nullptr, proc.connection->getRootObject()); EXPECT_EQ(nullptr, proc.connection->getRootObject()); } } TEST(BinderRpc, Ping) { TEST_P(BinderRpc, Ping) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); ASSERT_NE(proc.rootBinder, nullptr); ASSERT_NE(proc.rootBinder, nullptr); EXPECT_EQ(OK, proc.rootBinder->pingBinder()); EXPECT_EQ(OK, proc.rootBinder->pingBinder()); } } TEST(BinderRpc, TransactionsMustBeMarkedRpc) { TEST_P(BinderRpc, TransactionsMustBeMarkedRpc) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); Parcel data; Parcel data; Parcel reply; Parcel reply; EXPECT_EQ(BAD_TYPE, proc.rootBinder->transact(IBinder::PING_TRANSACTION, data, &reply, 0)); EXPECT_EQ(BAD_TYPE, proc.rootBinder->transact(IBinder::PING_TRANSACTION, data, &reply, 0)); } } TEST(BinderRpc, UnknownTransaction) { TEST_P(BinderRpc, UnknownTransaction) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); Parcel data; Parcel data; data.markForBinder(proc.rootBinder); data.markForBinder(proc.rootBinder); Loading @@ -345,19 +398,19 @@ TEST(BinderRpc, UnknownTransaction) { EXPECT_EQ(UNKNOWN_TRANSACTION, proc.rootBinder->transact(1337, data, &reply, 0)); EXPECT_EQ(UNKNOWN_TRANSACTION, proc.rootBinder->transact(1337, data, &reply, 0)); } } TEST(BinderRpc, SendSomethingOneway) { TEST_P(BinderRpc, SendSomethingOneway) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); EXPECT_OK(proc.rootIface->sendString("asdf")); EXPECT_OK(proc.rootIface->sendString("asdf")); } } TEST(BinderRpc, SendAndGetResultBack) { TEST_P(BinderRpc, SendAndGetResultBack) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); std::string doubled; std::string doubled; EXPECT_OK(proc.rootIface->doubleString("cool ", &doubled)); EXPECT_OK(proc.rootIface->doubleString("cool ", &doubled)); EXPECT_EQ("cool cool ", doubled); EXPECT_EQ("cool cool ", doubled); } } TEST(BinderRpc, SendAndGetResultBackBig) { TEST_P(BinderRpc, SendAndGetResultBackBig) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); std::string single = std::string(1024, 'a'); std::string single = std::string(1024, 'a'); std::string doubled; std::string doubled; Loading @@ -365,7 +418,7 @@ TEST(BinderRpc, SendAndGetResultBackBig) { EXPECT_EQ(single + single, doubled); EXPECT_EQ(single + single, doubled); } } TEST(BinderRpc, CallMeBack) { TEST_P(BinderRpc, CallMeBack) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); int32_t pingResult; int32_t pingResult; Loading @@ -375,7 +428,7 @@ TEST(BinderRpc, CallMeBack) { EXPECT_EQ(0, MyBinderRpcSession::gNum); EXPECT_EQ(0, MyBinderRpcSession::gNum); } } TEST(BinderRpc, RepeatBinder) { TEST_P(BinderRpc, RepeatBinder) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> inBinder = new MyBinderRpcSession("foo"); sp<IBinder> inBinder = new MyBinderRpcSession("foo"); Loading @@ -397,7 +450,7 @@ TEST(BinderRpc, RepeatBinder) { EXPECT_EQ(0, MyBinderRpcSession::gNum); EXPECT_EQ(0, MyBinderRpcSession::gNum); } } TEST(BinderRpc, RepeatTheirBinder) { TEST_P(BinderRpc, RepeatTheirBinder) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinderRpcSession> session; sp<IBinderRpcSession> session; Loading @@ -421,7 +474,7 @@ TEST(BinderRpc, RepeatTheirBinder) { EXPECT_EQ(nullptr, weak.promote()); EXPECT_EQ(nullptr, weak.promote()); } } TEST(BinderRpc, RepeatBinderNull) { TEST_P(BinderRpc, RepeatBinderNull) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> outBinder; sp<IBinder> outBinder; Loading @@ -429,7 +482,7 @@ TEST(BinderRpc, RepeatBinderNull) { EXPECT_EQ(nullptr, outBinder); EXPECT_EQ(nullptr, outBinder); } } TEST(BinderRpc, HoldBinder) { TEST_P(BinderRpc, HoldBinder) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); IBinder* ptr = nullptr; IBinder* ptr = nullptr; Loading @@ -455,7 +508,7 @@ TEST(BinderRpc, HoldBinder) { // These are behavioral differences form regular binder, where certain usecases // These are behavioral differences form regular binder, where certain usecases // aren't supported. // aren't supported. TEST(BinderRpc, CannotMixBindersBetweenUnrelatedSocketConnections) { TEST_P(BinderRpc, CannotMixBindersBetweenUnrelatedSocketConnections) { auto proc1 = createRpcTestSocketServerProcess(1); auto proc1 = createRpcTestSocketServerProcess(1); auto proc2 = createRpcTestSocketServerProcess(1); auto proc2 = createRpcTestSocketServerProcess(1); Loading @@ -464,7 +517,7 @@ TEST(BinderRpc, CannotMixBindersBetweenUnrelatedSocketConnections) { proc1.rootIface->repeatBinder(proc2.rootBinder, &outBinder).transactionError()); proc1.rootIface->repeatBinder(proc2.rootBinder, &outBinder).transactionError()); } } TEST(BinderRpc, CannotSendRegularBinderOverSocketBinder) { TEST_P(BinderRpc, CannotSendRegularBinderOverSocketBinder) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> someRealBinder = IInterface::asBinder(defaultServiceManager()); sp<IBinder> someRealBinder = IInterface::asBinder(defaultServiceManager()); Loading @@ -473,7 +526,7 @@ TEST(BinderRpc, CannotSendRegularBinderOverSocketBinder) { proc.rootIface->repeatBinder(someRealBinder, &outBinder).transactionError()); proc.rootIface->repeatBinder(someRealBinder, &outBinder).transactionError()); } } TEST(BinderRpc, CannotSendSocketBinderOverRegularBinder) { TEST_P(BinderRpc, CannotSendSocketBinderOverRegularBinder) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); // for historical reasons, IServiceManager interface only returns the // for historical reasons, IServiceManager interface only returns the Loading @@ -484,7 +537,7 @@ TEST(BinderRpc, CannotSendSocketBinderOverRegularBinder) { // END TESTS FOR LIMITATIONS OF SOCKET BINDER // END TESTS FOR LIMITATIONS OF SOCKET BINDER TEST(BinderRpc, RepeatRootObject) { TEST_P(BinderRpc, RepeatRootObject) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> outBinder; sp<IBinder> outBinder; Loading @@ -492,7 +545,7 @@ TEST(BinderRpc, RepeatRootObject) { EXPECT_EQ(proc.rootBinder, outBinder); EXPECT_EQ(proc.rootBinder, outBinder); } } TEST(BinderRpc, NestedTransactions) { TEST_P(BinderRpc, NestedTransactions) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); auto nastyNester = sp<MyBinderRpcTest>::make(); auto nastyNester = sp<MyBinderRpcTest>::make(); Loading @@ -503,7 +556,7 @@ TEST(BinderRpc, NestedTransactions) { EXPECT_EQ(nullptr, weak.promote()); EXPECT_EQ(nullptr, weak.promote()); } } TEST(BinderRpc, SameBinderEquality) { TEST_P(BinderRpc, SameBinderEquality) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> a; sp<IBinder> a; Loading @@ -515,7 +568,7 @@ TEST(BinderRpc, SameBinderEquality) { EXPECT_EQ(a, b); EXPECT_EQ(a, b); } } TEST(BinderRpc, SameBinderEqualityWeak) { TEST_P(BinderRpc, SameBinderEqualityWeak) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> a; sp<IBinder> a; Loading Loading @@ -547,7 +600,7 @@ TEST(BinderRpc, SameBinderEqualityWeak) { EXPECT_EQ(expected, session); \ EXPECT_EQ(expected, session); \ } while (false) } while (false) TEST(BinderRpc, SingleSession) { TEST_P(BinderRpc, SingleSession) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinderRpcSession> session; sp<IBinderRpcSession> session; Loading @@ -561,7 +614,7 @@ TEST(BinderRpc, SingleSession) { expectSessions(0, proc.rootIface); expectSessions(0, proc.rootIface); } } TEST(BinderRpc, ManySessions) { TEST_P(BinderRpc, ManySessions) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); std::vector<sp<IBinderRpcSession>> sessions; std::vector<sp<IBinderRpcSession>> sessions; Loading Loading @@ -595,7 +648,7 @@ size_t epochMillis() { return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); } } TEST(BinderRpc, ThreadPoolGreaterThanEqualRequested) { TEST_P(BinderRpc, ThreadPoolGreaterThanEqualRequested) { constexpr size_t kNumThreads = 10; constexpr size_t kNumThreads = 10; auto proc = createRpcTestSocketServerProcess(kNumThreads); auto proc = createRpcTestSocketServerProcess(kNumThreads); Loading Loading @@ -627,7 +680,7 @@ TEST(BinderRpc, ThreadPoolGreaterThanEqualRequested) { for (auto& t : ts) t.join(); for (auto& t : ts) t.join(); } } TEST(BinderRpc, ThreadPoolOverSaturated) { TEST_P(BinderRpc, ThreadPoolOverSaturated) { constexpr size_t kNumThreads = 10; constexpr size_t kNumThreads = 10; constexpr size_t kNumCalls = kNumThreads + 3; constexpr size_t kNumCalls = kNumThreads + 3; constexpr size_t kSleepMs = 500; constexpr size_t kSleepMs = 500; Loading @@ -651,7 +704,7 @@ TEST(BinderRpc, ThreadPoolOverSaturated) { EXPECT_LE(epochMsAfter, epochMsBefore + 3 * kSleepMs); EXPECT_LE(epochMsAfter, epochMsBefore + 3 * kSleepMs); } } TEST(BinderRpc, ThreadingStressTest) { TEST_P(BinderRpc, ThreadingStressTest) { constexpr size_t kNumClientThreads = 10; constexpr size_t kNumClientThreads = 10; constexpr size_t kNumServerThreads = 10; constexpr size_t kNumServerThreads = 10; constexpr size_t kNumCalls = 100; constexpr size_t kNumCalls = 100; Loading @@ -672,7 +725,7 @@ TEST(BinderRpc, ThreadingStressTest) { for (auto& t : threads) t.join(); for (auto& t : threads) t.join(); } } TEST(BinderRpc, OnewayCallDoesNotWait) { TEST_P(BinderRpc, OnewayCallDoesNotWait) { constexpr size_t kReallyLongTimeMs = 100; constexpr size_t kReallyLongTimeMs = 100; constexpr size_t kSleepMs = kReallyLongTimeMs * 5; constexpr size_t kSleepMs = kReallyLongTimeMs * 5; Loading @@ -687,7 +740,7 @@ TEST(BinderRpc, OnewayCallDoesNotWait) { EXPECT_LT(epochMsAfter, epochMsBefore + kReallyLongTimeMs); EXPECT_LT(epochMsAfter, epochMsBefore + kReallyLongTimeMs); } } TEST(BinderRpc, OnewayCallQueueing) { TEST_P(BinderRpc, OnewayCallQueueing) { constexpr size_t kNumSleeps = 10; constexpr size_t kNumSleeps = 10; constexpr size_t kNumExtraServerThreads = 4; constexpr size_t kNumExtraServerThreads = 4; constexpr size_t kSleepMs = 50; constexpr size_t kSleepMs = 50; Loading @@ -711,7 +764,7 @@ TEST(BinderRpc, OnewayCallQueueing) { EXPECT_GT(epochMsAfter, epochMsBefore + kSleepMs * kNumSleeps); EXPECT_GT(epochMsAfter, epochMsBefore + kSleepMs * kNumSleeps); } } TEST(BinderRpc, Die) { TEST_P(BinderRpc, Die) { // TODO(b/183141167): handle this in library // TODO(b/183141167): handle this in library signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN); Loading Loading @@ -743,7 +796,7 @@ ssize_t countFds() { return ret; return ret; } } TEST(BinderRpc, Fds) { TEST_P(BinderRpc, Fds) { ssize_t beforeFds = countFds(); ssize_t beforeFds = countFds(); ASSERT_GE(beforeFds, 0); ASSERT_GE(beforeFds, 0); { { Loading @@ -753,10 +806,19 @@ TEST(BinderRpc, Fds) { ASSERT_EQ(beforeFds, countFds()) << (system("ls -l /proc/self/fd/"), "fd leak?"); ASSERT_EQ(beforeFds, countFds()) << (system("ls -l /proc/self/fd/"), "fd leak?"); } } extern "C" int main(int argc, char** argv) { INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpc, ::testing::Values(SocketType::UNIX #ifdef __BIONIC__ , SocketType::VSOCK #endif // __BIONIC__ ), PrintSocketType); } // namespace android int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv); android::base::InitLogging(argv, android::base::StderrLogger, android::base::DefaultAborter); android::base::InitLogging(argv, android::base::StderrLogger, android::base::DefaultAborter); return RUN_ALL_TESTS(); return RUN_ALL_TESTS(); } } } // namespace android Loading
libs/binder/RpcConnection.cpp +104 −54 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <binder/Parcel.h> #include <binder/Parcel.h> #include <binder/Stability.h> #include <binder/Stability.h> #include <utils/String8.h> #include "RpcState.h" #include "RpcState.h" #include "RpcWireFormat.h" #include "RpcWireFormat.h" Loading @@ -29,14 +30,20 @@ #include <sys/un.h> #include <sys/un.h> #include <unistd.h> #include <unistd.h> #if defined(__GLIBC__) #ifdef __GLIBC__ extern "C" pid_t gettid(); extern "C" pid_t gettid(); #endif #endif #ifdef __BIONIC__ #include <linux/vm_sockets.h> #endif namespace android { namespace android { using base::unique_fd; using base::unique_fd; RpcConnection::SocketAddress::~SocketAddress() {} RpcConnection::RpcConnection() { RpcConnection::RpcConnection() { LOG_RPC_DETAIL("RpcConnection created %p", this); LOG_RPC_DETAIL("RpcConnection created %p", this); Loading @@ -50,65 +57,68 @@ sp<RpcConnection> RpcConnection::make() { return new RpcConnection; return new RpcConnection; } } bool RpcConnection::setupUnixDomainServer(const char* path) { class UnixSocketAddress : public RpcConnection::SocketAddress { LOG_ALWAYS_FATAL_IF(mServer.get() != -1, "Only supports one server now"); public: explicit UnixSocketAddress(const char* path) : mAddr({.sun_family = AF_UNIX}) { unique_fd serverFd(TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0))); unsigned int pathLen = strlen(path) + 1; if (serverFd == -1) { LOG_ALWAYS_FATAL_IF(pathLen > sizeof(mAddr.sun_path), "%u %s", pathLen, path); ALOGE("Could not create socket at %s: %s", path, strerror(errno)); memcpy(mAddr.sun_path, path, pathLen); return false; } virtual ~UnixSocketAddress() {} std::string toString() const override { return String8::format("path '%.*s'", static_cast<int>(sizeof(mAddr.sun_path)), mAddr.sun_path) .c_str(); } } const sockaddr* addr() const override { return reinterpret_cast<const sockaddr*>(&mAddr); } size_t addrSize() const override { return sizeof(mAddr); } struct sockaddr_un addr = { private: .sun_family = AF_UNIX, sockaddr_un mAddr; }; }; unsigned int pathLen = strlen(path) + 1; bool RpcConnection::setupUnixDomainServer(const char* path) { LOG_ALWAYS_FATAL_IF(pathLen > sizeof(addr.sun_path), "%u", pathLen); return addServer(UnixSocketAddress(path)); memcpy(addr.sun_path, path, pathLen); if (0 != TEMP_FAILURE_RETRY(bind(serverFd.get(), (struct sockaddr*)&addr, sizeof(addr)))) { ALOGE("Could not bind socket at %s: %s", path, strerror(errno)); return false; } if (0 != TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/))) { ALOGE("Could not listen socket at %s: %s", path, strerror(errno)); return false; } } mServer = std::move(serverFd); bool RpcConnection::addUnixDomainClient(const char* path) { return true; return addClient(UnixSocketAddress(path)); } } bool RpcConnection::addUnixDomainClient(const char* path) { #ifdef __BIONIC__ LOG_RPC_DETAIL("Connecting on path: %s", path); unique_fd serverFd(TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0))); class VsockSocketAddress : public RpcConnection::SocketAddress { if (serverFd == -1) { public: ALOGE("Could not create socket at %s: %s", path, strerror(errno)); VsockSocketAddress(unsigned int cid, unsigned int port) return false; : mAddr({ .svm_family = AF_VSOCK, .svm_port = port, .svm_cid = cid, }) {} virtual ~VsockSocketAddress() {} std::string toString() const override { return String8::format("cid %du port %du", mAddr.svm_cid, mAddr.svm_port).c_str(); } } const sockaddr* addr() const override { return reinterpret_cast<const sockaddr*>(&mAddr); } size_t addrSize() const override { return sizeof(mAddr); } struct sockaddr_un addr = { private: .sun_family = AF_UNIX, sockaddr_vm mAddr; }; }; unsigned int pathLen = strlen(path) + 1; bool RpcConnection::setupVsockServer(unsigned int port) { LOG_ALWAYS_FATAL_IF(pathLen > sizeof(addr.sun_path), "%u", pathLen); // realizing value w/ this type at compile time to avoid ubsan abort memcpy(addr.sun_path, path, pathLen); constexpr unsigned int kAnyCid = VMADDR_CID_ANY; if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), (struct sockaddr*)&addr, sizeof(addr)))) { return addServer(VsockSocketAddress(kAnyCid, port)); ALOGE("Could not connect socket at %s: %s", path, strerror(errno)); return false; } } LOG_RPC_DETAIL("Unix domain client with fd %d", serverFd.get()); bool RpcConnection::addVsockClient(unsigned int cid, unsigned int port) { return addClient(VsockSocketAddress(cid, port)); addClient(std::move(serverFd)); return true; } } #endif // __BIONIC__ sp<IBinder> RpcConnection::getRootObject() { sp<IBinder> RpcConnection::getRootObject() { ExclusiveSocket socket(this, SocketUse::CLIENT); ExclusiveSocket socket(this, SocketUse::CLIENT); return state()->getRootObject(socket.fd(), this); return state()->getRootObject(socket.fd(), this); Loading @@ -130,11 +140,8 @@ status_t RpcConnection::sendDecStrong(const RpcAddress& address) { void RpcConnection::join() { void RpcConnection::join() { // establish a connection // establish a connection { { struct sockaddr_un clientSa; unique_fd clientFd( socklen_t clientSaLen = sizeof(clientSa); TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, 0 /*length*/, SOCK_CLOEXEC))); unique_fd clientFd(TEMP_FAILURE_RETRY( accept4(mServer.get(), (struct sockaddr*)&clientSa, &clientSaLen, SOCK_CLOEXEC))); if (clientFd < 0) { if (clientFd < 0) { // If this log becomes confusing, should save more state from setupUnixDomainServer // If this log becomes confusing, should save more state from setupUnixDomainServer // in order to output here. // in order to output here. Loading @@ -144,7 +151,7 @@ void RpcConnection::join() { LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get()); LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get()); addServer(std::move(clientFd)); assignServerToThisThread(std::move(clientFd)); } } // We may not use the connection we just established (two threads might // We may not use the connection we just established (two threads might Loading @@ -170,14 +177,57 @@ wp<RpcServer> RpcConnection::server() { return mForServer; return mForServer; } } void RpcConnection::addClient(base::unique_fd&& fd) { bool RpcConnection::addServer(const SocketAddress& addr) { LOG_ALWAYS_FATAL_IF(mServer.get() != -1, "Each RpcConnection can only have one server."); unique_fd serverFd( TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0))); if (serverFd == -1) { ALOGE("Could not create socket: %s", strerror(errno)); return false; } if (0 != TEMP_FAILURE_RETRY(bind(serverFd.get(), addr.addr(), addr.addrSize()))) { int savedErrno = errno; ALOGE("Could not bind socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); return false; } if (0 != TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/))) { int savedErrno = errno; ALOGE("Could not listen socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); return false; } mServer = std::move(serverFd); return true; } bool RpcConnection::addClient(const SocketAddress& addr) { unique_fd serverFd( TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0))); if (serverFd == -1) { int savedErrno = errno; ALOGE("Could not create socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); return false; } if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) { int savedErrno = errno; ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); return false; } LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get()); std::lock_guard<std::mutex> _l(mSocketMutex); std::lock_guard<std::mutex> _l(mSocketMutex); sp<ConnectionSocket> connection = new ConnectionSocket(); sp<ConnectionSocket> connection = new ConnectionSocket(); connection->fd = std::move(fd); connection->fd = std::move(serverFd); mClients.push_back(connection); mClients.push_back(connection); return true; } } void RpcConnection::addServer(base::unique_fd&& fd) { void RpcConnection::assignServerToThisThread(base::unique_fd&& fd) { std::lock_guard<std::mutex> _l(mSocketMutex); std::lock_guard<std::mutex> _l(mSocketMutex); sp<ConnectionSocket> connection = new ConnectionSocket(); sp<ConnectionSocket> connection = new ConnectionSocket(); connection->fd = std::move(fd); connection->fd = std::move(fd); Loading
libs/binder/include/binder/RpcConnection.h +23 −2 Original line number Original line Diff line number Diff line Loading @@ -61,6 +61,18 @@ public: */ */ [[nodiscard]] bool addUnixDomainClient(const char* path); [[nodiscard]] bool addUnixDomainClient(const char* path); #ifdef __BIONIC__ /** * Creates an RPC server at the current port. */ [[nodiscard]] bool setupVsockServer(unsigned int port); /** * Connects to an RPC server at the CVD & port. */ [[nodiscard]] bool addVsockClient(unsigned int cvd, unsigned int port); #endif // __BIONIC__ /** /** * Query the other side of the connection for the root object hosted by that * Query the other side of the connection for the root object hosted by that * process's RpcServer (if one exists) * process's RpcServer (if one exists) Loading @@ -85,11 +97,20 @@ public: // internal only // internal only const std::unique_ptr<RpcState>& state() { return mState; } const std::unique_ptr<RpcState>& state() { return mState; } class SocketAddress { public: virtual ~SocketAddress(); virtual std::string toString() const = 0; virtual const sockaddr* addr() const = 0; virtual size_t addrSize() const = 0; }; private: private: RpcConnection(); RpcConnection(); void addServer(base::unique_fd&& fd); bool addServer(const SocketAddress& address); void addClient(base::unique_fd&& fd); bool addClient(const SocketAddress& address); void assignServerToThisThread(base::unique_fd&& fd); struct ConnectionSocket : public RefBase { struct ConnectionSocket : public RefBase { base::unique_fd fd; base::unique_fd fd; Loading
libs/binder/tests/Android.bp +6 −0 Original line number Original line Diff line number Diff line Loading @@ -106,6 +106,12 @@ cc_test { cc_test { cc_test { name: "binderRpcTest", name: "binderRpcTest", host_supported: true, target: { darwin: { enabled: false, }, }, defaults: ["binder_test_defaults"], defaults: ["binder_test_defaults"], srcs: [ srcs: [ Loading
libs/binder/tests/binderRpcTest.cpp +171 −109 Original line number Original line Diff line number Diff line Loading @@ -14,14 +14,6 @@ * limitations under the License. * limitations under the License. */ */ #include <sys/prctl.h> #include <unistd.h> #include <chrono> #include <cstdlib> #include <iostream> #include <thread> #include <BnBinderRpcSession.h> #include <BnBinderRpcSession.h> #include <BnBinderRpcTest.h> #include <BnBinderRpcTest.h> #include <android-base/logging.h> #include <android-base/logging.h> Loading @@ -33,6 +25,18 @@ #include <binder/RpcServer.h> #include <binder/RpcServer.h> #include <gtest/gtest.h> #include <gtest/gtest.h> #include <chrono> #include <cstdlib> #include <iostream> #include <thread> #ifdef __BIONIC__ #include <linux/vm_sockets.h> #endif //__BIONIC__ #include <sys/prctl.h> #include <unistd.h> #include "../RpcState.h" // for debugging #include "../RpcState.h" // for debugging namespace android { namespace android { Loading Loading @@ -185,8 +189,13 @@ private: static std::string allocateSocketAddress() { static std::string allocateSocketAddress() { static size_t id = 0; static size_t id = 0; static bool gUseTmp = access("/tmp/", F_OK) != -1; if (gUseTmp) { return "/tmp/binderRpcTest_" + std::to_string(id++); } else { return "/dev/binderRpcTest_" + std::to_string(id++); return "/dev/binderRpcTest_" + std::to_string(id++); } }; }; struct ProcessConnection { struct ProcessConnection { Loading Loading @@ -214,6 +223,51 @@ struct ProcessConnection { } } }; }; // Process connection where the process hosts IBinderRpcTest, the server used // for most testing here struct BinderRpcTestProcessConnection { ProcessConnection proc; // pre-fetched root object sp<IBinder> rootBinder; // pre-casted root object sp<IBinderRpcTest> rootIface; ~BinderRpcTestProcessConnection() { if (!proc.expectInvalid) { int32_t remoteBinders = 0; EXPECT_OK(rootIface->countBinders(&remoteBinders)); // should only be the root binder object, iface EXPECT_EQ(remoteBinders, 1); } rootIface = nullptr; rootBinder = nullptr; } }; enum class SocketType { UNIX, #ifdef __BIONIC__ VSOCK, #endif // __BIONIC__ }; static inline std::string PrintSocketType(const testing::TestParamInfo<SocketType>& info) { switch (info.param) { case SocketType::UNIX: return "unix_domain_socket"; #ifdef __BIONIC__ case SocketType::VSOCK: return "vm_socket"; #endif // __BIONIC__ default: LOG_ALWAYS_FATAL("Unknown socket type"); return ""; } } class BinderRpc : public ::testing::TestWithParam<SocketType> { public: // This creates a new process serving an interface on a certain number of // This creates a new process serving an interface on a certain number of // threads. // threads. ProcessConnection createRpcTestSocketServerProcess( ProcessConnection createRpcTestSocketServerProcess( Loading @@ -221,8 +275,12 @@ ProcessConnection createRpcTestSocketServerProcess( const std::function<void(const sp<RpcServer>&, const sp<RpcConnection>&)>& configure) { const std::function<void(const sp<RpcServer>&, const sp<RpcConnection>&)>& configure) { CHECK_GT(numThreads, 0); CHECK_GT(numThreads, 0); SocketType socketType = GetParam(); std::string addr = allocateSocketAddress(); std::string addr = allocateSocketAddress(); unlink(addr.c_str()); unlink(addr.c_str()); static unsigned int port = 3456; port++; auto ret = ProcessConnection{ auto ret = ProcessConnection{ .host = Process([&] { .host = Process([&] { Loading @@ -232,7 +290,19 @@ ProcessConnection createRpcTestSocketServerProcess( // server supporting one client on one socket // server supporting one client on one socket sp<RpcConnection> connection = server->addClientConnection(); sp<RpcConnection> connection = server->addClientConnection(); switch (socketType) { case SocketType::UNIX: CHECK(connection->setupUnixDomainServer(addr.c_str())) << addr; CHECK(connection->setupUnixDomainServer(addr.c_str())) << addr; break; #ifdef __BIONIC__ case SocketType::VSOCK: CHECK(connection->setupVsockServer(port)); break; #endif // __BIONIC__ default: LOG_ALWAYS_FATAL("Unknown socket type"); } configure(server, connection); configure(server, connection); Loading @@ -247,48 +317,30 @@ ProcessConnection createRpcTestSocketServerProcess( .connection = RpcConnection::make(), .connection = RpcConnection::make(), }; }; // wait up to 1s for sockets to be created constexpr useconds_t kMaxWaitUs = 1000000; constexpr useconds_t kWaitDivision = 100; for (size_t i = 0; i < kWaitDivision && 0 != access(addr.c_str(), F_OK); i++) { usleep(kMaxWaitUs / kWaitDivision); } // create remainder of connections // create remainder of connections for (size_t i = 0; i < numThreads; i++) { for (size_t i = 0; i < numThreads; i++) { // Connection refused sometimes after file created but before listening. for (size_t tries = 0; tries < 5; tries++) { CHECK(ret.connection->addUnixDomainClient(addr.c_str()) || usleep(10000); (usleep(10000), ret.connection->addUnixDomainClient(addr.c_str()))) switch (socketType) { << i; case SocketType::UNIX: if (ret.connection->addUnixDomainClient(addr.c_str())) goto success; break; #ifdef __BIONIC__ case SocketType::VSOCK: if (ret.connection->addVsockClient(VMADDR_CID_LOCAL, port)) goto success; break; #endif // __BIONIC__ default: LOG_ALWAYS_FATAL("Unknown socket type"); } } ret.rootBinder = ret.connection->getRootObject(); return ret; } } LOG_ALWAYS_FATAL("Could not connect"); // Process connection where the process hosts IBinderRpcTest, the server used success:; // for most testing here struct BinderRpcTestProcessConnection { ProcessConnection proc; // pre-fetched root object sp<IBinder> rootBinder; // pre-casted root object sp<IBinderRpcTest> rootIface; ~BinderRpcTestProcessConnection() { if (!proc.expectInvalid) { int32_t remoteBinders = 0; EXPECT_OK(rootIface->countBinders(&remoteBinders)); // should only be the root binder object, iface EXPECT_EQ(remoteBinders, 1); } } rootIface = nullptr; ret.rootBinder = ret.connection->getRootObject(); rootBinder = nullptr; return ret; } } }; BinderRpcTestProcessConnection createRpcTestSocketServerProcess(size_t numThreads) { BinderRpcTestProcessConnection createRpcTestSocketServerProcess(size_t numThreads) { BinderRpcTestProcessConnection ret{ BinderRpcTestProcessConnection ret{ Loading @@ -308,8 +360,9 @@ BinderRpcTestProcessConnection createRpcTestSocketServerProcess(size_t numThread return ret; return ret; } } }; TEST(BinderRpc, RootObjectIsNull) { TEST_P(BinderRpc, RootObjectIsNull) { auto proc = createRpcTestSocketServerProcess(1, auto proc = createRpcTestSocketServerProcess(1, [](const sp<RpcServer>& server, [](const sp<RpcServer>& server, const sp<RpcConnection>&) { const sp<RpcConnection>&) { Loading @@ -324,20 +377,20 @@ TEST(BinderRpc, RootObjectIsNull) { EXPECT_EQ(nullptr, proc.connection->getRootObject()); EXPECT_EQ(nullptr, proc.connection->getRootObject()); } } TEST(BinderRpc, Ping) { TEST_P(BinderRpc, Ping) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); ASSERT_NE(proc.rootBinder, nullptr); ASSERT_NE(proc.rootBinder, nullptr); EXPECT_EQ(OK, proc.rootBinder->pingBinder()); EXPECT_EQ(OK, proc.rootBinder->pingBinder()); } } TEST(BinderRpc, TransactionsMustBeMarkedRpc) { TEST_P(BinderRpc, TransactionsMustBeMarkedRpc) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); Parcel data; Parcel data; Parcel reply; Parcel reply; EXPECT_EQ(BAD_TYPE, proc.rootBinder->transact(IBinder::PING_TRANSACTION, data, &reply, 0)); EXPECT_EQ(BAD_TYPE, proc.rootBinder->transact(IBinder::PING_TRANSACTION, data, &reply, 0)); } } TEST(BinderRpc, UnknownTransaction) { TEST_P(BinderRpc, UnknownTransaction) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); Parcel data; Parcel data; data.markForBinder(proc.rootBinder); data.markForBinder(proc.rootBinder); Loading @@ -345,19 +398,19 @@ TEST(BinderRpc, UnknownTransaction) { EXPECT_EQ(UNKNOWN_TRANSACTION, proc.rootBinder->transact(1337, data, &reply, 0)); EXPECT_EQ(UNKNOWN_TRANSACTION, proc.rootBinder->transact(1337, data, &reply, 0)); } } TEST(BinderRpc, SendSomethingOneway) { TEST_P(BinderRpc, SendSomethingOneway) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); EXPECT_OK(proc.rootIface->sendString("asdf")); EXPECT_OK(proc.rootIface->sendString("asdf")); } } TEST(BinderRpc, SendAndGetResultBack) { TEST_P(BinderRpc, SendAndGetResultBack) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); std::string doubled; std::string doubled; EXPECT_OK(proc.rootIface->doubleString("cool ", &doubled)); EXPECT_OK(proc.rootIface->doubleString("cool ", &doubled)); EXPECT_EQ("cool cool ", doubled); EXPECT_EQ("cool cool ", doubled); } } TEST(BinderRpc, SendAndGetResultBackBig) { TEST_P(BinderRpc, SendAndGetResultBackBig) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); std::string single = std::string(1024, 'a'); std::string single = std::string(1024, 'a'); std::string doubled; std::string doubled; Loading @@ -365,7 +418,7 @@ TEST(BinderRpc, SendAndGetResultBackBig) { EXPECT_EQ(single + single, doubled); EXPECT_EQ(single + single, doubled); } } TEST(BinderRpc, CallMeBack) { TEST_P(BinderRpc, CallMeBack) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); int32_t pingResult; int32_t pingResult; Loading @@ -375,7 +428,7 @@ TEST(BinderRpc, CallMeBack) { EXPECT_EQ(0, MyBinderRpcSession::gNum); EXPECT_EQ(0, MyBinderRpcSession::gNum); } } TEST(BinderRpc, RepeatBinder) { TEST_P(BinderRpc, RepeatBinder) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> inBinder = new MyBinderRpcSession("foo"); sp<IBinder> inBinder = new MyBinderRpcSession("foo"); Loading @@ -397,7 +450,7 @@ TEST(BinderRpc, RepeatBinder) { EXPECT_EQ(0, MyBinderRpcSession::gNum); EXPECT_EQ(0, MyBinderRpcSession::gNum); } } TEST(BinderRpc, RepeatTheirBinder) { TEST_P(BinderRpc, RepeatTheirBinder) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinderRpcSession> session; sp<IBinderRpcSession> session; Loading @@ -421,7 +474,7 @@ TEST(BinderRpc, RepeatTheirBinder) { EXPECT_EQ(nullptr, weak.promote()); EXPECT_EQ(nullptr, weak.promote()); } } TEST(BinderRpc, RepeatBinderNull) { TEST_P(BinderRpc, RepeatBinderNull) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> outBinder; sp<IBinder> outBinder; Loading @@ -429,7 +482,7 @@ TEST(BinderRpc, RepeatBinderNull) { EXPECT_EQ(nullptr, outBinder); EXPECT_EQ(nullptr, outBinder); } } TEST(BinderRpc, HoldBinder) { TEST_P(BinderRpc, HoldBinder) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); IBinder* ptr = nullptr; IBinder* ptr = nullptr; Loading @@ -455,7 +508,7 @@ TEST(BinderRpc, HoldBinder) { // These are behavioral differences form regular binder, where certain usecases // These are behavioral differences form regular binder, where certain usecases // aren't supported. // aren't supported. TEST(BinderRpc, CannotMixBindersBetweenUnrelatedSocketConnections) { TEST_P(BinderRpc, CannotMixBindersBetweenUnrelatedSocketConnections) { auto proc1 = createRpcTestSocketServerProcess(1); auto proc1 = createRpcTestSocketServerProcess(1); auto proc2 = createRpcTestSocketServerProcess(1); auto proc2 = createRpcTestSocketServerProcess(1); Loading @@ -464,7 +517,7 @@ TEST(BinderRpc, CannotMixBindersBetweenUnrelatedSocketConnections) { proc1.rootIface->repeatBinder(proc2.rootBinder, &outBinder).transactionError()); proc1.rootIface->repeatBinder(proc2.rootBinder, &outBinder).transactionError()); } } TEST(BinderRpc, CannotSendRegularBinderOverSocketBinder) { TEST_P(BinderRpc, CannotSendRegularBinderOverSocketBinder) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> someRealBinder = IInterface::asBinder(defaultServiceManager()); sp<IBinder> someRealBinder = IInterface::asBinder(defaultServiceManager()); Loading @@ -473,7 +526,7 @@ TEST(BinderRpc, CannotSendRegularBinderOverSocketBinder) { proc.rootIface->repeatBinder(someRealBinder, &outBinder).transactionError()); proc.rootIface->repeatBinder(someRealBinder, &outBinder).transactionError()); } } TEST(BinderRpc, CannotSendSocketBinderOverRegularBinder) { TEST_P(BinderRpc, CannotSendSocketBinderOverRegularBinder) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); // for historical reasons, IServiceManager interface only returns the // for historical reasons, IServiceManager interface only returns the Loading @@ -484,7 +537,7 @@ TEST(BinderRpc, CannotSendSocketBinderOverRegularBinder) { // END TESTS FOR LIMITATIONS OF SOCKET BINDER // END TESTS FOR LIMITATIONS OF SOCKET BINDER TEST(BinderRpc, RepeatRootObject) { TEST_P(BinderRpc, RepeatRootObject) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> outBinder; sp<IBinder> outBinder; Loading @@ -492,7 +545,7 @@ TEST(BinderRpc, RepeatRootObject) { EXPECT_EQ(proc.rootBinder, outBinder); EXPECT_EQ(proc.rootBinder, outBinder); } } TEST(BinderRpc, NestedTransactions) { TEST_P(BinderRpc, NestedTransactions) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); auto nastyNester = sp<MyBinderRpcTest>::make(); auto nastyNester = sp<MyBinderRpcTest>::make(); Loading @@ -503,7 +556,7 @@ TEST(BinderRpc, NestedTransactions) { EXPECT_EQ(nullptr, weak.promote()); EXPECT_EQ(nullptr, weak.promote()); } } TEST(BinderRpc, SameBinderEquality) { TEST_P(BinderRpc, SameBinderEquality) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> a; sp<IBinder> a; Loading @@ -515,7 +568,7 @@ TEST(BinderRpc, SameBinderEquality) { EXPECT_EQ(a, b); EXPECT_EQ(a, b); } } TEST(BinderRpc, SameBinderEqualityWeak) { TEST_P(BinderRpc, SameBinderEqualityWeak) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> a; sp<IBinder> a; Loading Loading @@ -547,7 +600,7 @@ TEST(BinderRpc, SameBinderEqualityWeak) { EXPECT_EQ(expected, session); \ EXPECT_EQ(expected, session); \ } while (false) } while (false) TEST(BinderRpc, SingleSession) { TEST_P(BinderRpc, SingleSession) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); sp<IBinderRpcSession> session; sp<IBinderRpcSession> session; Loading @@ -561,7 +614,7 @@ TEST(BinderRpc, SingleSession) { expectSessions(0, proc.rootIface); expectSessions(0, proc.rootIface); } } TEST(BinderRpc, ManySessions) { TEST_P(BinderRpc, ManySessions) { auto proc = createRpcTestSocketServerProcess(1); auto proc = createRpcTestSocketServerProcess(1); std::vector<sp<IBinderRpcSession>> sessions; std::vector<sp<IBinderRpcSession>> sessions; Loading Loading @@ -595,7 +648,7 @@ size_t epochMillis() { return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); } } TEST(BinderRpc, ThreadPoolGreaterThanEqualRequested) { TEST_P(BinderRpc, ThreadPoolGreaterThanEqualRequested) { constexpr size_t kNumThreads = 10; constexpr size_t kNumThreads = 10; auto proc = createRpcTestSocketServerProcess(kNumThreads); auto proc = createRpcTestSocketServerProcess(kNumThreads); Loading Loading @@ -627,7 +680,7 @@ TEST(BinderRpc, ThreadPoolGreaterThanEqualRequested) { for (auto& t : ts) t.join(); for (auto& t : ts) t.join(); } } TEST(BinderRpc, ThreadPoolOverSaturated) { TEST_P(BinderRpc, ThreadPoolOverSaturated) { constexpr size_t kNumThreads = 10; constexpr size_t kNumThreads = 10; constexpr size_t kNumCalls = kNumThreads + 3; constexpr size_t kNumCalls = kNumThreads + 3; constexpr size_t kSleepMs = 500; constexpr size_t kSleepMs = 500; Loading @@ -651,7 +704,7 @@ TEST(BinderRpc, ThreadPoolOverSaturated) { EXPECT_LE(epochMsAfter, epochMsBefore + 3 * kSleepMs); EXPECT_LE(epochMsAfter, epochMsBefore + 3 * kSleepMs); } } TEST(BinderRpc, ThreadingStressTest) { TEST_P(BinderRpc, ThreadingStressTest) { constexpr size_t kNumClientThreads = 10; constexpr size_t kNumClientThreads = 10; constexpr size_t kNumServerThreads = 10; constexpr size_t kNumServerThreads = 10; constexpr size_t kNumCalls = 100; constexpr size_t kNumCalls = 100; Loading @@ -672,7 +725,7 @@ TEST(BinderRpc, ThreadingStressTest) { for (auto& t : threads) t.join(); for (auto& t : threads) t.join(); } } TEST(BinderRpc, OnewayCallDoesNotWait) { TEST_P(BinderRpc, OnewayCallDoesNotWait) { constexpr size_t kReallyLongTimeMs = 100; constexpr size_t kReallyLongTimeMs = 100; constexpr size_t kSleepMs = kReallyLongTimeMs * 5; constexpr size_t kSleepMs = kReallyLongTimeMs * 5; Loading @@ -687,7 +740,7 @@ TEST(BinderRpc, OnewayCallDoesNotWait) { EXPECT_LT(epochMsAfter, epochMsBefore + kReallyLongTimeMs); EXPECT_LT(epochMsAfter, epochMsBefore + kReallyLongTimeMs); } } TEST(BinderRpc, OnewayCallQueueing) { TEST_P(BinderRpc, OnewayCallQueueing) { constexpr size_t kNumSleeps = 10; constexpr size_t kNumSleeps = 10; constexpr size_t kNumExtraServerThreads = 4; constexpr size_t kNumExtraServerThreads = 4; constexpr size_t kSleepMs = 50; constexpr size_t kSleepMs = 50; Loading @@ -711,7 +764,7 @@ TEST(BinderRpc, OnewayCallQueueing) { EXPECT_GT(epochMsAfter, epochMsBefore + kSleepMs * kNumSleeps); EXPECT_GT(epochMsAfter, epochMsBefore + kSleepMs * kNumSleeps); } } TEST(BinderRpc, Die) { TEST_P(BinderRpc, Die) { // TODO(b/183141167): handle this in library // TODO(b/183141167): handle this in library signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN); Loading Loading @@ -743,7 +796,7 @@ ssize_t countFds() { return ret; return ret; } } TEST(BinderRpc, Fds) { TEST_P(BinderRpc, Fds) { ssize_t beforeFds = countFds(); ssize_t beforeFds = countFds(); ASSERT_GE(beforeFds, 0); ASSERT_GE(beforeFds, 0); { { Loading @@ -753,10 +806,19 @@ TEST(BinderRpc, Fds) { ASSERT_EQ(beforeFds, countFds()) << (system("ls -l /proc/self/fd/"), "fd leak?"); ASSERT_EQ(beforeFds, countFds()) << (system("ls -l /proc/self/fd/"), "fd leak?"); } } extern "C" int main(int argc, char** argv) { INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpc, ::testing::Values(SocketType::UNIX #ifdef __BIONIC__ , SocketType::VSOCK #endif // __BIONIC__ ), PrintSocketType); } // namespace android int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); ::testing::InitGoogleTest(&argc, argv); android::base::InitLogging(argv, android::base::StderrLogger, android::base::DefaultAborter); android::base::InitLogging(argv, android::base::StderrLogger, android::base::DefaultAborter); return RUN_ALL_TESTS(); return RUN_ALL_TESTS(); } } } // namespace android