blob: 5c9d2a0ba90fc086148184a4bf462027eeed5897 [file] [log] [blame]
Alan Stokescd359bb2021-10-08 18:22:42 +01001/*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//! Helpers for implementing an RPC Binder server.
18
Alan Stokescd359bb2021-10-08 18:22:42 +010019use binder::unstable_api::AsNative;
Stephen Crane44fd9bc2022-01-19 17:49:46 +000020use binder::SpIBinder;
Alan Stokescd359bb2021-10-08 18:22:42 +010021use std::os::raw;
22
23/// Run a binder RPC server, serving the supplied binder service implementation on the given vsock
24/// port.
25/// If and when the server is ready for connections (it is listening on the port) on_ready
26/// is called to allow appropriate action to be taken - e.g. to notify clients they
27/// may now attempt to connect.
28/// The current thread is joined to the binder thread pool to handle incoming messages.
29/// Returns true if the server has shutdown normally, false if it failed in some way.
30pub fn run_rpc_server<F>(service: SpIBinder, port: u32, on_ready: F) -> bool
31where
32 F: FnOnce(),
33{
34 let mut ready_notifier = ReadyNotifier(Some(on_ready));
35 ready_notifier.run_server(service, port)
36}
37
38struct ReadyNotifier<F>(Option<F>)
39where
40 F: FnOnce();
41
42impl<F> ReadyNotifier<F>
43where
44 F: FnOnce(),
45{
46 fn run_server(&mut self, mut service: SpIBinder, port: u32) -> bool {
47 let service = service.as_native_mut() as *mut binder_rpc_unstable_bindgen::AIBinder;
48 let param = self.as_void_ptr();
49
50 // SAFETY: Service ownership is transferring to the server and won't be valid afterward.
51 // Plus the binder objects are threadsafe.
52 // RunRpcServerCallback does not retain a reference to ready_callback, and only ever
53 // calls it with the param we provide during the lifetime of self.
54 unsafe {
55 binder_rpc_unstable_bindgen::RunRpcServerCallback(
56 service,
57 port,
58 Some(Self::ready_callback),
59 param,
60 )
61 }
62 }
63
64 fn as_void_ptr(&mut self) -> *mut raw::c_void {
65 self as *mut _ as *mut raw::c_void
66 }
67
68 unsafe extern "C" fn ready_callback(param: *mut raw::c_void) {
69 // SAFETY: This is only ever called by RunRpcServerCallback, within the lifetime of the
70 // ReadyNotifier, with param taking the value returned by as_void_ptr (so a properly aligned
71 // non-null pointer to an initialized instance).
72 let ready_notifier = param as *mut Self;
73 ready_notifier.as_mut().unwrap().notify()
74 }
75
76 fn notify(&mut self) {
77 if let Some(on_ready) = self.0.take() {
78 on_ready();
79 }
80 }
81}