Loading libs/binder/RpcSession.cpp +7 −3 Original line number Original line Diff line number Diff line Loading @@ -188,7 +188,9 @@ status_t RpcSession::setupInetClient(const char* addr, unsigned int port) { } } status_t RpcSession::setupPreconnectedClient(unique_fd fd, std::function<unique_fd()>&& request) { status_t RpcSession::setupPreconnectedClient(unique_fd fd, std::function<unique_fd()>&& request) { return setupClient([&](const std::vector<uint8_t>& sessionId, bool incoming) -> status_t { return setupClient([&, fd = std::move(fd), request = std::move(request)](const std::vector<uint8_t>& sessionId, bool incoming) mutable -> status_t { if (!fd.ok()) { if (!fd.ok()) { fd = request(); fd = request(); if (!fd.ok()) return BAD_VALUE; if (!fd.ok()) return BAD_VALUE; Loading Loading @@ -476,8 +478,10 @@ sp<RpcServer> RpcSession::server() { return server; return server; } } status_t RpcSession::setupClient(const std::function<status_t(const std::vector<uint8_t>& sessionId, template <typename Fn, bool incoming)>& connectAndInit) { typename /* = std::enable_if_t<std::is_invocable_r_v< status_t, Fn, const std::vector<uint8_t>&, bool>> */> status_t RpcSession::setupClient(Fn&& connectAndInit) { { { RpcMutexLockGuard _l(mMutex); RpcMutexLockGuard _l(mMutex); LOG_ALWAYS_FATAL_IF(mStartedSetup, "Must only setup session once"); LOG_ALWAYS_FATAL_IF(mStartedSetup, "Must only setup session once"); Loading libs/binder/include/binder/RpcSession.h +9 −3 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <map> #include <map> #include <optional> #include <optional> #include <type_traits> #include <vector> #include <vector> namespace android { namespace android { Loading Loading @@ -291,9 +292,14 @@ private: // join on thread passed to preJoinThreadOwnership // join on thread passed to preJoinThreadOwnership static void join(sp<RpcSession>&& session, PreJoinSetupResult&& result); static void join(sp<RpcSession>&& session, PreJoinSetupResult&& result); [[nodiscard]] status_t setupClient( // This is a workaround to support move-only functors. const std::function<status_t(const std::vector<uint8_t>& sessionId, bool incoming)>& // TODO: use std::move_only_function when it becomes available. connectAndInit); template <typename Fn, // Fn must be a callable type taking (const std::vector<uint8_t>&, bool) and returning // status_t typename = std::enable_if_t< std::is_invocable_r_v<status_t, Fn, const std::vector<uint8_t>&, bool>>> [[nodiscard]] status_t setupClient(Fn&& connectAndInit); [[nodiscard]] status_t setupSocketClient(const RpcSocketAddress& address); [[nodiscard]] status_t setupSocketClient(const RpcSocketAddress& address); [[nodiscard]] status_t setupOneSocketConnection(const RpcSocketAddress& address, [[nodiscard]] status_t setupOneSocketConnection(const RpcSocketAddress& address, const std::vector<uint8_t>& sessionId, const std::vector<uint8_t>& sessionId, Loading libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp +6 −1 Original line number Original line Diff line number Diff line Loading @@ -134,9 +134,14 @@ AIBinder* ARpcSession_setupInet(ARpcSession* session, const char* address, unsig // // // param will be passed to requestFd. Callers can use param to pass contexts to // param will be passed to requestFd. Callers can use param to pass contexts to // the requestFd function. // the requestFd function. // // paramDeleteFd will be called when requestFd and param are no longer in use. // Callers can pass a function deleting param if necessary. Callers can set // paramDeleteFd to null if callers doesn't need to clean up param. AIBinder* ARpcSession_setupPreconnectedClient(ARpcSession* session, AIBinder* ARpcSession_setupPreconnectedClient(ARpcSession* session, int (*requestFd)(void* param), int (*requestFd)(void* param), void* param); void* param, void (*paramDeleteFd)(void* param)); // Sets the file descriptor transport mode for this session. // Sets the file descriptor transport mode for this session. void ARpcSession_setFileDescriptorTransportMode(ARpcSession* session, void ARpcSession_setFileDescriptorTransportMode(ARpcSession* session, Loading libs/binder/libbinder_rpc_unstable.cpp +11 −2 Original line number Original line Diff line number Diff line Loading @@ -248,9 +248,18 @@ AIBinder* ARpcSession_setupInet(ARpcSession* handle, const char* address, unsign #endif // __TRUSTY__ #endif // __TRUSTY__ AIBinder* ARpcSession_setupPreconnectedClient(ARpcSession* handle, int (*requestFd)(void* param), AIBinder* ARpcSession_setupPreconnectedClient(ARpcSession* handle, int (*requestFd)(void* param), void* param) { void* param, void (*paramDeleteFd)(void* param)) { auto session = handleToStrongPointer<RpcSession>(handle); auto session = handleToStrongPointer<RpcSession>(handle); auto request = [=] { return unique_fd{requestFd(param)}; }; auto deleter = [=](void* param) { if (paramDeleteFd) { paramDeleteFd(param); } }; // TODO: use unique_ptr once setupPreconnectedClient uses std::move_only_function. std::shared_ptr<void> sharedParam(param, deleter); auto request = [=, sharedParam = std::move(sharedParam)] { return unique_fd{requestFd(sharedParam.get())}; }; if (status_t status = session->setupPreconnectedClient(unique_fd{}, request); status != OK) { if (status_t status = session->setupPreconnectedClient(unique_fd{}, request); status != OK) { ALOGE("Failed to set up preconnected client. error: %s", statusToString(status).c_str()); ALOGE("Failed to set up preconnected client. error: %s", statusToString(status).c_str()); return nullptr; return nullptr; Loading libs/binder/rust/rpcbinder/src/session.rs +15 −7 Original line number Original line Diff line number Diff line Loading @@ -195,11 +195,13 @@ impl RpcSessionRef { /// take ownership of) file descriptors already connected to it. /// take ownership of) file descriptors already connected to it. pub fn setup_preconnected_client<T: FromIBinder + ?Sized>( pub fn setup_preconnected_client<T: FromIBinder + ?Sized>( &self, &self, mut request_fd: impl FnMut() -> Option<RawFd>, request_fd: impl FnMut() -> Option<RawFd>, ) -> Result<Strong<T>, StatusCode> { ) -> Result<Strong<T>, StatusCode> { // Double reference the factory because trait objects aren't FFI safe. // Trait objects aren't FFI safe, so *mut c_void can't be converted back to let mut request_fd_ref: RequestFd = &mut request_fd; // *mut dyn FnMut() -> Option<RawFd>>. Double box the factory to make it possible to get let param = &mut request_fd_ref as *mut RequestFd as *mut c_void; // the factory from *mut c_void (to *mut Box<dyn<...>>) in the callbacks. let request_fd_box: Box<dyn FnMut() -> Option<RawFd>> = Box::new(request_fd); let param = Box::into_raw(Box::new(request_fd_box)) as *mut c_void; // SAFETY: AIBinder returned by RpcPreconnectedClient has correct reference count, and the // SAFETY: AIBinder returned by RpcPreconnectedClient has correct reference count, and the // ownership can be safely taken by new_spibinder. RpcPreconnectedClient does not take ownership // ownership can be safely taken by new_spibinder. RpcPreconnectedClient does not take ownership Loading @@ -209,6 +211,7 @@ impl RpcSessionRef { self.as_ptr(), self.as_ptr(), Some(request_fd_wrapper), Some(request_fd_wrapper), param, param, Some(param_delete_fd_wrapper), )) )) }; }; Self::get_interface(service) Self::get_interface(service) Loading @@ -225,13 +228,18 @@ impl RpcSessionRef { } } } } type RequestFd<'a> = &'a mut dyn FnMut() -> Option<RawFd>; unsafe extern "C" fn request_fd_wrapper(param: *mut c_void) -> c_int { unsafe extern "C" fn request_fd_wrapper(param: *mut c_void) -> c_int { let request_fd_ptr = param as *mut RequestFd; let request_fd_ptr = param as *mut Box<dyn FnMut() -> Option<RawFd>>; // SAFETY: This is only ever called by RpcPreconnectedClient, within the lifetime of the // SAFETY: This is only ever called by RpcPreconnectedClient, within the lifetime of the // BinderFdFactory reference, with param being a properly aligned non-null pointer to an // BinderFdFactory reference, with param being a properly aligned non-null pointer to an // initialized instance. // initialized instance. let request_fd = unsafe { request_fd_ptr.as_mut().unwrap() }; let request_fd = unsafe { request_fd_ptr.as_mut().unwrap() }; request_fd().unwrap_or(-1) request_fd().unwrap_or(-1) } } unsafe extern "C" fn param_delete_fd_wrapper(param: *mut c_void) { // SAFETY: This is only ever called by RpcPreconnectedClient, with param being the // pointer returned from Box::into_raw. let request_fd_box = unsafe { Box::from_raw(param as *mut Box<dyn FnMut() -> Option<RawFd>>) }; drop(request_fd_box); } Loading
libs/binder/RpcSession.cpp +7 −3 Original line number Original line Diff line number Diff line Loading @@ -188,7 +188,9 @@ status_t RpcSession::setupInetClient(const char* addr, unsigned int port) { } } status_t RpcSession::setupPreconnectedClient(unique_fd fd, std::function<unique_fd()>&& request) { status_t RpcSession::setupPreconnectedClient(unique_fd fd, std::function<unique_fd()>&& request) { return setupClient([&](const std::vector<uint8_t>& sessionId, bool incoming) -> status_t { return setupClient([&, fd = std::move(fd), request = std::move(request)](const std::vector<uint8_t>& sessionId, bool incoming) mutable -> status_t { if (!fd.ok()) { if (!fd.ok()) { fd = request(); fd = request(); if (!fd.ok()) return BAD_VALUE; if (!fd.ok()) return BAD_VALUE; Loading Loading @@ -476,8 +478,10 @@ sp<RpcServer> RpcSession::server() { return server; return server; } } status_t RpcSession::setupClient(const std::function<status_t(const std::vector<uint8_t>& sessionId, template <typename Fn, bool incoming)>& connectAndInit) { typename /* = std::enable_if_t<std::is_invocable_r_v< status_t, Fn, const std::vector<uint8_t>&, bool>> */> status_t RpcSession::setupClient(Fn&& connectAndInit) { { { RpcMutexLockGuard _l(mMutex); RpcMutexLockGuard _l(mMutex); LOG_ALWAYS_FATAL_IF(mStartedSetup, "Must only setup session once"); LOG_ALWAYS_FATAL_IF(mStartedSetup, "Must only setup session once"); Loading
libs/binder/include/binder/RpcSession.h +9 −3 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,7 @@ #include <map> #include <map> #include <optional> #include <optional> #include <type_traits> #include <vector> #include <vector> namespace android { namespace android { Loading Loading @@ -291,9 +292,14 @@ private: // join on thread passed to preJoinThreadOwnership // join on thread passed to preJoinThreadOwnership static void join(sp<RpcSession>&& session, PreJoinSetupResult&& result); static void join(sp<RpcSession>&& session, PreJoinSetupResult&& result); [[nodiscard]] status_t setupClient( // This is a workaround to support move-only functors. const std::function<status_t(const std::vector<uint8_t>& sessionId, bool incoming)>& // TODO: use std::move_only_function when it becomes available. connectAndInit); template <typename Fn, // Fn must be a callable type taking (const std::vector<uint8_t>&, bool) and returning // status_t typename = std::enable_if_t< std::is_invocable_r_v<status_t, Fn, const std::vector<uint8_t>&, bool>>> [[nodiscard]] status_t setupClient(Fn&& connectAndInit); [[nodiscard]] status_t setupSocketClient(const RpcSocketAddress& address); [[nodiscard]] status_t setupSocketClient(const RpcSocketAddress& address); [[nodiscard]] status_t setupOneSocketConnection(const RpcSocketAddress& address, [[nodiscard]] status_t setupOneSocketConnection(const RpcSocketAddress& address, const std::vector<uint8_t>& sessionId, const std::vector<uint8_t>& sessionId, Loading
libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp +6 −1 Original line number Original line Diff line number Diff line Loading @@ -134,9 +134,14 @@ AIBinder* ARpcSession_setupInet(ARpcSession* session, const char* address, unsig // // // param will be passed to requestFd. Callers can use param to pass contexts to // param will be passed to requestFd. Callers can use param to pass contexts to // the requestFd function. // the requestFd function. // // paramDeleteFd will be called when requestFd and param are no longer in use. // Callers can pass a function deleting param if necessary. Callers can set // paramDeleteFd to null if callers doesn't need to clean up param. AIBinder* ARpcSession_setupPreconnectedClient(ARpcSession* session, AIBinder* ARpcSession_setupPreconnectedClient(ARpcSession* session, int (*requestFd)(void* param), int (*requestFd)(void* param), void* param); void* param, void (*paramDeleteFd)(void* param)); // Sets the file descriptor transport mode for this session. // Sets the file descriptor transport mode for this session. void ARpcSession_setFileDescriptorTransportMode(ARpcSession* session, void ARpcSession_setFileDescriptorTransportMode(ARpcSession* session, Loading
libs/binder/libbinder_rpc_unstable.cpp +11 −2 Original line number Original line Diff line number Diff line Loading @@ -248,9 +248,18 @@ AIBinder* ARpcSession_setupInet(ARpcSession* handle, const char* address, unsign #endif // __TRUSTY__ #endif // __TRUSTY__ AIBinder* ARpcSession_setupPreconnectedClient(ARpcSession* handle, int (*requestFd)(void* param), AIBinder* ARpcSession_setupPreconnectedClient(ARpcSession* handle, int (*requestFd)(void* param), void* param) { void* param, void (*paramDeleteFd)(void* param)) { auto session = handleToStrongPointer<RpcSession>(handle); auto session = handleToStrongPointer<RpcSession>(handle); auto request = [=] { return unique_fd{requestFd(param)}; }; auto deleter = [=](void* param) { if (paramDeleteFd) { paramDeleteFd(param); } }; // TODO: use unique_ptr once setupPreconnectedClient uses std::move_only_function. std::shared_ptr<void> sharedParam(param, deleter); auto request = [=, sharedParam = std::move(sharedParam)] { return unique_fd{requestFd(sharedParam.get())}; }; if (status_t status = session->setupPreconnectedClient(unique_fd{}, request); status != OK) { if (status_t status = session->setupPreconnectedClient(unique_fd{}, request); status != OK) { ALOGE("Failed to set up preconnected client. error: %s", statusToString(status).c_str()); ALOGE("Failed to set up preconnected client. error: %s", statusToString(status).c_str()); return nullptr; return nullptr; Loading
libs/binder/rust/rpcbinder/src/session.rs +15 −7 Original line number Original line Diff line number Diff line Loading @@ -195,11 +195,13 @@ impl RpcSessionRef { /// take ownership of) file descriptors already connected to it. /// take ownership of) file descriptors already connected to it. pub fn setup_preconnected_client<T: FromIBinder + ?Sized>( pub fn setup_preconnected_client<T: FromIBinder + ?Sized>( &self, &self, mut request_fd: impl FnMut() -> Option<RawFd>, request_fd: impl FnMut() -> Option<RawFd>, ) -> Result<Strong<T>, StatusCode> { ) -> Result<Strong<T>, StatusCode> { // Double reference the factory because trait objects aren't FFI safe. // Trait objects aren't FFI safe, so *mut c_void can't be converted back to let mut request_fd_ref: RequestFd = &mut request_fd; // *mut dyn FnMut() -> Option<RawFd>>. Double box the factory to make it possible to get let param = &mut request_fd_ref as *mut RequestFd as *mut c_void; // the factory from *mut c_void (to *mut Box<dyn<...>>) in the callbacks. let request_fd_box: Box<dyn FnMut() -> Option<RawFd>> = Box::new(request_fd); let param = Box::into_raw(Box::new(request_fd_box)) as *mut c_void; // SAFETY: AIBinder returned by RpcPreconnectedClient has correct reference count, and the // SAFETY: AIBinder returned by RpcPreconnectedClient has correct reference count, and the // ownership can be safely taken by new_spibinder. RpcPreconnectedClient does not take ownership // ownership can be safely taken by new_spibinder. RpcPreconnectedClient does not take ownership Loading @@ -209,6 +211,7 @@ impl RpcSessionRef { self.as_ptr(), self.as_ptr(), Some(request_fd_wrapper), Some(request_fd_wrapper), param, param, Some(param_delete_fd_wrapper), )) )) }; }; Self::get_interface(service) Self::get_interface(service) Loading @@ -225,13 +228,18 @@ impl RpcSessionRef { } } } } type RequestFd<'a> = &'a mut dyn FnMut() -> Option<RawFd>; unsafe extern "C" fn request_fd_wrapper(param: *mut c_void) -> c_int { unsafe extern "C" fn request_fd_wrapper(param: *mut c_void) -> c_int { let request_fd_ptr = param as *mut RequestFd; let request_fd_ptr = param as *mut Box<dyn FnMut() -> Option<RawFd>>; // SAFETY: This is only ever called by RpcPreconnectedClient, within the lifetime of the // SAFETY: This is only ever called by RpcPreconnectedClient, within the lifetime of the // BinderFdFactory reference, with param being a properly aligned non-null pointer to an // BinderFdFactory reference, with param being a properly aligned non-null pointer to an // initialized instance. // initialized instance. let request_fd = unsafe { request_fd_ptr.as_mut().unwrap() }; let request_fd = unsafe { request_fd_ptr.as_mut().unwrap() }; request_fd().unwrap_or(-1) request_fd().unwrap_or(-1) } } unsafe extern "C" fn param_delete_fd_wrapper(param: *mut c_void) { // SAFETY: This is only ever called by RpcPreconnectedClient, with param being the // pointer returned from Box::into_raw. let request_fd_box = unsafe { Box::from_raw(param as *mut Box<dyn FnMut() -> Option<RawFd>>) }; drop(request_fd_box); }