diff options
| -rw-r--r-- | libs/binder/RpcServer.cpp | 18 | ||||
| -rw-r--r-- | libs/binder/include/binder/RpcServer.h | 11 | ||||
| -rw-r--r-- | libs/binder/tests/binderRpcTest.cpp | 13 |
3 files changed, 42 insertions, 0 deletions
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp index dc10d1c524..9cc6e7fe04 100644 --- a/libs/binder/RpcServer.cpp +++ b/libs/binder/RpcServer.cpp @@ -272,8 +272,26 @@ void RpcServer::onSessionTerminating(const sp<RpcSession>& session) { } bool RpcServer::hasServer() { + LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); std::lock_guard<std::mutex> _l(mLock); return mServer.ok(); } +unique_fd RpcServer::releaseServer() { + LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); + std::lock_guard<std::mutex> _l(mLock); + return std::move(mServer); +} + +bool RpcServer::setupExternalServer(base::unique_fd serverFd) { + LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); + std::lock_guard<std::mutex> _l(mLock); + if (mServer.ok()) { + ALOGE("Each RpcServer can only have one server."); + return false; + } + mServer = std::move(serverFd); + return true; +} + } // namespace android diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h index 771bbe68b8..8f0c6fd5e1 100644 --- a/libs/binder/include/binder/RpcServer.h +++ b/libs/binder/include/binder/RpcServer.h @@ -79,6 +79,17 @@ public: */ [[nodiscard]] bool hasServer(); + /** + * If hasServer(), return the server FD. Otherwise return invalid FD. + */ + [[nodiscard]] base::unique_fd releaseServer(); + + /** + * Set up server using an external FD previously set up by releaseServer(). + * Return false if there's already a server. + */ + bool setupExternalServer(base::unique_fd serverFd); + void iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); /** diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp index 260be570f9..a96deb5d27 100644 --- a/libs/binder/tests/binderRpcTest.cpp +++ b/libs/binder/tests/binderRpcTest.cpp @@ -49,6 +49,19 @@ TEST(BinderRpcParcel, EntireParcelFormatted) { EXPECT_DEATH(p.markForBinder(sp<BBinder>::make()), ""); } +TEST(BinderRpc, SetExternalServer) { + base::unique_fd sink(TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR))); + int sinkFd = sink.get(); + auto server = RpcServer::make(); + server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction(); + ASSERT_FALSE(server->hasServer()); + ASSERT_TRUE(server->setupExternalServer(std::move(sink))); + ASSERT_TRUE(server->hasServer()); + base::unique_fd retrieved = server->releaseServer(); + ASSERT_FALSE(server->hasServer()); + ASSERT_EQ(sinkFd, retrieved.get()); +} + using android::binder::Status; #define EXPECT_OK(status) \ |