Add API getting list of assignable devices

An app can call getAssignableDevices to check the types of devices
supported. The app must have USE_CUSTOM_VIRTUAL_MACHINE permission
to do that.

Bug: 287379025
Test: TH
Change-Id: I2013810388eaf7599ac1e2e6e535be0aca0cbec7
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index b2497b1..daee7c5 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -28,6 +28,7 @@
     ErrorCode::ErrorCode,
 };
 use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
+    AssignableDevice::AssignableDevice,
     CpuTopology::CpuTopology,
     DiskImage::DiskImage,
     IVirtualMachine::{BnVirtualMachine, IVirtualMachine},
@@ -270,6 +271,12 @@
         // Delegate to the global service, including checking the debug permission.
         GLOBAL_SERVICE.debugListVms()
     }
+
+    /// Get a list of assignable device types.
+    fn getAssignableDevices(&self) -> binder::Result<Vec<AssignableDevice>> {
+        // Delegate to the global service, including checking the permission.
+        GLOBAL_SERVICE.getAssignableDevices()
+    }
 }
 
 impl VirtualizationService {
@@ -1236,7 +1243,7 @@
             return Err(Status::new_service_specific_error_str(
                 -1,
                 Some(format!("cannot find a VM with CID {}", cid)),
-            ))
+            ));
         };
         let instance_img_path = vm.temporary_directory.join("rkpvm_instance.img");
         let instance_img = OpenOptions::new()
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/AssignableDevice.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/AssignableDevice.aidl
new file mode 100644
index 0000000..014d78c
--- /dev/null
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/AssignableDevice.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+package android.system.virtualizationservice;
+
+/** A specification of device to be assigned to the virtual machine. */
+@RustDerive(Clone=true)
+parcelable AssignableDevice {
+    /** Path to SysFS node of the device. */
+    String node;
+
+    /** Kind of the device. */
+    String kind;
+}
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl b/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl
index 99bc076..df72e49 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl
@@ -15,6 +15,7 @@
  */
 package android.system.virtualizationservice;
 
+import android.system.virtualizationservice.AssignableDevice;
 import android.system.virtualizationservice.IVirtualMachine;
 import android.system.virtualizationservice.PartitionType;
 import android.system.virtualizationservice.VirtualMachineConfig;
@@ -55,4 +56,9 @@
      * and as such is only permitted from the shell user.
      */
     VirtualMachineDebugInfo[] debugListVms();
+
+    /**
+     * Get a list of assignable device types.
+     */
+    AssignableDevice[] getAssignableDevices();
 }
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl b/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl
index cc59b3f..947aa86 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl
@@ -15,6 +15,7 @@
  */
 package android.system.virtualizationservice_internal;
 
+import android.system.virtualizationservice.AssignableDevice;
 import android.system.virtualizationservice.VirtualMachineDebugInfo;
 import android.system.virtualizationservice_internal.AtomVmBooted;
 import android.system.virtualizationservice_internal.AtomVmCreationRequested;
@@ -59,4 +60,9 @@
      * @return the X.509 encoded certificate.
      */
     byte[] requestCertificate(in byte[] csr, in ParcelFileDescriptor instanceImgFd);
+
+    /**
+     * Get a list of assignable devices.
+     */
+    AssignableDevice[] getAssignableDevices();
 }
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index 7dfabb0..4d0b823 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -19,6 +19,7 @@
 use crate::rkpvm::request_certificate;
 use android_os_permissions_aidl::aidl::android::os::IPermissionController;
 use android_system_virtualizationservice::{
+    aidl::android::system::virtualizationservice::AssignableDevice::AssignableDevice,
     aidl::android::system::virtualizationservice::VirtualMachineDebugInfo::VirtualMachineDebugInfo,
     binder::ParcelFileDescriptor,
 };
@@ -170,6 +171,16 @@
             Status::new_exception_str(ExceptionCode::SERVICE_SPECIFIC, Some(e.to_string()))
         })
     }
+
+    fn getAssignableDevices(&self) -> binder::Result<Vec<AssignableDevice>> {
+        check_use_custom_virtual_machine()?;
+
+        // TODO(b/291191362): read VM DTBO to find assignable devices.
+        Ok(vec![AssignableDevice {
+            kind: "eh".to_owned(),
+            node: "/sys/bus/platform/devices/16d00000.eh".to_owned(),
+        }])
+    }
 }
 
 #[derive(Debug, Default)]
@@ -393,3 +404,8 @@
 fn check_manage_access() -> binder::Result<()> {
     check_permission("android.permission.MANAGE_VIRTUAL_MACHINE")
 }
+
+/// Check whether the caller of the current Binder method is allowed to use custom VMs
+fn check_use_custom_virtual_machine() -> binder::Result<()> {
+    check_permission("android.permission.USE_CUSTOM_VIRTUAL_MACHINE")
+}