authfs: Support RPC binder
This change adds a new flag --rpc-binder to authfs, and --cid to
fd_server. The flag allows both to communicate through vsock. The
capability of local binder is kept for now (and still the default),
but can be removed later.
The change relies on the newly introduced libbinder_rpc_unstable.so
and the corresponding bindgen, in order to access the unstable API from
Rust.
Also, add authfs and libbinder_rpc_unstable to microdroid.
Bug: 190547489
Bug: 189947807
Test: [Android shell] sh -c 'exec 9<>/data/local/tmp/output \
/apex/com.android.virt/bin/fd_server --rw-fds 9 --rpc-binder'
[VM shell] /apex/com.android.virt/bin/authfs \
/data/local/tmp --cid 2 --remote-new-rw-file 9:9
[VM shell 2] ps -A > /data/local/tmp/9
[Android shell] cat /data/local/tmp/output # see correct data
Change-Id: I200f746aa4078508a0f0d2498a1525bb898a6e3b
diff --git a/authfs/src/file.rs b/authfs/src/file.rs
index 4b43786..033dbd6 100644
--- a/authfs/src/file.rs
+++ b/authfs/src/file.rs
@@ -4,21 +4,56 @@
pub use local_file::LocalFileReader;
pub use remote_file::{RemoteFileEditor, RemoteFileReader, RemoteMerkleTreeReader};
+use binder::unstable_api::{new_spibinder, AIBinder};
+use binder::FromIBinder;
use std::io;
use crate::common::CHUNK_SIZE;
-
-use authfs_aidl_interface::aidl::com::android::virt::fs::IVirtFdService;
+use authfs_aidl_interface::aidl::com::android::virt::fs::IVirtFdService::IVirtFdService;
use authfs_aidl_interface::binder::{get_interface, Strong};
-// TODO(victorhsieh): use remote binder.
-pub fn get_local_binder() -> Strong<dyn IVirtFdService::IVirtFdService> {
- let service_name = "authfs_fd_server";
- get_interface(&service_name).expect("Cannot reach authfs_fd_server binder service")
-}
+pub type VirtFdService = Strong<dyn IVirtFdService>;
pub type ChunkBuffer = [u8; CHUNK_SIZE as usize];
+pub const RPC_SERVICE_PORT: u32 = 3264;
+
+fn get_local_binder() -> io::Result<VirtFdService> {
+ let service_name = "authfs_fd_server";
+ get_interface(&service_name).map_err(|e| {
+ io::Error::new(
+ io::ErrorKind::AddrNotAvailable,
+ format!("Cannot reach authfs_fd_server binder service: {}", e),
+ )
+ })
+}
+
+fn get_rpc_binder(cid: u32) -> io::Result<VirtFdService> {
+ // SAFETY: AIBinder returned by RpcClient has correct reference count, and the ownership can be
+ // safely taken by new_spibinder.
+ let ibinder = unsafe {
+ new_spibinder(binder_rpc_unstable_bindgen::RpcClient(cid, RPC_SERVICE_PORT) as *mut AIBinder)
+ };
+ if let Some(ibinder) = ibinder {
+ Ok(IVirtFdService::try_from(ibinder).map_err(|e| {
+ io::Error::new(
+ io::ErrorKind::AddrNotAvailable,
+ format!("Cannot connect to RPC service: {}", e),
+ )
+ })?)
+ } else {
+ Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid raw AIBinder"))
+ }
+}
+
+pub fn get_binder_service(cid: Option<u32>) -> io::Result<VirtFdService> {
+ if let Some(cid) = cid {
+ get_rpc_binder(cid)
+ } else {
+ get_local_binder()
+ }
+}
+
/// A trait for reading data by chunks. Chunks can be read by specifying the chunk index. Only the
/// last chunk may have incomplete chunk size.
pub trait ReadByChunk {