[API] Wrap raw binder_rpc_unstable calls in vm_payload
Bug: 243513370
Test: atest MicrodroidTests
Change-Id: Idb1885a7c39080fd21fa6968e8bf062d935317fb
diff --git a/microdroid/vm_payload/Android.bp b/microdroid/vm_payload/Android.bp
index 925928e..dc314ce 100644
--- a/microdroid/vm_payload/Android.bp
+++ b/microdroid/vm_payload/Android.bp
@@ -14,6 +14,7 @@
"libanyhow",
"libbinder_rs",
"liblog_rust",
+ "librpcbinder_rs",
],
apex_available: [
"com.android.compos",
diff --git a/microdroid/vm_payload/include/vm_payload.h b/microdroid/vm_payload/include/vm_payload.h
index 6e065a5..dc01662 100644
--- a/microdroid/vm_payload/include/vm_payload.h
+++ b/microdroid/vm_payload/include/vm_payload.h
@@ -25,6 +25,9 @@
extern "C" {
#endif
+struct AIBinder;
+typedef struct AIBinder AIBinder;
+
/**
* Notifies the host that the payload is ready.
*
@@ -33,6 +36,27 @@
bool AVmPayload_notifyPayloadReady(void);
/**
+ * Runs a binder RPC server, serving the supplied binder service implementation on the given vsock
+ * port.
+ *
+ * If and when the server is ready for connections (it is listening on the port), `on_ready` is
+ * called to allow appropriate action to be taken - e.g. to notify clients that they may now
+ * attempt to connect with `AVmPayload_notifyPayloadReady`.
+ *
+ * The current thread is joined to the binder thread pool to handle incoming messages.
+ *
+ * \param service the service to bind to the given port.
+ * \param port vsock port.
+ * \param on_ready the callback to execute once the server is ready for connections. The callback
+ * will be called at most once.
+ * \param param param for the `on_ready` callback.
+ *
+ * \return true if the server has shutdown normally, false if it failed in some way.
+ */
+bool AVmPayload_runVsockRpcServer(AIBinder *service, unsigned int port,
+ void (*on_ready)(void *param), void *param);
+
+/**
* Get a secret that is uniquely bound to this VM instance. The secrets are 32-byte values and the
* value associated with an identifier will not change over the lifetime of the VM instance.
*
diff --git a/microdroid/vm_payload/src/vm_payload_service.rs b/microdroid/vm_payload/src/vm_payload_service.rs
index 44013c9..bec4fde 100644
--- a/microdroid/vm_payload/src/vm_payload_service.rs
+++ b/microdroid/vm_payload/src/vm_payload_service.rs
@@ -17,8 +17,10 @@
use android_system_virtualization_payload::aidl::android::system::virtualization::payload::IVmPayloadService::{
IVmPayloadService, VM_PAYLOAD_SERVICE_NAME};
use anyhow::{Context, Result};
-use binder::{wait_for_interface, Strong};
+use binder::{wait_for_interface, Strong, unstable_api::{AIBinder, new_spibinder}};
use log::{error, info, Level};
+use rpcbinder::run_vsock_rpc_server;
+use std::os::raw::c_void;
/// Notifies the host that the payload is ready.
/// Returns true if the notification succeeds else false.
@@ -42,6 +44,44 @@
get_vm_payload_service()?.notifyPayloadReady().context("Cannot notify payload ready")
}
+/// Runs a binder RPC server, serving the supplied binder service implementation on the given vsock
+/// port.
+///
+/// If and when the server is ready for connections (it is listening on the port), `on_ready` is
+/// called to allow appropriate action to be taken - e.g. to notify clients that they may now
+/// attempt to connect.
+///
+/// The current thread is joined to the binder thread pool to handle incoming messages.
+///
+/// Returns true if the server has shutdown normally, false if it failed in some way.
+///
+/// # Safety
+///
+/// The `on_ready` callback is only called inside `run_vsock_rpc_server`, within the lifetime of
+/// `ReadyNotifier` (the last parameter of `run_vsock_rpc_server`). If `on_ready` is called with
+/// wrong param, the callback execution could go wrong.
+#[no_mangle]
+pub unsafe extern "C" fn AVmPayload_runVsockRpcServer(
+ service: *mut AIBinder,
+ port: u32,
+ on_ready: Option<unsafe extern "C" fn(param: *mut c_void)>,
+ param: *mut c_void,
+) -> bool {
+ // SAFETY: AIBinder returned has correct reference count, and the ownership can
+ // safely be taken by new_spibinder.
+ let service = new_spibinder(service);
+ if let Some(service) = service {
+ run_vsock_rpc_server(service, port, || {
+ if let Some(on_ready) = on_ready {
+ on_ready(param);
+ }
+ })
+ } else {
+ error!("Failed to convert the given service from AIBinder to SpIBinder.");
+ false
+ }
+}
+
/// Get a secret that is uniquely bound to this VM instance.
///
/// # Safety
diff --git a/tests/testapk/Android.bp b/tests/testapk/Android.bp
index bb17058..da2c626 100644
--- a/tests/testapk/Android.bp
+++ b/tests/testapk/Android.bp
@@ -38,7 +38,6 @@
"com.android.microdroid.testservice-ndk",
"libbase",
"libbinder_ndk",
- "libbinder_rpc_unstable",
"MicrodroidTestNativeLibSub",
"libvm_payload",
],
diff --git a/tests/testapk/src/native/testbinary.cpp b/tests/testapk/src/native/testbinary.cpp
index 5d6ca8b..d57d224 100644
--- a/tests/testapk/src/native/testbinary.cpp
+++ b/tests/testapk/src/native/testbinary.cpp
@@ -30,7 +30,6 @@
#include <vm_main.h>
#include <vm_payload.h>
-#include <binder_rpc_unstable.hpp>
#include <string>
using android::base::ErrnoError;
@@ -122,8 +121,8 @@
abort();
}
};
- if (!RunVsockRpcServerCallback(testService->asBinder().get(), testService->SERVICE_PORT,
- callback, nullptr)) {
+ if (!AVmPayload_runVsockRpcServer(testService->asBinder().get(), testService->SERVICE_PORT,
+ callback, nullptr)) {
return Error() << "RPC Server failed to run";
}