libavf: Add AVirtualMachineRawConfig_setDeviceTreeOverlay

Bug: 381971307
Test: T/H
Change-Id: I44bc5281edce0e3933ed122708814fddd4122067
diff --git a/libs/libavf/include/android/virtualization.h b/libs/libavf/include/android/virtualization.h
index af39e9b..c2939bf 100644
--- a/libs/libavf/include/android/virtualization.h
+++ b/libs/libavf/include/android/virtualization.h
@@ -193,6 +193,19 @@
 int AVirtualMachineRawConfig_addCustomMemoryBackingFile(AVirtualMachineRawConfig* _Nonnull config,
                                                         int fd, uint64_t rangeStart,
                                                         uint64_t rangeEnd) __INTRODUCED_IN(36);
+/**
+ * Use the specified fd as the device tree overlay blob for booting VM.
+ *
+ * Here's the format of the device tree overlay blob.
+ * link: https://source.android.com/docs/core/architecture/dto
+ *
+ * \param config a virtual machine config object.
+ * \param fd a readable, seekable, and sized (i.e. report a valid size using fstat()) file
+ *   descriptor containing device tree overlay, or -1 to unset.
+ *   `AVirtualMachineRawConfig_setDeviceTreeOverlay` takes ownership of `fd`.
+ */
+void AVirtualMachineRawConfig_setDeviceTreeOverlay(AVirtualMachineRawConfig* _Nonnull config,
+                                                   int fd) __INTRODUCED_IN(36);
 
 /**
  * Represents a handle on a virtualization service, responsible for managing virtual machines.
diff --git a/libs/libavf/libavf.map.txt b/libs/libavf/libavf.map.txt
index a505d85..589c5d3 100644
--- a/libs/libavf/libavf.map.txt
+++ b/libs/libavf/libavf.map.txt
@@ -13,6 +13,7 @@
     AVirtualMachineRawConfig_setProtectedVm; # apex llndk
     AVirtualMachineRawConfig_setHypervisorSpecificAuthMethod; # apex llndk
     AVirtualMachineRawConfig_addCustomMemoryBackingFile; # apex llndk
+    AVirtualMachineRawConfig_setDeviceTreeOverlay; # apex llndk
     AVirtualizationService_create; # apex llndk
     AVirtualizationService_destroy; # apex llndk
     AVirtualMachine_createRaw; # apex llndk
diff --git a/libs/libavf/src/lib.rs b/libs/libavf/src/lib.rs
index 9ae2635..4f23da4 100644
--- a/libs/libavf/src/lib.rs
+++ b/libs/libavf/src/lib.rs
@@ -23,7 +23,7 @@
 
 use android_system_virtualizationservice::{
     aidl::android::system::virtualizationservice::{
-        CpuTopology::CpuTopology, DiskImage::DiskImage,
+        AssignedDevices::AssignedDevices, CpuTopology::CpuTopology, DiskImage::DiskImage,
         IVirtualizationService::IVirtualizationService, VirtualMachineConfig::VirtualMachineConfig,
         VirtualMachineRawConfig::VirtualMachineRawConfig,
     },
@@ -263,6 +263,32 @@
     -libc::ENOTSUP
 }
 
+/// Add device tree overlay blob
+///
+/// # Safety
+/// `config` must be a pointer returned by `AVirtualMachineRawConfig_create`. `fd` must be a valid
+/// file descriptor or -1. `AVirtualMachineRawConfig_setDeviceTreeOverlay` takes ownership of `fd`
+/// and `fd` will be closed upon `AVirtualMachineRawConfig_delete`.
+#[no_mangle]
+pub unsafe extern "C" fn AVirtualMachineRawConfig_setDeviceTreeOverlay(
+    config: *mut VirtualMachineRawConfig,
+    fd: c_int,
+) {
+    // 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 };
+
+    match get_file_from_fd(fd) {
+        Some(file) => {
+            let fd = ParcelFileDescriptor::new(file);
+            config.devices = AssignedDevices::Dtbo(Some(fd));
+        }
+        _ => {
+            config.devices = Default::default();
+        }
+    };
+}
+
 /// Spawn a new instance of `virtmgr`, a child process that will host the `VirtualizationService`
 /// AIDL service, and connect to the child process.
 ///