libavf: implement AVirtualMachineRawConfig_addCustomMemoryBackingFile

Bug: 381972137
Bug: 368143426
Test: m
Change-Id: Ic62ad99b1923d45406366c00541789fb1fdd9b74
diff --git a/libs/libavf/src/lib.rs b/libs/libavf/src/lib.rs
index 3fa1b75..8a4970a 100644
--- a/libs/libavf/src/lib.rs
+++ b/libs/libavf/src/lib.rs
@@ -24,8 +24,9 @@
 use android_system_virtualizationservice::{
     aidl::android::system::virtualizationservice::{
         AssignedDevices::AssignedDevices, CpuOptions::CpuOptions,
-        CpuOptions::CpuTopology::CpuTopology, DiskImage::DiskImage,
-        IVirtualizationService::IVirtualizationService, VirtualMachineConfig::VirtualMachineConfig,
+        CpuOptions::CpuTopology::CpuTopology, CustomMemoryBackingFile::CustomMemoryBackingFile,
+        DiskImage::DiskImage, IVirtualizationService::IVirtualizationService,
+        VirtualMachineConfig::VirtualMachineConfig,
         VirtualMachineRawConfig::VirtualMachineRawConfig,
     },
     binder::{ParcelFileDescriptor, Strong},
@@ -254,18 +255,35 @@
     0
 }
 
-/// NOT IMPLEMENTED.
+/// Use the specified fd as the backing memfd for a range of the guest physical memory.
 ///
-/// # Returns
-/// It always returns `-ENOTSUP`.
+/// # Safety
+/// `config` must be a pointer returned by `AVirtualMachineRawConfig_create`.
 #[no_mangle]
-pub extern "C" fn AVirtualMachineRawConfig_addCustomMemoryBackingFile(
-    _config: *mut VirtualMachineRawConfig,
-    _fd: c_int,
-    _range_start: u64,
-    _range_end: u64,
+pub unsafe extern "C" fn AVirtualMachineRawConfig_addCustomMemoryBackingFile(
+    config: *mut VirtualMachineRawConfig,
+    fd: c_int,
+    range_start: u64,
+    range_end: u64,
 ) -> c_int {
-    -libc::ENOTSUP
+    // SAFETY: `config` is assumed to be a valid, non-null pointer returned by
+    // AVirtualMachineRawConfig_create. It's the only reference to the object.
+    let config = unsafe { &mut *config };
+
+    let Some(file) = get_file_from_fd(fd) else {
+        return -libc::EINVAL;
+    };
+    let Some(size) = range_end.checked_sub(range_start) else {
+        return -libc::EINVAL;
+    };
+    config.customMemoryBackingFiles.push(CustomMemoryBackingFile {
+        file: Some(ParcelFileDescriptor::new(file)),
+        // AIDL doesn't support unsigned ints, so we've got to reinterpret the bytes into a signed
+        // int.
+        rangeStart: range_start as i64,
+        size: size as i64,
+    });
+    0
 }
 
 /// Add device tree overlay blob