Set encrypted storage size in bytes

Change the API to deal in bytes not KiB. Internally, round up to a
size that the crosvm will accept.

Modify callers appropriately. (Deliberately using round numbers in
base 10 not base 2.)

In passing, totally gratuitously switch from sleep to pause; it's
cleaner.

Bug: 262449687
Test: atest MicrodroidTests
Change-Id: I539ceb7845e7345e7e4f5b5b849afaba21497087
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index ca42999..cab7c71 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -90,6 +90,9 @@
 
 const UNFORMATTED_STORAGE_MAGIC: &str = "UNFORMATTED-STORAGE";
 
+/// crosvm requires all partitions to be a multiple of 4KiB.
+const PARTITION_GRANULARITY_BYTES: u64 = 4096;
+
 lazy_static! {
     pub static ref GLOBAL_SERVICE: Strong<dyn IVirtualizationServiceInternal> =
         wait_for_interface(BINDER_SERVICE_IDENTIFIER)
@@ -172,16 +175,17 @@
     fn initializeWritablePartition(
         &self,
         image_fd: &ParcelFileDescriptor,
-        size: i64,
+        size_bytes: i64,
         partition_type: PartitionType,
     ) -> binder::Result<()> {
         check_manage_access()?;
-        let size = size.try_into().map_err(|e| {
+        let size_bytes = size_bytes.try_into().map_err(|e| {
             Status::new_exception_str(
                 ExceptionCode::ILLEGAL_ARGUMENT,
-                Some(format!("Invalid size {}: {:?}", size, e)),
+                Some(format!("Invalid size {}: {:?}", size_bytes, e)),
             )
         })?;
+        let size_bytes = round_up(size_bytes, PARTITION_GRANULARITY_BYTES);
         let image = clone_file(image_fd)?;
         // initialize the file. Any data in the file will be erased.
         image.set_len(0).map_err(|e| {
@@ -190,7 +194,7 @@
                 Some(format!("Failed to reset a file: {:?}", e)),
             )
         })?;
-        let mut part = QcowFile::new(image, size).map_err(|e| {
+        let mut part = QcowFile::new(image, size_bytes).map_err(|e| {
             Status::new_service_specific_error_str(
                 -1,
                 Some(format!("Failed to create QCOW2 image: {:?}", e)),
@@ -460,6 +464,15 @@
     File::create(ramdump_path).context(format!("Failed to create ramdump file {:?}", &ramdump_path))
 }
 
+fn round_up(input: u64, granularity: u64) -> u64 {
+    if granularity == 0 {
+        return input;
+    }
+    // If the input is absurdly large we round down instead of up; it's going to fail anyway.
+    let result = input.checked_add(granularity - 1).unwrap_or(input);
+    (result / granularity) * granularity
+}
+
 /// Given the configuration for a disk image, assembles the `DiskFile` to pass to crosvm.
 ///
 /// This may involve assembling a composite disk from a set of partition images.