Flag guard vfio_handler

Guard the following on the value of the
RELEASE_AVF_ENABLE_DEVICE_ASSIGNMENT flag:

* vfio_handler binary & vfio_handler.rc in com.android.virt APEX;
* --devices flag in the vm shell binary
* Usage of the CustomConfig.devices field in the
  VirtualMachineAppConfig;

Test: atest MicrodroidTests
Change-Id: I40611b0cd93d17aacd68acf74f442e479a80d488
diff --git a/Android.bp b/Android.bp
index 550a6be..9c17c7f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -22,6 +22,7 @@
     module_type: "rust_defaults",
     config_namespace: "ANDROID",
     bool_variables: [
+        "release_avf_enable_device_assignment",
         "release_avf_enable_dice_changes",
         "release_avf_enable_llpvm_changes",
         "release_avf_enable_multi_tenant_microdroid_vm",
@@ -36,6 +37,9 @@
 avf_flag_aware_rust_defaults {
     name: "avf_build_flags_rust",
     soong_config_variables: {
+        release_avf_enable_device_assignment: {
+            cfgs: ["device_assignment"],
+        },
         release_avf_enable_dice_changes: {
             cfgs: ["dice_changes"],
         },
diff --git a/apex/Android.bp b/apex/Android.bp
index b7fd67e..96540aa 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -71,8 +71,14 @@
     name: "avf_flag_aware_apex_defaults",
     module_type: "apex_defaults",
     config_namespace: "ANDROID",
-    bool_variables: ["release_avf_enable_vendor_modules"],
-    properties: ["prebuilts"],
+    bool_variables: [
+        "release_avf_enable_device_assignment",
+        "release_avf_enable_vendor_modules",
+    ],
+    properties: [
+        "arch",
+        "prebuilts",
+    ],
 }
 
 avf_flag_aware_apex_defaults {
@@ -87,7 +93,6 @@
         arm64: {
             binaries: [
                 "crosvm",
-                "vfio_handler",
                 "virtmgr",
                 "virtualizationservice",
             ],
@@ -96,7 +101,6 @@
         x86_64: {
             binaries: [
                 "crosvm",
-                "vfio_handler",
                 "virtmgr",
                 "virtualizationservice",
             ],
@@ -124,6 +128,19 @@
         "EmptyPayloadApp",
     ],
     soong_config_variables: {
+        release_avf_enable_device_assignment: {
+            prebuilts: [
+                "com.android.virt.vfio_handler.rc",
+            ],
+            arch: {
+                arm64: {
+                    binaries: ["vfio_handler"],
+                },
+                x86_64: {
+                    binaries: ["vfio_handler"],
+                },
+            },
+        },
         release_avf_enable_vendor_modules: {
             prebuilts: [
                 "microdroid_gki_initrd_debuggable",
@@ -158,6 +175,13 @@
     installable: false,
 }
 
+prebuilt_etc {
+    name: "com.android.virt.vfio_handler.rc",
+    src: "vfio_handler.rc",
+    filename: "vfio_handler.rc",
+    installable: false,
+}
+
 sh_binary_host {
     name: "prepare_device_vfio",
     src: "prepare_device_vfio.sh",
diff --git a/apex/vfio_handler.rc b/apex/vfio_handler.rc
new file mode 100644
index 0000000..419acef
--- /dev/null
+++ b/apex/vfio_handler.rc
@@ -0,0 +1,20 @@
+# 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.
+
+service vfio_handler /apex/com.android.virt/bin/vfio_handler
+    user root
+    group system
+    interface aidl android.system.virtualizationservice_internal.IVfioHandler
+    disabled
+    oneshot
diff --git a/apex/virtualizationservice.rc b/apex/virtualizationservice.rc
index 8283594..02b2081 100644
--- a/apex/virtualizationservice.rc
+++ b/apex/virtualizationservice.rc
@@ -19,10 +19,3 @@
     interface aidl android.system.virtualizationservice
     disabled
     oneshot
-
-service vfio_handler /apex/com.android.virt/bin/vfio_handler
-    user root
-    group system
-    interface aidl android.system.virtualizationservice_internal.IVfioHandler
-    disabled
-    oneshot
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index c6a30aa..19768b5 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -1195,10 +1195,24 @@
     Ok(())
 }
 
+fn check_no_devices(config: &VirtualMachineConfig) -> binder::Result<()> {
+    let VirtualMachineConfig::AppConfig(config) = config else { return Ok(()) };
+    if let Some(custom_config) = &config.customConfig {
+        if !custom_config.devices.is_empty() {
+            return Err(anyhow!("device assignment feature is disabled"))
+                .or_binder_exception(ExceptionCode::UNSUPPORTED_OPERATION);
+        }
+    }
+    Ok(())
+}
+
 fn check_config_features(config: &VirtualMachineConfig) -> binder::Result<()> {
     if !cfg!(vendor_modules) {
         check_no_vendor_modules(config)?;
     }
+    if !cfg!(device_assignment) {
+        check_no_devices(config)?;
+    }
     Ok(())
 }
 
diff --git a/vm/src/main.rs b/vm/src/main.rs
index 0af9791..14db27c 100644
--- a/vm/src/main.rs
+++ b/vm/src/main.rs
@@ -108,6 +108,7 @@
     vendor: Option<PathBuf>,
 
     /// SysFS nodes of devices to assign to VM
+    #[cfg(device_assignment)]
     #[arg(long)]
     devices: Vec<PathBuf>,
 }
@@ -132,6 +133,16 @@
     fn vendor(&self) -> Option<PathBuf> {
         None
     }
+
+    #[cfg(device_assignment)]
+    fn devices(&self) -> &Vec<PathBuf> {
+        &self.devices
+    }
+
+    #[cfg(not(device_assignment))]
+    fn devices(&self) -> Vec<PathBuf> {
+        Vec::new()
+    }
 }
 
 #[derive(Args)]
diff --git a/vm/src/run.rs b/vm/src/run.rs
index 1ba9dec..84c3af6 100644
--- a/vm/src/run.rs
+++ b/vm/src/run.rs
@@ -130,7 +130,7 @@
         vendorImage: vendor,
         devices: config
             .microdroid
-            .devices
+            .devices()
             .iter()
             .map(|x| {
                 x.to_str().map(String::from).ok_or(anyhow!("Failed to convert {x:?} to String"))