Add persistent backing for encrypted storage in VM

Virtualization service will allow clients to pass the file that will
back the (encrypted) storage inside VM.

This patch:
1. Exposes (optional) encryptedStorageImage in VirtualMachineAppConfig.
2. Expose it as a block device to VM (by including it as partition in a
   writable disk).

Test: bin/vm run-app --storage -> inspect the block device in vm
Bug: 241543632
Change-Id: I9adbe832bda2c5f5a749d8614f056f51244ae52c
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index 563fab0..10d70ec 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -17,7 +17,7 @@
 use crate::atom::{write_vm_booted_stats, write_vm_creation_stats};
 use crate::composite::make_composite_image;
 use crate::crosvm::{CrosvmConfig, DiskFile, PayloadState, VmInstance, VmState};
-use crate::payload::add_microdroid_images;
+use crate::payload::{add_microdroid_payload_images, add_microdroid_system_images};
 use crate::{Cid, FIRST_GUEST_CID, SYSPROP_LAST_CID};
 use crate::selinux::{SeContext, getfilecon};
 use android_os_permissions_aidl::aidl::android::os::IPermissionController;
@@ -603,6 +603,12 @@
     let idsig_file = clone_file(config.idsig.as_ref().unwrap())?;
     let instance_file = clone_file(config.instanceImage.as_ref().unwrap())?;
 
+    let storage_image = if let Some(file) = config.encryptedStorageImage.as_ref() {
+        Some(clone_file(file)?)
+    } else {
+        None
+    };
+
     let vm_payload_config = match &config.payload {
         Payload::ConfigPath(config_path) => {
             load_vm_payload_config_from_file(&apk_file, config_path.as_str())
@@ -632,13 +638,15 @@
     vm_config.numCpus = config.numCpus;
     vm_config.taskProfiles = config.taskProfiles.clone();
 
-    // Microdroid requires an additional init ramdisk & payload disk image
-    add_microdroid_images(
+    // Microdroid takes additional init ramdisk & (optionally) storage image
+    add_microdroid_system_images(config, instance_file, storage_image, &mut vm_config)?;
+
+    // Include Microdroid payload disk (contains apks, idsigs) in vm config
+    add_microdroid_payload_images(
         config,
         temporary_directory,
         apk_file,
         idsig_file,
-        instance_file,
         &vm_payload_config,
         &mut vm_config,
     )?;
diff --git a/virtualizationservice/src/payload.rs b/virtualizationservice/src/payload.rs
index 82aa760..b6df500 100644
--- a/virtualizationservice/src/payload.rs
+++ b/virtualizationservice/src/payload.rs
@@ -363,13 +363,10 @@
         .collect()
 }
 
-pub fn add_microdroid_images(
+pub fn add_microdroid_system_images(
     config: &VirtualMachineAppConfig,
-    temporary_directory: &Path,
-    apk_file: File,
-    idsig_file: File,
     instance_file: File,
-    vm_payload_config: &VmPayloadConfig,
+    storage_image: Option<File>,
     vm_config: &mut VirtualMachineRawConfig,
 ) -> Result<()> {
     let debug_suffix = match config.debugLevel {
@@ -381,12 +378,37 @@
     let initrd = format!("/apex/com.android.virt/etc/microdroid_initrd_{}.img", debug_suffix);
     vm_config.initrd = Some(open_parcel_file(Path::new(&initrd), false)?);
 
-    let instance_img = Partition {
+    let mut writable_partitions = vec![Partition {
         label: "vm-instance".to_owned(),
         image: Some(ParcelFileDescriptor::new(instance_file)),
         writable: true,
-    };
-    vm_config.disks.push(DiskImage { image: None, partitions: vec![instance_img], writable: true });
+    }];
+
+    if let Some(file) = storage_image {
+        writable_partitions.push(Partition {
+            label: "encrypted-storage".to_owned(),
+            image: Some(ParcelFileDescriptor::new(file)),
+            writable: true,
+        });
+    }
+
+    vm_config.disks.push(DiskImage {
+        image: None,
+        partitions: writable_partitions,
+        writable: true,
+    });
+
+    Ok(())
+}
+
+pub fn add_microdroid_payload_images(
+    config: &VirtualMachineAppConfig,
+    temporary_directory: &Path,
+    apk_file: File,
+    idsig_file: File,
+    vm_payload_config: &VmPayloadConfig,
+    vm_config: &mut VirtualMachineRawConfig,
+) -> Result<()> {
     vm_config.disks.push(make_payload_disk(
         config,
         apk_file,