diff options
| -rw-r--r-- | PREUPLOAD.cfg | 1 | ||||
| -rw-r--r-- | libs/binder/BpBinder.cpp | 9 | ||||
| -rw-r--r-- | libs/binder/RpcConnection.cpp | 158 | ||||
| -rw-r--r-- | libs/binder/include/binder/RpcConnection.h | 25 | ||||
| -rw-r--r-- | libs/binder/ndk/include_platform/android/binder_stability.h | 6 | ||||
| -rw-r--r-- | libs/binder/ndk/parcel_internal.h | 13 | ||||
| -rw-r--r-- | libs/binder/tests/Android.bp | 38 | ||||
| -rw-r--r-- | libs/binder/tests/binderRpcTest.cpp | 313 |
8 files changed, 387 insertions, 176 deletions
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index f494f6e661..16ebf6f107 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -5,6 +5,7 @@ clang_format = true # Only turn on clang-format check for the following subfolders. clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp cmds/idlcli/ + cmds/servicemanager/ include/input/ libs/binder/fuzzer/ libs/binder/ diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp index 825a821cc4..53b36fffdc 100644 --- a/libs/binder/BpBinder.cpp +++ b/libs/binder/BpBinder.cpp @@ -194,10 +194,13 @@ bool BpBinder::isDescriptorCached() const { const String16& BpBinder::getInterfaceDescriptor() const { if (isDescriptorCached() == false) { - Parcel send, reply; + sp<BpBinder> thiz = const_cast<BpBinder*>(this); + + Parcel data; + data.markForBinder(thiz); + Parcel reply; // do the IPC without a lock held. - status_t err = const_cast<BpBinder*>(this)->transact( - INTERFACE_TRANSACTION, send, &reply); + status_t err = thiz->transact(INTERFACE_TRANSACTION, data, &reply); if (err == NO_ERROR) { String16 res(reply.readString16()); Mutex::Autolock _l(mLock); diff --git a/libs/binder/RpcConnection.cpp b/libs/binder/RpcConnection.cpp index 83a1618e9f..dab3246fc5 100644 --- a/libs/binder/RpcConnection.cpp +++ b/libs/binder/RpcConnection.cpp @@ -20,6 +20,7 @@ #include <binder/Parcel.h> #include <binder/Stability.h> +#include <utils/String8.h> #include "RpcState.h" #include "RpcWireFormat.h" @@ -29,14 +30,20 @@ #include <sys/un.h> #include <unistd.h> -#if defined(__GLIBC__) +#ifdef __GLIBC__ extern "C" pid_t gettid(); #endif +#ifdef __BIONIC__ +#include <linux/vm_sockets.h> +#endif + namespace android { using base::unique_fd; +RpcConnection::SocketAddress::~SocketAddress() {} + RpcConnection::RpcConnection() { LOG_RPC_DETAIL("RpcConnection created %p", this); @@ -50,65 +57,68 @@ sp<RpcConnection> RpcConnection::make() { return new RpcConnection; } -bool RpcConnection::setupUnixDomainServer(const char* path) { - LOG_ALWAYS_FATAL_IF(mServer.get() != -1, "Only supports one server now"); - - unique_fd serverFd(TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0))); - if (serverFd == -1) { - ALOGE("Could not create socket at %s: %s", path, strerror(errno)); - return false; +class UnixSocketAddress : public RpcConnection::SocketAddress { +public: + explicit UnixSocketAddress(const char* path) : mAddr({.sun_family = AF_UNIX}) { + unsigned int pathLen = strlen(path) + 1; + LOG_ALWAYS_FATAL_IF(pathLen > sizeof(mAddr.sun_path), "%u %s", pathLen, path); + memcpy(mAddr.sun_path, path, pathLen); } - - struct sockaddr_un addr = { - .sun_family = AF_UNIX, - }; - - unsigned int pathLen = strlen(path) + 1; - LOG_ALWAYS_FATAL_IF(pathLen > sizeof(addr.sun_path), "%u", pathLen); - 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; + 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); } - if (0 != TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/))) { - ALOGE("Could not listen socket at %s: %s", path, strerror(errno)); - return false; - } +private: + sockaddr_un mAddr; +}; - mServer = std::move(serverFd); - return true; +bool RpcConnection::setupUnixDomainServer(const char* path) { + return addServer(UnixSocketAddress(path)); } bool RpcConnection::addUnixDomainClient(const char* path) { - LOG_RPC_DETAIL("Connecting on path: %s", path); + return addClient(UnixSocketAddress(path)); +} - unique_fd serverFd(TEMP_FAILURE_RETRY(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0))); - if (serverFd == -1) { - ALOGE("Could not create socket at %s: %s", path, strerror(errno)); - return false; +#ifdef __BIONIC__ + +class VsockSocketAddress : public RpcConnection::SocketAddress { +public: + VsockSocketAddress(unsigned int cid, unsigned int port) + : 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 = { - .sun_family = AF_UNIX, - }; +private: + sockaddr_vm mAddr; +}; - unsigned int pathLen = strlen(path) + 1; - LOG_ALWAYS_FATAL_IF(pathLen > sizeof(addr.sun_path), "%u", pathLen); - memcpy(addr.sun_path, path, pathLen); +bool RpcConnection::setupVsockServer(unsigned int port) { + // realizing value w/ this type at compile time to avoid ubsan abort + constexpr unsigned int kAnyCid = VMADDR_CID_ANY; - if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), (struct sockaddr*)&addr, sizeof(addr)))) { - ALOGE("Could not connect socket at %s: %s", path, strerror(errno)); - return false; - } - - LOG_RPC_DETAIL("Unix domain client with fd %d", serverFd.get()); + return addServer(VsockSocketAddress(kAnyCid, port)); +} - addClient(std::move(serverFd)); - return true; +bool RpcConnection::addVsockClient(unsigned int cid, unsigned int port) { + return addClient(VsockSocketAddress(cid, port)); } +#endif // __BIONIC__ + sp<IBinder> RpcConnection::getRootObject() { ExclusiveSocket socket(this, SocketUse::CLIENT); return state()->getRootObject(socket.fd(), this); @@ -130,11 +140,8 @@ status_t RpcConnection::sendDecStrong(const RpcAddress& address) { void RpcConnection::join() { // establish a connection { - struct sockaddr_un clientSa; - socklen_t clientSaLen = sizeof(clientSa); - - unique_fd clientFd(TEMP_FAILURE_RETRY( - accept4(mServer.get(), (struct sockaddr*)&clientSa, &clientSaLen, SOCK_CLOEXEC))); + unique_fd clientFd( + TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, 0 /*length*/, SOCK_CLOEXEC))); if (clientFd < 0) { // If this log becomes confusing, should save more state from setupUnixDomainServer // in order to output here. @@ -144,7 +151,7 @@ void RpcConnection::join() { 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 @@ -170,14 +177,57 @@ wp<RpcServer> RpcConnection::server() { 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); sp<ConnectionSocket> connection = new ConnectionSocket(); - connection->fd = std::move(fd); + connection->fd = std::move(serverFd); 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); sp<ConnectionSocket> connection = new ConnectionSocket(); connection->fd = std::move(fd); diff --git a/libs/binder/include/binder/RpcConnection.h b/libs/binder/include/binder/RpcConnection.h index 65c5232d46..a300575454 100644 --- a/libs/binder/include/binder/RpcConnection.h +++ b/libs/binder/include/binder/RpcConnection.h @@ -61,6 +61,18 @@ public: */ [[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 * process's RpcServer (if one exists) @@ -85,11 +97,20 @@ public: // internal only 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: RpcConnection(); - void addServer(base::unique_fd&& fd); - void addClient(base::unique_fd&& fd); + bool addServer(const SocketAddress& address); + bool addClient(const SocketAddress& address); + void assignServerToThisThread(base::unique_fd&& fd); struct ConnectionSocket : public RefBase { base::unique_fd fd; diff --git a/libs/binder/ndk/include_platform/android/binder_stability.h b/libs/binder/ndk/include_platform/android/binder_stability.h index ce7255e174..c23716c778 100644 --- a/libs/binder/ndk/include_platform/android/binder_stability.h +++ b/libs/binder/ndk/include_platform/android/binder_stability.h @@ -65,6 +65,12 @@ static inline void AIBinder_markCompilationUnitStability(AIBinder* binder) { #endif // defined(__ANDROID_VENDOR__) /** + * WARNING: this is not expected to be used manually. When the build system has + * versioned checks in place for an interface that prevent it being changed year + * over year (specifically like those for @VintfStability stable AIDL + * interfaces), this could be called. Calling this without this or equivalent + * infrastructure will lead to de facto frozen APIs or GSI test failures. + * * This interface has system<->vendor stability */ void AIBinder_markVintfStability(AIBinder* binder); diff --git a/libs/binder/ndk/parcel_internal.h b/libs/binder/ndk/parcel_internal.h index 6b7295e4b9..aebc7f4539 100644 --- a/libs/binder/ndk/parcel_internal.h +++ b/libs/binder/ndk/parcel_internal.h @@ -27,10 +27,13 @@ struct AParcel { const ::android::Parcel* get() const { return mParcel; } ::android::Parcel* get() { return mParcel; } - explicit AParcel(const AIBinder* binder) - : AParcel(binder, new ::android::Parcel, true /*owns*/) {} - AParcel(const AIBinder* binder, ::android::Parcel* parcel, bool owns) - : mBinder(binder), mParcel(parcel), mOwns(owns) {} + explicit AParcel(AIBinder* binder) : AParcel(binder, new ::android::Parcel, true /*owns*/) {} + AParcel(AIBinder* binder, ::android::Parcel* parcel, bool owns) + : mBinder(binder), mParcel(parcel), mOwns(owns) { + if (binder != nullptr) { + parcel->markForBinder(binder->getBinder()); + } + } ~AParcel() { if (mOwns) { @@ -38,7 +41,7 @@ struct AParcel { } } - static const AParcel readOnly(const AIBinder* binder, const ::android::Parcel* parcel) { + static const AParcel readOnly(AIBinder* binder, const ::android::Parcel* parcel) { return AParcel(binder, const_cast<::android::Parcel*>(parcel), false); } diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp index a44cddf761..afc4b1b72c 100644 --- a/libs/binder/tests/Android.bp +++ b/libs/binder/tests/Android.bp @@ -104,22 +104,49 @@ cc_test { require_root: true, } +aidl_interface { + name: "binderRpcTestIface", + host_supported: true, + unstable: true, + srcs: [ + "IBinderRpcSession.aidl", + "IBinderRpcTest.aidl", + ], + backend: { + java: { + enabled: false, + }, + }, +} + cc_test { name: "binderRpcTest", - defaults: ["binder_test_defaults"], + host_supported: true, + target: { + darwin: { + enabled: false, + }, + }, + defaults: [ + "binder_test_defaults", + "libbinder_ndk_host_user", + ], srcs: [ - "IBinderRpcSession.aidl", - "IBinderRpcTest.aidl", "binderRpcTest.cpp", ], shared_libs: [ "libbinder", + "libbinder_ndk", "libbase", "libutils", "libcutils", "liblog", ], + static_libs: [ + "binderRpcTestIface-cpp", + "binderRpcTestIface-ndk_platform", + ], test_suites: ["general-tests"], require_root: true, } @@ -210,6 +237,11 @@ aidl_interface { srcs: [ "IBinderStabilityTest.aidl", ], + backend: { + java: { + enabled: false, + }, + }, } cc_test { diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index 6fa53330ef..27f18df096 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -14,17 +14,12 @@ * limitations under the License. */ -#include <sys/prctl.h> -#include <unistd.h> - -#include <chrono> -#include <cstdlib> -#include <iostream> -#include <thread> - #include <BnBinderRpcSession.h> #include <BnBinderRpcTest.h> +#include <aidl/IBinderRpcTest.h> #include <android-base/logging.h> +#include <android/binder_auto_utils.h> +#include <android/binder_libbinder.h> #include <binder/Binder.h> #include <binder/BpBinder.h> #include <binder/IServiceManager.h> @@ -33,6 +28,18 @@ #include <binder/RpcServer.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 namespace android { @@ -185,8 +192,13 @@ private: static std::string allocateSocketAddress() { static size_t id = 0; + static bool gUseTmp = access("/tmp/", F_OK) != -1; - return "/dev/binderRpcTest_" + std::to_string(id++); + if (gUseTmp) { + return "/tmp/binderRpcTest_" + std::to_string(id++); + } else { + return "/dev/binderRpcTest_" + std::to_string(id++); + } }; struct ProcessConnection { @@ -214,58 +226,6 @@ struct ProcessConnection { } }; -// This creates a new process serving an interface on a certain number of -// threads. -ProcessConnection createRpcTestSocketServerProcess( - size_t numThreads, - const std::function<void(const sp<RpcServer>&, const sp<RpcConnection>&)>& configure) { - CHECK_GT(numThreads, 0); - - std::string addr = allocateSocketAddress(); - unlink(addr.c_str()); - - auto ret = ProcessConnection{ - .host = Process([&] { - sp<RpcServer> server = RpcServer::make(); - - server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); - - // server supporting one client on one socket - sp<RpcConnection> connection = server->addClientConnection(); - CHECK(connection->setupUnixDomainServer(addr.c_str())) << addr; - - configure(server, connection); - - // accept 'numThreads' connections - std::vector<std::thread> pool; - for (size_t i = 0; i + 1 < numThreads; i++) { - pool.push_back(std::thread([=] { connection->join(); })); - } - connection->join(); - for (auto& t : pool) t.join(); - }), - .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 - for (size_t i = 0; i < numThreads; i++) { - // Connection refused sometimes after file created but before listening. - CHECK(ret.connection->addUnixDomainClient(addr.c_str()) || - (usleep(10000), ret.connection->addUnixDomainClient(addr.c_str()))) - << i; - } - - ret.rootBinder = ret.connection->getRootObject(); - return ret; -} - // Process connection where the process hosts IBinderRpcTest, the server used // for most testing here struct BinderRpcTestProcessConnection { @@ -290,26 +250,122 @@ struct BinderRpcTestProcessConnection { } }; -BinderRpcTestProcessConnection createRpcTestSocketServerProcess(size_t numThreads) { - BinderRpcTestProcessConnection ret{ - .proc = createRpcTestSocketServerProcess(numThreads, - [&](const sp<RpcServer>& server, - const sp<RpcConnection>& connection) { - sp<MyBinderRpcTest> service = - new MyBinderRpcTest; - server->setRootObject(service); - service->connection = - connection; // for testing only - }), - }; - - ret.rootBinder = ret.proc.rootBinder; - ret.rootIface = interface_cast<IBinderRpcTest>(ret.rootBinder); +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 + // threads. + ProcessConnection createRpcTestSocketServerProcess( + size_t numThreads, + const std::function<void(const sp<RpcServer>&, const sp<RpcConnection>&)>& configure) { + CHECK_GT(numThreads, 0); + + SocketType socketType = GetParam(); + + std::string addr = allocateSocketAddress(); + unlink(addr.c_str()); + static unsigned int port = 3456; + port++; + + auto ret = ProcessConnection{ + .host = Process([&] { + sp<RpcServer> server = RpcServer::make(); + + server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); + + // server supporting one client on one socket + sp<RpcConnection> connection = server->addClientConnection(); + + switch (socketType) { + case SocketType::UNIX: + 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); + + // accept 'numThreads' connections + std::vector<std::thread> pool; + for (size_t i = 0; i + 1 < numThreads; i++) { + pool.push_back(std::thread([=] { connection->join(); })); + } + connection->join(); + for (auto& t : pool) t.join(); + }), + .connection = RpcConnection::make(), + }; + + // create remainder of connections + for (size_t i = 0; i < numThreads; i++) { + for (size_t tries = 0; tries < 5; tries++) { + usleep(10000); + switch (socketType) { + 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"); + } + } + LOG_ALWAYS_FATAL("Could not connect"); + success:; + } - return ret; -} + ret.rootBinder = ret.connection->getRootObject(); + return ret; + } + + BinderRpcTestProcessConnection createRpcTestSocketServerProcess(size_t numThreads) { + BinderRpcTestProcessConnection ret{ + .proc = createRpcTestSocketServerProcess(numThreads, + [&](const sp<RpcServer>& server, + const sp<RpcConnection>& connection) { + sp<MyBinderRpcTest> service = + new MyBinderRpcTest; + server->setRootObject(service); + service->connection = + connection; // for testing only + }), + }; + + ret.rootBinder = ret.proc.rootBinder; + ret.rootIface = interface_cast<IBinderRpcTest>(ret.rootBinder); -TEST(BinderRpc, RootObjectIsNull) { + return ret; + } +}; + +TEST_P(BinderRpc, RootObjectIsNull) { auto proc = createRpcTestSocketServerProcess(1, [](const sp<RpcServer>& server, const sp<RpcConnection>&) { @@ -324,20 +380,26 @@ TEST(BinderRpc, RootObjectIsNull) { EXPECT_EQ(nullptr, proc.connection->getRootObject()); } -TEST(BinderRpc, Ping) { +TEST_P(BinderRpc, Ping) { auto proc = createRpcTestSocketServerProcess(1); ASSERT_NE(proc.rootBinder, nullptr); EXPECT_EQ(OK, proc.rootBinder->pingBinder()); } -TEST(BinderRpc, TransactionsMustBeMarkedRpc) { +TEST_P(BinderRpc, GetInterfaceDescriptor) { + auto proc = createRpcTestSocketServerProcess(1); + ASSERT_NE(proc.rootBinder, nullptr); + EXPECT_EQ(IBinderRpcTest::descriptor, proc.rootBinder->getInterfaceDescriptor()); +} + +TEST_P(BinderRpc, TransactionsMustBeMarkedRpc) { auto proc = createRpcTestSocketServerProcess(1); Parcel data; Parcel reply; EXPECT_EQ(BAD_TYPE, proc.rootBinder->transact(IBinder::PING_TRANSACTION, data, &reply, 0)); } -TEST(BinderRpc, UnknownTransaction) { +TEST_P(BinderRpc, UnknownTransaction) { auto proc = createRpcTestSocketServerProcess(1); Parcel data; data.markForBinder(proc.rootBinder); @@ -345,19 +407,19 @@ TEST(BinderRpc, UnknownTransaction) { EXPECT_EQ(UNKNOWN_TRANSACTION, proc.rootBinder->transact(1337, data, &reply, 0)); } -TEST(BinderRpc, SendSomethingOneway) { +TEST_P(BinderRpc, SendSomethingOneway) { auto proc = createRpcTestSocketServerProcess(1); EXPECT_OK(proc.rootIface->sendString("asdf")); } -TEST(BinderRpc, SendAndGetResultBack) { +TEST_P(BinderRpc, SendAndGetResultBack) { auto proc = createRpcTestSocketServerProcess(1); std::string doubled; EXPECT_OK(proc.rootIface->doubleString("cool ", &doubled)); EXPECT_EQ("cool cool ", doubled); } -TEST(BinderRpc, SendAndGetResultBackBig) { +TEST_P(BinderRpc, SendAndGetResultBackBig) { auto proc = createRpcTestSocketServerProcess(1); std::string single = std::string(1024, 'a'); std::string doubled; @@ -365,7 +427,7 @@ TEST(BinderRpc, SendAndGetResultBackBig) { EXPECT_EQ(single + single, doubled); } -TEST(BinderRpc, CallMeBack) { +TEST_P(BinderRpc, CallMeBack) { auto proc = createRpcTestSocketServerProcess(1); int32_t pingResult; @@ -375,7 +437,7 @@ TEST(BinderRpc, CallMeBack) { EXPECT_EQ(0, MyBinderRpcSession::gNum); } -TEST(BinderRpc, RepeatBinder) { +TEST_P(BinderRpc, RepeatBinder) { auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> inBinder = new MyBinderRpcSession("foo"); @@ -397,7 +459,7 @@ TEST(BinderRpc, RepeatBinder) { EXPECT_EQ(0, MyBinderRpcSession::gNum); } -TEST(BinderRpc, RepeatTheirBinder) { +TEST_P(BinderRpc, RepeatTheirBinder) { auto proc = createRpcTestSocketServerProcess(1); sp<IBinderRpcSession> session; @@ -421,7 +483,7 @@ TEST(BinderRpc, RepeatTheirBinder) { EXPECT_EQ(nullptr, weak.promote()); } -TEST(BinderRpc, RepeatBinderNull) { +TEST_P(BinderRpc, RepeatBinderNull) { auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> outBinder; @@ -429,7 +491,7 @@ TEST(BinderRpc, RepeatBinderNull) { EXPECT_EQ(nullptr, outBinder); } -TEST(BinderRpc, HoldBinder) { +TEST_P(BinderRpc, HoldBinder) { auto proc = createRpcTestSocketServerProcess(1); IBinder* ptr = nullptr; @@ -455,7 +517,7 @@ TEST(BinderRpc, HoldBinder) { // These are behavioral differences form regular binder, where certain usecases // aren't supported. -TEST(BinderRpc, CannotMixBindersBetweenUnrelatedSocketConnections) { +TEST_P(BinderRpc, CannotMixBindersBetweenUnrelatedSocketConnections) { auto proc1 = createRpcTestSocketServerProcess(1); auto proc2 = createRpcTestSocketServerProcess(1); @@ -464,7 +526,7 @@ TEST(BinderRpc, CannotMixBindersBetweenUnrelatedSocketConnections) { proc1.rootIface->repeatBinder(proc2.rootBinder, &outBinder).transactionError()); } -TEST(BinderRpc, CannotSendRegularBinderOverSocketBinder) { +TEST_P(BinderRpc, CannotSendRegularBinderOverSocketBinder) { auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> someRealBinder = IInterface::asBinder(defaultServiceManager()); @@ -473,7 +535,7 @@ TEST(BinderRpc, CannotSendRegularBinderOverSocketBinder) { proc.rootIface->repeatBinder(someRealBinder, &outBinder).transactionError()); } -TEST(BinderRpc, CannotSendSocketBinderOverRegularBinder) { +TEST_P(BinderRpc, CannotSendSocketBinderOverRegularBinder) { auto proc = createRpcTestSocketServerProcess(1); // for historical reasons, IServiceManager interface only returns the @@ -484,7 +546,7 @@ TEST(BinderRpc, CannotSendSocketBinderOverRegularBinder) { // END TESTS FOR LIMITATIONS OF SOCKET BINDER -TEST(BinderRpc, RepeatRootObject) { +TEST_P(BinderRpc, RepeatRootObject) { auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> outBinder; @@ -492,7 +554,7 @@ TEST(BinderRpc, RepeatRootObject) { EXPECT_EQ(proc.rootBinder, outBinder); } -TEST(BinderRpc, NestedTransactions) { +TEST_P(BinderRpc, NestedTransactions) { auto proc = createRpcTestSocketServerProcess(1); auto nastyNester = sp<MyBinderRpcTest>::make(); @@ -503,7 +565,7 @@ TEST(BinderRpc, NestedTransactions) { EXPECT_EQ(nullptr, weak.promote()); } -TEST(BinderRpc, SameBinderEquality) { +TEST_P(BinderRpc, SameBinderEquality) { auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> a; @@ -515,7 +577,7 @@ TEST(BinderRpc, SameBinderEquality) { EXPECT_EQ(a, b); } -TEST(BinderRpc, SameBinderEqualityWeak) { +TEST_P(BinderRpc, SameBinderEqualityWeak) { auto proc = createRpcTestSocketServerProcess(1); sp<IBinder> a; @@ -547,7 +609,7 @@ TEST(BinderRpc, SameBinderEqualityWeak) { EXPECT_EQ(expected, session); \ } while (false) -TEST(BinderRpc, SingleSession) { +TEST_P(BinderRpc, SingleSession) { auto proc = createRpcTestSocketServerProcess(1); sp<IBinderRpcSession> session; @@ -561,7 +623,7 @@ TEST(BinderRpc, SingleSession) { expectSessions(0, proc.rootIface); } -TEST(BinderRpc, ManySessions) { +TEST_P(BinderRpc, ManySessions) { auto proc = createRpcTestSocketServerProcess(1); std::vector<sp<IBinderRpcSession>> sessions; @@ -595,7 +657,7 @@ size_t epochMillis() { return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); } -TEST(BinderRpc, ThreadPoolGreaterThanEqualRequested) { +TEST_P(BinderRpc, ThreadPoolGreaterThanEqualRequested) { constexpr size_t kNumThreads = 10; auto proc = createRpcTestSocketServerProcess(kNumThreads); @@ -627,7 +689,7 @@ TEST(BinderRpc, ThreadPoolGreaterThanEqualRequested) { for (auto& t : ts) t.join(); } -TEST(BinderRpc, ThreadPoolOverSaturated) { +TEST_P(BinderRpc, ThreadPoolOverSaturated) { constexpr size_t kNumThreads = 10; constexpr size_t kNumCalls = kNumThreads + 3; constexpr size_t kSleepMs = 500; @@ -651,7 +713,7 @@ TEST(BinderRpc, ThreadPoolOverSaturated) { EXPECT_LE(epochMsAfter, epochMsBefore + 3 * kSleepMs); } -TEST(BinderRpc, ThreadingStressTest) { +TEST_P(BinderRpc, ThreadingStressTest) { constexpr size_t kNumClientThreads = 10; constexpr size_t kNumServerThreads = 10; constexpr size_t kNumCalls = 100; @@ -672,7 +734,7 @@ TEST(BinderRpc, ThreadingStressTest) { for (auto& t : threads) t.join(); } -TEST(BinderRpc, OnewayCallDoesNotWait) { +TEST_P(BinderRpc, OnewayCallDoesNotWait) { constexpr size_t kReallyLongTimeMs = 100; constexpr size_t kSleepMs = kReallyLongTimeMs * 5; @@ -687,7 +749,7 @@ TEST(BinderRpc, OnewayCallDoesNotWait) { EXPECT_LT(epochMsAfter, epochMsBefore + kReallyLongTimeMs); } -TEST(BinderRpc, OnewayCallQueueing) { +TEST_P(BinderRpc, OnewayCallQueueing) { constexpr size_t kNumSleeps = 10; constexpr size_t kNumExtraServerThreads = 4; constexpr size_t kSleepMs = 50; @@ -711,7 +773,7 @@ TEST(BinderRpc, OnewayCallQueueing) { EXPECT_GT(epochMsAfter, epochMsBefore + kSleepMs * kNumSleeps); } -TEST(BinderRpc, Die) { +TEST_P(BinderRpc, Die) { // TODO(b/183141167): handle this in library signal(SIGPIPE, SIG_IGN); @@ -733,6 +795,30 @@ TEST(BinderRpc, Die) { } } +TEST_P(BinderRpc, WorksWithLibbinderNdkPing) { + auto proc = createRpcTestSocketServerProcess(1); + + ndk::SpAIBinder binder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(proc.rootBinder)); + ASSERT_NE(binder, nullptr); + + ASSERT_EQ(STATUS_OK, AIBinder_ping(binder.get())); +} + +TEST_P(BinderRpc, WorksWithLibbinderNdkUserTransaction) { + auto proc = createRpcTestSocketServerProcess(1); + + ndk::SpAIBinder binder = ndk::SpAIBinder(AIBinder_fromPlatformBinder(proc.rootBinder)); + ASSERT_NE(binder, nullptr); + + auto ndkBinder = aidl::IBinderRpcTest::fromBinder(binder); + ASSERT_NE(ndkBinder, nullptr); + + std::string out; + ndk::ScopedAStatus status = ndkBinder->doubleString("aoeu", &out); + ASSERT_TRUE(status.isOk()) << status.getDescription(); + ASSERT_EQ("aoeuaoeu", out); +} + ssize_t countFds() { DIR* dir = opendir("/proc/self/fd/"); if (dir == nullptr) return -1; @@ -743,7 +829,7 @@ ssize_t countFds() { return ret; } -TEST(BinderRpc, Fds) { +TEST_P(BinderRpc, Fds) { ssize_t beforeFds = countFds(); ASSERT_GE(beforeFds, 0); { @@ -753,10 +839,19 @@ TEST(BinderRpc, Fds) { 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); android::base::InitLogging(argv, android::base::StderrLogger, android::base::DefaultAborter); return RUN_ALL_TESTS(); } - -} // namespace android |