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/Android.bp b/microdroid_manager/Android.bp
index a082beb..95a7014 100644
--- a/microdroid_manager/Android.bp
+++ b/microdroid_manager/Android.bp
@@ -9,8 +9,12 @@
     edition: "2018",
     prefer_rlib: true,
     rustlibs: [
+        "android.system.virtualizationservice-rust",
+        "android.system.virtualmachineservice-rust",
         "libanyhow",
         "libapkverify",
+        "libbinder_rpc_unstable_bindgen",
+        "libbinder_rs",
         "libkernlog",
         "liblibc",
         "liblog_rust",
@@ -22,6 +26,9 @@
         "libserde_json",
         "libvsock",
     ],
+    shared_libs: [
+        "libbinder_rpc_unstable",
+    ],
     init_rc: ["microdroid_manager.rc"],
 }
 
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))?;