GUID of a partion can be specified if needed

Previously, when a composite disk is create from one or more partition
images, the GUID for each of the partition was randomly chosen.

This change makes it possible to specify the partition GUID if needed.
This is required for Ferrochrome where partitions are accessed via their
GUID, not by their label in the partition table.

Bug: 351973725
Test: Ferrochrome boots with the vm_config.json in the follow-up change.

Change-Id: I63647d77d74a7be99cc4811f5c836f74f13928a9
diff --git a/virtualizationmanager/Android.bp b/virtualizationmanager/Android.bp
index ada66dd..ae85934 100644
--- a/virtualizationmanager/Android.bp
+++ b/virtualizationmanager/Android.bp
@@ -71,6 +71,7 @@
         "liblibfdt",
         "libfsfdt",
         "libhypervisor_props",
+        "libuuid",
         // TODO(b/202115393) stabilize the interface
         "packagemanager_aidl-rust",
     ],
diff --git a/virtualizationmanager/src/composite.rs b/virtualizationmanager/src/composite.rs
index a4b7eae..681ec59 100644
--- a/virtualizationmanager/src/composite.rs
+++ b/virtualizationmanager/src/composite.rs
@@ -23,6 +23,8 @@
 use std::os::unix::io::AsRawFd;
 use std::path::{Path, PathBuf};
 
+use uuid::Uuid;
+
 /// Constructs a composite disk image for the given list of partitions, and opens it ready to use.
 ///
 /// Returns the composite disk image file, and a list of files whose file descriptors must be passed
@@ -105,6 +107,7 @@
                 partition_type: ImagePartitionType::LinuxFilesystem,
                 writable: partition.writable,
                 size,
+                part_guid: partition.guid.as_deref().map(Uuid::parse_str).transpose()?,
             })
         })
         .collect::<Result<_, Error>>()?;
diff --git a/virtualizationmanager/src/payload.rs b/virtualizationmanager/src/payload.rs
index 9d0c7d6..82d9ba0 100644
--- a/virtualizationmanager/src/payload.rs
+++ b/virtualizationmanager/src/payload.rs
@@ -289,6 +289,7 @@
         label: "payload-metadata".to_owned(),
         image: Some(metadata_file),
         writable: false,
+        guid: None,
     }];
 
     for (i, apex_info) in apex_infos.iter().enumerate() {
@@ -297,17 +298,20 @@
             label: format!("microdroid-apex-{}", i),
             image: Some(apex_file),
             writable: false,
+            guid: None,
         });
     }
     partitions.push(Partition {
         label: "microdroid-apk".to_owned(),
         image: Some(ParcelFileDescriptor::new(apk_file)),
         writable: false,
+        guid: None,
     });
     partitions.push(Partition {
         label: "microdroid-apk-idsig".to_owned(),
         image: Some(ParcelFileDescriptor::new(idsig_file)),
         writable: false,
+        guid: None,
     });
 
     // we've already checked that extra_apks and extraIdsigs are in the same size.
@@ -319,6 +323,7 @@
             label: format!("extra-apk-{i}"),
             image: Some(ParcelFileDescriptor::new(extra_apk_file)),
             writable: false,
+            guid: None,
         });
 
         partitions.push(Partition {
@@ -330,6 +335,7 @@
                     .with_context(|| format!("Failed to clone the extra idsig #{i}"))?,
             )),
             writable: false,
+            guid: None,
         });
     }
 
@@ -416,6 +422,7 @@
             label: "microdroid-vendor".to_owned(),
             image: Some(ParcelFileDescriptor::new(vendor_image)),
             writable: false,
+            guid: None,
         }],
     })
 }
@@ -439,6 +446,7 @@
         label: "vm-instance".to_owned(),
         image: Some(ParcelFileDescriptor::new(instance_file)),
         writable: true,
+        guid: None,
     }];
 
     if let Some(file) = storage_image {
@@ -446,6 +454,7 @@
             label: "encryptedstore".to_owned(),
             image: Some(ParcelFileDescriptor::new(file)),
             writable: true,
+            guid: None,
         });
     }