Merge "Split userdebug only tests from MicrodroidHostTestCases" into main
diff --git a/libs/service_vm_comm/src/lib.rs b/libs/service_vm_comm/src/lib.rs
index c3d3ed5..ef5e8bb 100644
--- a/libs/service_vm_comm/src/lib.rs
+++ b/libs/service_vm_comm/src/lib.rs
@@ -20,5 +20,7 @@
 extern crate alloc;
 
 mod message;
+mod vsock;
 
 pub use message::{Request, Response};
+pub use vsock::host_port;
diff --git a/libs/service_vm_comm/src/vsock.rs b/libs/service_vm_comm/src/vsock.rs
new file mode 100644
index 0000000..fd6f088
--- /dev/null
+++ b/libs/service_vm_comm/src/vsock.rs
@@ -0,0 +1,27 @@
+// Copyright 2023, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Vsock setup shared between the host and the service VM.
+
+/// Returns the host port number for the given VM protection state.
+pub fn host_port(is_protected_vm: bool) -> u32 {
+    const PROTECTED_VM_PORT: u32 = 5679;
+    const NON_PROTECTED_VM_PORT: u32 = 5680;
+
+    if is_protected_vm {
+        PROTECTED_VM_PORT
+    } else {
+        NON_PROTECTED_VM_PORT
+    }
+}
diff --git a/rialto/src/main.rs b/rialto/src/main.rs
index 42d39c4..b34b9de 100644
--- a/rialto/src/main.rs
+++ b/rialto/src/main.rs
@@ -34,7 +34,7 @@
 use libfdt::FdtError;
 use log::{debug, error, info};
 use virtio_drivers::{
-    device::socket::VsockAddr,
+    device::socket::{VsockAddr, VMADDR_CID_HOST},
     transport::{pci::bus::PciRoot, DeviceType, Transport},
     Hal,
 };
@@ -52,12 +52,7 @@
 };
 
 fn host_addr() -> VsockAddr {
-    const PROTECTED_VM_PORT: u32 = 5679;
-    const NON_PROTECTED_VM_PORT: u32 = 5680;
-    const VMADDR_CID_HOST: u64 = 2;
-
-    let port = if is_protected_vm() { PROTECTED_VM_PORT } else { NON_PROTECTED_VM_PORT };
-    VsockAddr { cid: VMADDR_CID_HOST, port }
+    VsockAddr { cid: VMADDR_CID_HOST, port: service_vm_comm::host_port(is_protected_vm()) }
 }
 
 fn is_protected_vm() -> bool {
diff --git a/rialto/tests/test.rs b/rialto/tests/test.rs
index 2bd8968..e9bdab6 100644
--- a/rialto/tests/test.rs
+++ b/rialto/tests/test.rs
@@ -24,7 +24,7 @@
 };
 use anyhow::{anyhow, bail, Context, Result};
 use log::info;
-use service_vm_comm::{Request, Response};
+use service_vm_comm::{host_port, Request, Response};
 use std::fs::File;
 use std::io::{self, BufRead, BufReader, BufWriter, Write};
 use std::os::unix::io::FromRawFd;
@@ -34,11 +34,6 @@
 use vmclient::{DeathReason, VmInstance};
 use vsock::{VsockListener, VMADDR_CID_HOST};
 
-// TODO(b/291732060): Move the port numbers to the common library shared between the host
-// and rialto.
-const PROTECTED_VM_PORT: u32 = 5679;
-const NON_PROTECTED_VM_PORT: u32 = 5680;
-
 const SIGNED_RIALTO_PATH: &str = "/data/local/tmp/rialto_test/arm64/rialto.bin";
 const UNSIGNED_RIALTO_PATH: &str = "/data/local/tmp/rialto_test/arm64/rialto_unsigned.bin";
 const INSTANCE_IMG_PATH: &str = "/data/local/tmp/rialto_test/arm64/instance.img";
@@ -131,7 +126,7 @@
     )
     .context("Failed to create VM")?;
 
-    let port = if protected_vm { PROTECTED_VM_PORT } else { NON_PROTECTED_VM_PORT };
+    let port = host_port(protected_vm);
     let check_socket_handle = thread::spawn(move || try_check_socket_connection(port).unwrap());
 
     vm.start().context("Failed to start VM")?;
diff --git a/virtualizationservice/Android.bp b/virtualizationservice/Android.bp
index 67890e2..f96c76b 100644
--- a/virtualizationservice/Android.bp
+++ b/virtualizationservice/Android.bp
@@ -37,6 +37,15 @@
         "libstatslog_virtualization_rust",
         "libtombstoned_client_rust",
         "libvsock",
+        "libserde",
+        "libserde_xml_rs",
     ],
     apex_available: ["com.android.virt"],
 }
