Orderly VM shutdown, part 1

Rather than killing the VM when we are done with it, ask the payload
to exit, and wait for the VM to have full exited. This allows the VM
time to write logs, generated crash dumps etc if there has been a
failure.

Add a quit method to the CompOS service, so clients can request it to
exit. Add the ability to wait for a VM to have died with a timeout to
vmclient. Implement a wait for shutdown in compos_client that waits
for the VM to exit but terminates it abruptly if it doesn't do so in a
reasonable time; do the same thing if the VM fails to start.

Change compos_verify to use this method to wait for the VM to have
fully exited once we are done with it.

Assorted refactorings:

- Simplify the timeout handling code so we panic if the neccessary
  property isn't available (all requests would fail anyway). Also
  updated the timeouts a little.

- Rename get_service to connect_service (it's definitely not a simple
  getter).

I haven't dealt with compilation yet; that will have ramifications all
the way up to Java, and this CL is big enough already. Additionally I
haven't yet attempted to allow odsign to continue while we wait for
the VM to exit.

Bug: 236581575
Test: Run VM, see both finished & died in the logs.
Change-Id: I47501081d23833fe7ef791240161d93e38b3d951
diff --git a/vmclient/src/errors.rs b/vmclient/src/errors.rs
index 532706d..994d0ef 100644
--- a/vmclient/src/errors.rs
+++ b/vmclient/src/errors.rs
@@ -33,9 +33,9 @@
     Finished,
 }
 
-/// An error connection to a VM RPC Binder service.
+/// An error connecting to a VM RPC Binder service.
 #[derive(Clone, Debug, Error)]
-pub enum GetServiceError {
+pub enum ConnectServiceError {
     /// The RPC binder connection failed.
     #[error("Vsock connection to RPC binder failed.")]
     ConnectionFailed,
diff --git a/vmclient/src/lib.rs b/vmclient/src/lib.rs
index 867c3a7..9b5b8dd 100644
--- a/vmclient/src/lib.rs
+++ b/vmclient/src/lib.rs
@@ -20,7 +20,7 @@
 mod sync;
 
 pub use crate::death_reason::DeathReason;
-pub use crate::errors::{GetServiceError, VmWaitError};
+pub use crate::errors::{ConnectServiceError, VmWaitError};
 use crate::{rpc_binder::VsockFactory, sync::Monitor};
 use android_system_virtualizationservice::{
     aidl::android::system::virtualizationservice::{
@@ -111,6 +111,15 @@
         self.state.wait_while(|state| state.death_reason.is_none()).unwrap().death_reason.unwrap()
     }
 
+    /// Blocks until the VM or the VirtualizationService itself dies, or the given timeout expires.
+    /// Returns the reason why it died if it did so.
+    pub fn wait_for_death_with_timeout(&self, timeout: Duration) -> Option<DeathReason> {
+        let (state, _timeout_result) =
+            self.state.wait_timeout_while(timeout, |state| state.death_reason.is_none()).unwrap();
+        // We don't care if it timed out - we just return the reason if there now is one
+        state.death_reason
+    }
+
     /// Waits until the VM reports that it is ready.
     ///
     /// Returns an error if the VM dies first, or the `timeout` elapses before the VM is ready.
@@ -133,15 +142,15 @@
     }
 
     /// Tries to connect to an RPC Binder service provided by the VM on the given vsock port.
-    pub fn get_service<T: FromIBinder + ?Sized>(
+    pub fn connect_service<T: FromIBinder + ?Sized>(
         &self,
         port: u32,
-    ) -> Result<Strong<T>, GetServiceError> {
+    ) -> Result<Strong<T>, ConnectServiceError> {
         let mut vsock_factory = VsockFactory::new(&*self.vm, port);
 
         let ibinder = vsock_factory.connect_rpc_client()?;
 
-        FromIBinder::try_from(ibinder).map_err(GetServiceError::WrongServiceType)
+        FromIBinder::try_from(ibinder).map_err(ConnectServiceError::WrongServiceType)
     }
 
     /// Get ramdump
diff --git a/vmclient/src/rpc_binder.rs b/vmclient/src/rpc_binder.rs
index fee643f..7c2992b 100644
--- a/vmclient/src/rpc_binder.rs
+++ b/vmclient/src/rpc_binder.rs
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-use crate::errors::GetServiceError;
+use crate::errors::ConnectServiceError;
 use android_system_virtualizationservice::{
     aidl::android::system::virtualizationservice::IVirtualMachine::IVirtualMachine,
 };
@@ -30,7 +30,7 @@
         Self { vm, port }
     }
 
-    pub fn connect_rpc_client(&mut self) -> Result<binder::SpIBinder, GetServiceError> {
+    pub fn connect_rpc_client(&mut self) -> Result<binder::SpIBinder, ConnectServiceError> {
         let param = self.as_void_ptr();
 
         unsafe {
@@ -41,7 +41,7 @@
             let binder =
                 binder_rpc_unstable_bindgen::RpcPreconnectedClient(Some(Self::request_fd), param)
                     as *mut AIBinder;
-            new_spibinder(binder).ok_or(GetServiceError::ConnectionFailed)
+            new_spibinder(binder).ok_or(ConnectServiceError::ConnectionFailed)
         }
     }