Persistent vm_payload_service connection

Create a connection to Microdroid Manager when we first need it, then
hold it for use in any subsequent interaction.

Bug: 243512108
Test: atest MicrodroidTests
Change-Id: I191fabee64889ddf130f8c42da7c30074fdccd10
diff --git a/microdroid/vm_payload/include/vm_payload.h b/microdroid/vm_payload/include/vm_payload.h
index 82dbd6d..2eeaef8 100644
--- a/microdroid/vm_payload/include/vm_payload.h
+++ b/microdroid/vm_payload/include/vm_payload.h
@@ -56,8 +56,9 @@
                                   void (*on_ready)(void *param), void *param);
 
 /**
- * Get a secret that is uniquely bound to this VM instance. The secrets are 32-byte values and the
- * value associated with an identifier will not change over the lifetime of the VM instance.
+ * Get a secret that is uniquely bound to this VM instance. The secrets are
+ * values up to 32 bytes long and the value associated with an identifier will
+ * not change over the lifetime of the VM instance.
  *
  * \param identifier identifier of the secret to return.
  * \param identifier_size size of the secret identifier.
diff --git a/microdroid/vm_payload/src/vm_payload_service.rs b/microdroid/vm_payload/src/vm_payload_service.rs
index dc1d100..eb4a38e 100644
--- a/microdroid/vm_payload/src/vm_payload_service.rs
+++ b/microdroid/vm_payload/src/vm_payload_service.rs
@@ -23,13 +23,31 @@
 use rpcbinder::{get_unix_domain_rpc_interface, run_vsock_rpc_server};
 use std::ffi::CString;
 use std::os::raw::{c_char, c_void};
+use std::sync::Mutex;
 
 lazy_static! {
     static ref VM_APK_CONTENTS_PATH_C: CString =
         CString::new(VM_APK_CONTENTS_PATH).expect("CString::new failed");
+    static ref PAYLOAD_CONNECTION: Mutex<Option<Strong<dyn IVmPayloadService>>> = Mutex::default();
 }
 
-// Make sure our logging goes to logcat. It is harmless to call this more than once.
+/// Return a connection to the payload service in Microdroid Manager. Uses the existing connection
+/// if there is one, otherwise attempts to create a new one.
+fn get_vm_payload_service() -> Result<Strong<dyn IVmPayloadService>> {
+    let mut connection = PAYLOAD_CONNECTION.lock().unwrap();
+    if let Some(strong) = &*connection {
+        Ok(strong.clone())
+    } else {
+        let new_connection: Strong<dyn IVmPayloadService> = get_unix_domain_rpc_interface(
+            VM_PAYLOAD_SERVICE_SOCKET_NAME,
+        )
+        .context(format!("Failed to connect to service: {}", VM_PAYLOAD_SERVICE_SOCKET_NAME))?;
+        *connection = Some(new_connection.clone());
+        Ok(new_connection)
+    }
+}
+
+/// Make sure our logging goes to logcat. It is harmless to call this more than once.
 fn initialize_logging() {
     android_logger::init_once(
         android_logger::Config::default().with_tag("vm_payload").with_min_level(Level::Debug),
@@ -215,8 +233,3 @@
 fn try_get_dice_attestation_cdi() -> Result<Vec<u8>> {
     get_vm_payload_service()?.getDiceAttestationCdi().context("Cannot get attestation CDI")
 }
-
-fn get_vm_payload_service() -> Result<Strong<dyn IVmPayloadService>> {
-    get_unix_domain_rpc_interface(VM_PAYLOAD_SERVICE_SOCKET_NAME)
-        .context(format!("Failed to connect to service: {}", VM_PAYLOAD_SERVICE_SOCKET_NAME))
-}