Add VM ID database and maintenance functionality

Convert `VirtualizationServiceInternal` to support both the
`IVirtualizationServiceInternal` interface and (optionally) the
`IVirtualizationMaintenance` interface.

Support for the latter has state held in a `maintenance::State` item,
holding both:
- A reference to the device's Secretkeeper instance
- An SQLite database of VM IDs and the corresponding (user_id, app_id).

The latter is implemented in a new maintenance::vmdb submodule.

Bug: 294177871
Test: virtualizationservice_test
Change-Id: I0c2f482252bc97dfdb75dd2e3a43883ab0eb3a77
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index 3bc7caf..c0024f1 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -15,11 +15,13 @@
 //! Implementation of the AIDL interface of the VirtualizationService.
 
 use crate::atom::{forward_vm_booted_atom, forward_vm_creation_atom, forward_vm_exited_atom};
+use crate::maintenance;
 use crate::remote_provisioning;
 use crate::rkpvm::{generate_ecdsa_p256_key_pair, request_attestation};
 use crate::{get_calling_pid, get_calling_uid, REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME};
 use android_os_permissions_aidl::aidl::android::os::IPermissionController;
 use android_system_virtualizationcommon::aidl::android::system::virtualizationcommon;
+use android_system_virtualizationmaintenance::aidl::android::system::virtualizationmaintenance;
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice;
 use android_system_virtualizationservice_internal as android_vs_internal;
 use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice;
@@ -49,6 +51,7 @@
 use std::sync::{Arc, Mutex, Weak};
 use tombstoned_client::{DebuggerdDumpType, TombstonedConnection};
 use virtualizationcommon::Certificate::Certificate;
+use virtualizationmaintenance::IVirtualizationMaintenance::IVirtualizationMaintenance;
 use virtualizationservice::{
     AssignableDevice::AssignableDevice, VirtualMachineDebugInfo::VirtualMachineDebugInfo,
 };
@@ -60,9 +63,7 @@
     IGlobalVmContext::{BnGlobalVmContext, IGlobalVmContext},
     IVfioHandler::VfioDev::VfioDev,
     IVfioHandler::{BpVfioHandler, IVfioHandler},
-    IVirtualizationServiceInternal::{
-        BnVirtualizationServiceInternal, IVirtualizationServiceInternal,
-    },
+    IVirtualizationServiceInternal::IVirtualizationServiceInternal,
 };
 use virtualmachineservice::IVirtualMachineService::VM_TOMBSTONES_SERVICE_PORT;
 use vsock::{VsockListener, VsockStream};
@@ -160,14 +161,15 @@
 
 /// Singleton service for allocating globally-unique VM resources, such as the CID, and running
 /// singleton servers, like tombstone receiver.
-#[derive(Debug, Default)]
+#[derive(Clone)]
 pub struct VirtualizationServiceInternal {
     state: Arc<Mutex<GlobalState>>,
 }
 
 impl VirtualizationServiceInternal {
-    pub fn init() -> Strong<dyn IVirtualizationServiceInternal> {
-        let service = VirtualizationServiceInternal::default();
+    pub fn init() -> VirtualizationServiceInternal {
+        let service =
+            VirtualizationServiceInternal { state: Arc::new(Mutex::new(GlobalState::new())) };
 
         std::thread::spawn(|| {
             if let Err(e) = handle_stream_connection_tombstoned() {
@@ -175,7 +177,7 @@
             }
         });
 
-        BnVirtualizationServiceInternal::new_binder(service, BinderFeatures::default())
+        service
     }
 }
 
@@ -390,6 +392,41 @@
         info!("Allocated a VM's instance_id: {:?}, for uid: {:?}", hex::encode(id), uid);
         Ok(id)
     }
+
+    fn removeVmInstance(&self, instance_id: &[u8; 64]) -> binder::Result<()> {
+        let state = &mut *self.state.lock().unwrap();
+        if let Some(sk_state) = &mut state.sk_state {
+            info!("removeVmInstance(): delete secret");
+            sk_state.delete_ids(&[*instance_id]);
+        } else {
+            info!("ignoring removeVmInstance() as no ISecretkeeper");
+        }
+        Ok(())
+    }
+}
+
+impl IVirtualizationMaintenance for VirtualizationServiceInternal {
+    fn appRemoved(&self, user_id: i32, app_id: i32) -> binder::Result<()> {
+        let state = &mut *self.state.lock().unwrap();
+        if let Some(sk_state) = &mut state.sk_state {
+            info!("packageRemoved(user_id={user_id}, app_id={app_id})");
+            sk_state.delete_ids_for_app(user_id, app_id).or_service_specific_exception(-1)?;
+        } else {
+            info!("ignoring packageRemoved(user_id={user_id}, app_id={app_id})");
+        }
+        Ok(())
+    }
+
+    fn userRemoved(&self, user_id: i32) -> binder::Result<()> {
+        let state = &mut *self.state.lock().unwrap();
+        if let Some(sk_state) = &mut state.sk_state {
+            info!("userRemoved({user_id})");
+            sk_state.delete_ids_for_user(user_id).or_service_specific_exception(-1)?;
+        } else {
+            info!("ignoring userRemoved(user_id={user_id})");
+        }
+        Ok(())
+    }
 }
 
 // KEEP IN SYNC WITH assignable_devices.xsd
@@ -474,7 +511,6 @@
 
 /// The mutable state of the VirtualizationServiceInternal. There should only be one instance
 /// of this struct.
-#[derive(Debug, Default)]
 struct GlobalState {
     /// VM contexts currently allocated to running VMs. A CID is never recycled as long
     /// as there is a strong reference held by a GlobalVmContext.
@@ -482,9 +518,20 @@
 
     /// Cached read-only FD of VM DTBO file. Also serves as a lock for creating the file.
     dtbo_file: Mutex<Option<File>>,
+
+    /// State relating to secrets held by (optional) Secretkeeper instance on behalf of VMs.
+    sk_state: Option<maintenance::State>,
 }
 
 impl GlobalState {
+    fn new() -> Self {
+        Self {
+            held_contexts: HashMap::new(),
+            dtbo_file: Mutex::new(None),
+            sk_state: maintenance::State::new(),
+        }
+    }
+
     /// Get the next available CID, or an error if we have run out. The last CID used is stored in
     /// a system property so that restart of virtualizationservice doesn't reuse CID while the host
     /// Android is up.
@@ -729,7 +776,6 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use std::fs;
 
     const TEST_RKP_CERT_CHAIN_PATH: &str = "testdata/rkp_cert_chain.der";