• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
19 use binder::unstable_api::AsNative;
20 use binder::SpIBinder;
21 use 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.
run_rpc_server<F>(service: SpIBinder, port: u32, on_ready: F) -> bool where F: FnOnce(),30 pub fn run_rpc_server<F>(service: SpIBinder, port: u32, on_ready: F) -> bool
31 where
32     F: FnOnce(),
33 {
34     let mut ready_notifier = ReadyNotifier(Some(on_ready));
35     ready_notifier.run_server(service, port)
36 }
37 
38 struct ReadyNotifier<F>(Option<F>)
39 where
40     F: FnOnce();
41 
42 impl<F> ReadyNotifier<F>
43 where
44     F: FnOnce(),
45 {
run_server(&mut self, mut service: SpIBinder, port: u32) -> bool46     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 
as_void_ptr(&mut self) -> *mut raw::c_void64     fn as_void_ptr(&mut self) -> *mut raw::c_void {
65         self as *mut _ as *mut raw::c_void
66     }
67 
ready_callback(param: *mut raw::c_void)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 
notify(&mut self)76     fn notify(&mut self) {
77         if let Some(on_ready) = self.0.take() {
78             on_ready();
79         }
80     }
81 }
82