Add VirtualMachineService skeleton code

VirtualMachineService (the name isn't yet fixed) is a binder service
between virt service and guest VMs. Guest VMs can notify that it's ready
over VirtualMachineService.

Bug: 191845268
Test: atest MicrodroidHostTestCases
Change-Id: I80c529f104fe184a1bdbee25805c7871392336d5
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index d7e256b..2fb7fdd 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -19,6 +19,8 @@
 
 use anyhow::{anyhow, bail, Context, Result};
 use apkverify::verify;
+use binder::unstable_api::{new_spibinder, AIBinder};
+use binder::{FromIBinder, Strong};
 use log::{error, info, warn};
 use microdroid_payload_config::{Task, TaskType, VmPayloadConfig};
 use rustutils::system_properties::PropertyWatcher;
@@ -30,9 +32,35 @@
 use std::time::Duration;
 use vsock::VsockStream;
 
+use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::IVirtualMachineService::IVirtualMachineService;
+
 const WAIT_TIMEOUT: Duration = Duration::from_secs(10);
 const DM_MOUNTED_APK_PATH: &str = "/dev/block/mapper/microdroid-apk";
 
+/// The CID representing the host VM
+const VMADDR_CID_HOST: u32 = 2;
+
+/// Port number that virtualizationservice listens on connections from the guest VMs for the
+/// VirtualMachineService binder service
+/// Sync with virtualizationservice/src/aidl.rs
+const PORT_VM_BINDER_SERVICE: u32 = 5000;
+
+fn get_vms_rpc_binder() -> Result<Strong<dyn IVirtualMachineService>> {
+    // 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(
+            VMADDR_CID_HOST,
+            PORT_VM_BINDER_SERVICE,
+        ) as *mut AIBinder)
+    };
+    if let Some(ibinder) = ibinder {
+        <dyn IVirtualMachineService>::try_from(ibinder).context("Cannot connect to RPC service")
+    } else {
+        bail!("Invalid raw AIBinder")
+    }
+}
+
 fn main() -> Result<()> {
     kernlog::init()?;
     info!("started.");
@@ -44,6 +72,11 @@
         return Err(err);
     }
 
+    // TODO(b/191845268): microdroid_manager should use this binder to communicate with the host
+    if let Err(err) = get_vms_rpc_binder() {
+        error!("cannot connect to VirtualMachineService: {}", err);
+    }
+
     if !metadata.payload_config_path.is_empty() {
         let config = load_config(Path::new(&metadata.payload_config_path))?;