+
+xsd_config {
+    name: "assignable_devices",
+    srcs: ["assignable_devices.xsd"],
+    api_dir: "schema",
+    package_name: "android.system.virtualizationservice",
+}
diff --git a/virtualizationservice/assignable_devices.xsd b/virtualizationservice/assignable_devices.xsd
new file mode 100644
index 0000000..842542e
--- /dev/null
+++ b/virtualizationservice/assignable_devices.xsd
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+         Licensed under the Apache License, Version 2.0 (the "License");
+         you may not use this file except in compliance with the License.
+         You may obtain a copy of the License at
+
+                    http://www.apache.org/licenses/LICENSE-2.0
+
+         Unless required by applicable law or agreed to in writing, software
+         distributed under the License is distributed on an "AS IS" BASIS,
+         WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+         See the License for the specific language governing permissions and
+         limitations under the License.
+-->
+<!-- KEEP IN SYNC WITH aidl.rs -->
+<xs:schema version="2.0"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <xs:element name="devices">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="device" type="device" minOccurs="0" maxOccurs="unbounded"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+    <xs:complexType name="device">
+        <xs:attribute name="kind" type="xs:string"/>
+        <xs:attribute name="sysfs_path" type="xs:string"/>
+    </xs:complexType>
+</xs:schema>
diff --git a/virtualizationservice/schema/current.txt b/virtualizationservice/schema/current.txt
new file mode 100644
index 0000000..ed0763a
--- /dev/null
+++ b/virtualizationservice/schema/current.txt
@@ -0,0 +1,25 @@
+// Signature format: 2.0
+package android.system.virtualizationservice {
+
+  public class Device {
+    ctor public Device();
+    method public String getKind();
+    method public String getSysfs_path();
+    method public void setKind(String);
+    method public void setSysfs_path(String);
+  }
+
+  public class Devices {
+    ctor public Devices();
+    method public java.util.List<android.system.virtualizationservice.Device> getDevice();
+  }
+
+  public class XmlParser {
+    ctor public XmlParser();
+    method public static android.system.virtualizationservice.Devices read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+  }
+
+}
+
diff --git a/virtualizationservice/schema/last_current.txt b/virtualizationservice/schema/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/virtualizationservice/schema/last_current.txt
diff --git a/virtualizationservice/schema/last_removed.txt b/virtualizationservice/schema/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/virtualizationservice/schema/last_removed.txt
diff --git a/virtualizationservice/schema/removed.txt b/virtualizationservice/schema/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/virtualizationservice/schema/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index b2513d9..f94dd4e 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -38,8 +38,9 @@
 use libc::VMADDR_CID_HOST;
 use log::{error, info, warn};
 use rustutils::system_properties;
-use std::collections::HashMap;
-use std::fs::{create_dir, remove_dir_all, set_permissions, Permissions};
+use serde::Deserialize;
+use std::collections::{HashMap, HashSet};
+use std::fs::{self, create_dir, remove_dir_all, set_permissions, Permissions};
 use std::io::{Read, Write};
 use std::os::unix::fs::PermissionsExt;
 use std::os::unix::raw::{pid_t, uid_t};
@@ -172,13 +173,41 @@
     fn getAssignableDevices(&self) -> binder::Result<Vec<AssignableDevice>> {
         check_use_custom_virtual_machine()?;
 
-        // TODO(b/291191362): read VM DTBO to find assignable devices.
-        let mut devices = Vec::new();
-        let eh_path = "/sys/bus/platform/devices/16d00000.eh";
-        if Path::new(eh_path).exists() {
-            devices.push(AssignableDevice { kind: "eh".to_owned(), node: eh_path.to_owned() });
+        let mut ret = Vec::new();
+        let xml_path = Path::new("/vendor/etc/avf/assignable_devices.xml");
+        if !xml_path.exists() {
+            return Ok(ret);
         }
-        Ok(devices)
+
+        let xml = fs::read(xml_path)
+            .context("Failed to read assignable_devices.xml")
+            .with_log()
+            .or_service_specific_exception(-1)?;
+
+        let xml = String::from_utf8(xml)
+            .context("assignable_devices.xml is not a valid UTF-8 file")
+            .with_log()
+            .or_service_specific_exception(-1)?;
+
+        let devices: Devices = serde_xml_rs::from_str(&xml)
+            .context("can't parse assignable_devices.xml")
+            .with_log()
+            .or_service_specific_exception(-1)?;
+
+        let mut device_set = HashSet::new();
+
+        for device in devices.device.into_iter() {
+            if device_set.contains(&device.sysfs_path) {
+                warn!("duplicated assignable device {device:?}; ignoring...")
+            } else if Path::new(&device.sysfs_path).exists() {
+                device_set.insert(device.sysfs_path.clone());
+                ret.push(AssignableDevice { kind: device.kind, node: device.sysfs_path });
+            } else {
+                warn!("assignable device {device:?} doesn't exist; ignoring...");
+            }
+        }
+
+        Ok(ret)
     }
 
     fn bindDevicesToVfioDriver(
@@ -196,6 +225,18 @@
     }
 }
 
+// KEEP IN SYNC WITH assignable_devices.xsd
+#[derive(Debug, Deserialize)]
+struct Device {
+    kind: String,
+    sysfs_path: String,
+}
+
+#[derive(Debug, Deserialize)]
+struct Devices {
+    device: Vec<Device>,
+}
+
 #[derive(Debug, Default)]
 struct GlobalVmInstance {
     /// The unique CID assigned to the VM for vsock communication.