Skip to content

Commit 1175227

Browse files
Treehugger RobotGerrit Code Review
authored andcommitted
Merge "Support deleting param for preconnected sessions" into main
2 parents 6dfc509 + 4d78e34 commit 1175227

6 files changed

Lines changed: 50 additions & 16 deletions

File tree

libs/binder/RpcSession.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,9 @@ status_t RpcSession::setupInetClient(const char* addr, unsigned int port) {
188188
}
189189

190190
status_t RpcSession::setupPreconnectedClient(unique_fd fd, std::function<unique_fd()>&& request) {
191-
return setupClient([&](const std::vector<uint8_t>& sessionId, bool incoming) -> status_t {
191+
return setupClient([&, fd = std::move(fd),
192+
request = std::move(request)](const std::vector<uint8_t>& sessionId,
193+
bool incoming) mutable -> status_t {
192194
if (!fd.ok()) {
193195
fd = request();
194196
if (!fd.ok()) return BAD_VALUE;
@@ -476,8 +478,10 @@ sp<RpcServer> RpcSession::server() {
476478
return server;
477479
}
478480

479-
status_t RpcSession::setupClient(const std::function<status_t(const std::vector<uint8_t>& sessionId,
480-
bool incoming)>& connectAndInit) {
481+
template <typename Fn,
482+
typename /* = std::enable_if_t<std::is_invocable_r_v<
483+
status_t, Fn, const std::vector<uint8_t>&, bool>> */>
484+
status_t RpcSession::setupClient(Fn&& connectAndInit) {
481485
{
482486
RpcMutexLockGuard _l(mMutex);
483487
LOG_ALWAYS_FATAL_IF(mStartedSetup, "Must only setup session once");

libs/binder/include/binder/RpcSession.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include <map>
2727
#include <optional>
28+
#include <type_traits>
2829
#include <vector>
2930

3031
namespace android {
@@ -291,9 +292,14 @@ class RpcSession final : public virtual RefBase {
291292
// join on thread passed to preJoinThreadOwnership
292293
static void join(sp<RpcSession>&& session, PreJoinSetupResult&& result);
293294

294-
[[nodiscard]] status_t setupClient(
295-
const std::function<status_t(const std::vector<uint8_t>& sessionId, bool incoming)>&
296-
connectAndInit);
295+
// This is a workaround to support move-only functors.
296+
// TODO: use std::move_only_function when it becomes available.
297+
template <typename Fn,
298+
// Fn must be a callable type taking (const std::vector<uint8_t>&, bool) and returning
299+
// status_t
300+
typename = std::enable_if_t<
301+
std::is_invocable_r_v<status_t, Fn, const std::vector<uint8_t>&, bool>>>
302+
[[nodiscard]] status_t setupClient(Fn&& connectAndInit);
297303
[[nodiscard]] status_t setupSocketClient(const RpcSocketAddress& address);
298304
[[nodiscard]] status_t setupOneSocketConnection(const RpcSocketAddress& address,
299305
const std::vector<uint8_t>& sessionId,

libs/binder/include_rpc_unstable/binder_rpc_unstable.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,14 @@ AIBinder* ARpcSession_setupInet(ARpcSession* session, const char* address, unsig
134134
//
135135
// param will be passed to requestFd. Callers can use param to pass contexts to
136136
// the requestFd function.
137+
//
138+
// paramDeleteFd will be called when requestFd and param are no longer in use.
139+
// Callers can pass a function deleting param if necessary. Callers can set
140+
// paramDeleteFd to null if callers doesn't need to clean up param.
137141
AIBinder* ARpcSession_setupPreconnectedClient(ARpcSession* session,
138142
int (*requestFd)(void* param),
139-
void* param);
143+
void* param,
144+
void (*paramDeleteFd)(void* param));
140145

141146
// Sets the file descriptor transport mode for this session.
142147
void ARpcSession_setFileDescriptorTransportMode(ARpcSession* session,

libs/binder/libbinder_rpc_unstable.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,18 @@ AIBinder* ARpcSession_setupInet(ARpcSession* handle, const char* address, unsign
248248
#endif // __TRUSTY__
249249

250250
AIBinder* ARpcSession_setupPreconnectedClient(ARpcSession* handle, int (*requestFd)(void* param),
251-
void* param) {
251+
void* param, void (*paramDeleteFd)(void* param)) {
252252
auto session = handleToStrongPointer<RpcSession>(handle);
253-
auto request = [=] { return unique_fd{requestFd(param)}; };
253+
auto deleter = [=](void* param) {
254+
if (paramDeleteFd) {
255+
paramDeleteFd(param);
256+
}
257+
};
258+
// TODO: use unique_ptr once setupPreconnectedClient uses std::move_only_function.
259+
std::shared_ptr<void> sharedParam(param, deleter);
260+
auto request = [=, sharedParam = std::move(sharedParam)] {
261+
return unique_fd{requestFd(sharedParam.get())};
262+
};
254263
if (status_t status = session->setupPreconnectedClient(unique_fd{}, request); status != OK) {
255264
ALOGE("Failed to set up preconnected client. error: %s", statusToString(status).c_str());
256265
return nullptr;

libs/binder/rust/rpcbinder/src/session.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,13 @@ impl RpcSessionRef {
195195
/// take ownership of) file descriptors already connected to it.
196196
pub fn setup_preconnected_client<T: FromIBinder + ?Sized>(
197197
&self,
198-
mut request_fd: impl FnMut() -> Option<RawFd>,
198+
request_fd: impl FnMut() -> Option<RawFd>,
199199
) -> Result<Strong<T>, StatusCode> {
200-
// Double reference the factory because trait objects aren't FFI safe.
201-
let mut request_fd_ref: RequestFd = &mut request_fd;
202-
let param = &mut request_fd_ref as *mut RequestFd as *mut c_void;
200+
// Trait objects aren't FFI safe, so *mut c_void can't be converted back to
201+
// *mut dyn FnMut() -> Option<RawFd>>. Double box the factory to make it possible to get
202+
// the factory from *mut c_void (to *mut Box<dyn<...>>) in the callbacks.
203+
let request_fd_box: Box<dyn FnMut() -> Option<RawFd>> = Box::new(request_fd);
204+
let param = Box::into_raw(Box::new(request_fd_box)) as *mut c_void;
203205

204206
// SAFETY: AIBinder returned by RpcPreconnectedClient has correct reference count, and the
205207
// ownership can be safely taken by new_spibinder. RpcPreconnectedClient does not take ownership
@@ -209,6 +211,7 @@ impl RpcSessionRef {
209211
self.as_ptr(),
210212
Some(request_fd_wrapper),
211213
param,
214+
Some(param_delete_fd_wrapper),
212215
))
213216
};
214217
Self::get_interface(service)
@@ -225,13 +228,18 @@ impl RpcSessionRef {
225228
}
226229
}
227230

228-
type RequestFd<'a> = &'a mut dyn FnMut() -> Option<RawFd>;
229-
230231
unsafe extern "C" fn request_fd_wrapper(param: *mut c_void) -> c_int {
231-
let request_fd_ptr = param as *mut RequestFd;
232+
let request_fd_ptr = param as *mut Box<dyn FnMut() -> Option<RawFd>>;
232233
// SAFETY: This is only ever called by RpcPreconnectedClient, within the lifetime of the
233234
// BinderFdFactory reference, with param being a properly aligned non-null pointer to an
234235
// initialized instance.
235236
let request_fd = unsafe { request_fd_ptr.as_mut().unwrap() };
236237
request_fd().unwrap_or(-1)
237238
}
239+
240+
unsafe extern "C" fn param_delete_fd_wrapper(param: *mut c_void) {
241+
// SAFETY: This is only ever called by RpcPreconnectedClient, with param being the
242+
// pointer returned from Box::into_raw.
243+
let request_fd_box = unsafe { Box::from_raw(param as *mut Box<dyn FnMut() -> Option<RawFd>>) };
244+
drop(request_fd_box);
245+
}

libs/binder/trusty/rust/binder_rpc_unstable_bindgen/rules.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ MODULE_LIBRARY_DEPS += \
3030
trusty/user/base/lib/libstdc++-trusty \
3131
trusty/user/base/lib/trusty-sys \
3232

33+
MODULE_SRCDEPS := $(LIBBINDER_DIR)/include_rpc_unstable/binder_rpc_unstable.hpp
34+
3335
MODULE_BINDGEN_SRC_HEADER := $(LOCAL_DIR)/BinderBindings.hpp
3436

3537
MODULE_BINDGEN_FLAGS += \

0 commit comments

Comments
 (0)