Move VsockFactory into VM client library.
Test: ComposHostTestCases compos_key_tests Change-Id: I0500c9ad46df4c004f033161ade53b94d3d2afea
This commit is contained in:
parent
d0ef400bd1
commit
1072cc0580
|
@ -13,7 +13,6 @@ rust_library {
|
|||
"libanyhow",
|
||||
"libbinder_common",
|
||||
"libbinder_rpc_unstable_bindgen",
|
||||
"libbinder_rs",
|
||||
"liblog_rust",
|
||||
"libnum_traits",
|
||||
"librustutils",
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
//! Helper for converting Error types to what Binder expects
|
||||
|
||||
use binder::{ExceptionCode, Result as BinderResult};
|
||||
use android_system_virtualizationservice::binder::{ExceptionCode, Result as BinderResult};
|
||||
use binder_common::new_binder_exception;
|
||||
use log::warn;
|
||||
use std::fmt::Debug;
|
||||
|
|
|
@ -20,7 +20,6 @@ use crate::timeouts::timeouts;
|
|||
use crate::{COMPOS_APEX_ROOT, COMPOS_DATA_ROOT, COMPOS_VSOCK_PORT, DEFAULT_VM_CONFIG_PATH};
|
||||
use android_system_virtualizationservice::aidl::android::system::virtualizationservice::{
|
||||
DeathReason::DeathReason,
|
||||
IVirtualMachine::IVirtualMachine,
|
||||
IVirtualMachineCallback::{BnVirtualMachineCallback, IVirtualMachineCallback},
|
||||
IVirtualizationService::IVirtualizationService,
|
||||
VirtualMachineAppConfig::{DebugLevel::DebugLevel, VirtualMachineAppConfig},
|
||||
|
@ -29,19 +28,13 @@ use android_system_virtualizationservice::aidl::android::system::virtualizations
|
|||
use android_system_virtualizationservice::binder::{
|
||||
BinderFeatures, Interface, ParcelFileDescriptor, Result as BinderResult, Strong,
|
||||
};
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use binder::{
|
||||
unstable_api::{new_spibinder, AIBinder},
|
||||
FromIBinder,
|
||||
};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use compos_aidl_interface::aidl::com::android::compos::ICompOsService::ICompOsService;
|
||||
use log::{info, warn};
|
||||
use rustutils::system_properties;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::num::NonZeroU32;
|
||||
use std::os::raw;
|
||||
use std::os::unix::io::IntoRawFd;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::thread;
|
||||
use vmclient::VmInstance;
|
||||
|
@ -159,13 +152,7 @@ impl ComposClient {
|
|||
|
||||
/// Create and return an RPC Binder connection to the Comp OS service in the VM.
|
||||
pub fn get_service(&self) -> Result<Strong<dyn ICompOsService>> {
|
||||
let mut vsock_factory = VsockFactory::new(&*self.0.vm);
|
||||
|
||||
let ibinder = vsock_factory
|
||||
.connect_rpc_client()
|
||||
.ok_or_else(|| anyhow!("Failed to connect to CompOS service"))?;
|
||||
|
||||
FromIBinder::try_from(ibinder).context("Connecting to CompOS service")
|
||||
self.0.get_service(COMPOS_VSOCK_PORT).context("Connecting to CompOS service")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,56 +199,6 @@ fn want_protected_vm() -> Result<bool> {
|
|||
bail!("No VM support available")
|
||||
}
|
||||
|
||||
struct VsockFactory<'a> {
|
||||
vm: &'a dyn IVirtualMachine,
|
||||
}
|
||||
|
||||
impl<'a> VsockFactory<'a> {
|
||||
fn new(vm: &'a dyn IVirtualMachine) -> Self {
|
||||
Self { vm }
|
||||
}
|
||||
|
||||
fn connect_rpc_client(&mut self) -> Option<binder::SpIBinder> {
|
||||
let param = self.as_void_ptr();
|
||||
|
||||
unsafe {
|
||||
// SAFETY: AIBinder returned by RpcPreconnectedClient has correct reference count, and
|
||||
// the ownership can be safely taken by new_spibinder.
|
||||
// RpcPreconnectedClient does not take ownership of param, only passing it to
|
||||
// request_fd.
|
||||
let binder =
|
||||
binder_rpc_unstable_bindgen::RpcPreconnectedClient(Some(Self::request_fd), param)
|
||||
as *mut AIBinder;
|
||||
new_spibinder(binder)
|
||||
}
|
||||
}
|
||||
|
||||
fn as_void_ptr(&mut self) -> *mut raw::c_void {
|
||||
self as *mut _ as *mut raw::c_void
|
||||
}
|
||||
|
||||
fn try_new_vsock_fd(&self) -> Result<i32> {
|
||||
let vsock = self.vm.connectVsock(COMPOS_VSOCK_PORT as i32)?;
|
||||
// Ownership of the fd is transferred to binder
|
||||
Ok(vsock.into_raw_fd())
|
||||
}
|
||||
|
||||
fn new_vsock_fd(&self) -> i32 {
|
||||
self.try_new_vsock_fd().unwrap_or_else(|e| {
|
||||
warn!("Connecting vsock failed: {}", e);
|
||||
-1_i32
|
||||
})
|
||||
}
|
||||
|
||||
unsafe extern "C" fn request_fd(param: *mut raw::c_void) -> raw::c_int {
|
||||
// SAFETY: This is only ever called by RpcPreconnectedClient, within the lifetime of the
|
||||
// VsockFactory, with param taking the value returned by as_void_ptr (so a properly aligned
|
||||
// non-null pointer to an initialized instance).
|
||||
let vsock_factory = param as *mut Self;
|
||||
vsock_factory.as_ref().unwrap().new_vsock_fd()
|
||||
}
|
||||
}
|
||||
|
||||
struct VmCallback();
|
||||
|
||||
impl Interface for VmCallback {}
|
||||
|
|
|
@ -9,9 +9,14 @@ rust_library {
|
|||
edition: "2021",
|
||||
rustlibs: [
|
||||
"android.system.virtualizationservice-rust",
|
||||
"libbinder_rpc_unstable_bindgen",
|
||||
"libbinder_rs",
|
||||
"liblog_rust",
|
||||
"libthiserror",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbinder_rpc_unstable",
|
||||
],
|
||||
apex_available: [
|
||||
"com.android.compos",
|
||||
"com.android.virt",
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
use super::DeathReason;
|
||||
use android_system_virtualizationservice::binder::StatusCode;
|
||||
use thiserror::Error;
|
||||
|
||||
/// An error while waiting for a VM to do something.
|
||||
|
@ -31,3 +32,14 @@ pub enum VmWaitError {
|
|||
#[error("VM payload finished.")]
|
||||
Finished,
|
||||
}
|
||||
|
||||
/// An error connection to a VM RPC Binder service.
|
||||
#[derive(Clone, Debug, Error)]
|
||||
pub enum GetServiceError {
|
||||
/// The RPC binder connection failed.
|
||||
#[error("Vsock connection to RPC binder failed.")]
|
||||
ConnectionFailed,
|
||||
/// The AIDL service type didn't match.
|
||||
#[error("Service type didn't match ({0}).")]
|
||||
WrongServiceType(StatusCode),
|
||||
}
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
|
||||
mod death_reason;
|
||||
mod errors;
|
||||
mod rpc_binder;
|
||||
mod sync;
|
||||
|
||||
pub use crate::death_reason::DeathReason;
|
||||
pub use crate::errors::VmWaitError;
|
||||
use crate::sync::Monitor;
|
||||
pub use crate::errors::{GetServiceError, VmWaitError};
|
||||
use crate::{rpc_binder::VsockFactory, sync::Monitor};
|
||||
use android_system_virtualizationservice::{
|
||||
aidl::android::system::virtualizationservice::{
|
||||
DeathReason::DeathReason as AidlDeathReason,
|
||||
|
@ -31,7 +32,7 @@ use android_system_virtualizationservice::{
|
|||
VirtualMachineState::VirtualMachineState,
|
||||
},
|
||||
binder::{
|
||||
wait_for_interface, BinderFeatures, DeathRecipient, IBinder, Interface,
|
||||
wait_for_interface, BinderFeatures, DeathRecipient, FromIBinder, IBinder, Interface,
|
||||
ParcelFileDescriptor, Result as BinderResult, StatusCode, Strong,
|
||||
},
|
||||
};
|
||||
|
@ -130,6 +131,18 @@ impl VmInstance {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to connect to an RPC Binder service provided by the VM on the given vsock port.
|
||||
pub fn get_service<T: FromIBinder + ?Sized>(
|
||||
&self,
|
||||
port: u32,
|
||||
) -> Result<Strong<T>, GetServiceError> {
|
||||
let mut vsock_factory = VsockFactory::new(&*self.vm, port);
|
||||
|
||||
let ibinder = vsock_factory.connect_rpc_client()?;
|
||||
|
||||
FromIBinder::try_from(ibinder).map_err(GetServiceError::WrongServiceType)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for VmInstance {
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright 2022, 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.
|
||||
|
||||
use crate::errors::GetServiceError;
|
||||
use android_system_virtualizationservice::{
|
||||
aidl::android::system::virtualizationservice::IVirtualMachine::IVirtualMachine,
|
||||
};
|
||||
use binder::unstable_api::{new_spibinder, AIBinder};
|
||||
use log::warn;
|
||||
use std::os::{raw, unix::io::IntoRawFd};
|
||||
|
||||
pub struct VsockFactory<'a> {
|
||||
vm: &'a dyn IVirtualMachine,
|
||||
port: u32,
|
||||
}
|
||||
|
||||
impl<'a> VsockFactory<'a> {
|
||||
pub fn new(vm: &'a dyn IVirtualMachine, port: u32) -> Self {
|
||||
Self { vm, port }
|
||||
}
|
||||
|
||||
pub fn connect_rpc_client(&mut self) -> Result<binder::SpIBinder, GetServiceError> {
|
||||
let param = self.as_void_ptr();
|
||||
|
||||
unsafe {
|
||||
// SAFETY: AIBinder returned by RpcPreconnectedClient has correct reference count, and
|
||||
// the ownership can be safely taken by new_spibinder.
|
||||
// RpcPreconnectedClient does not take ownership of param, only passing it to
|
||||
// request_fd.
|
||||
let binder =
|
||||
binder_rpc_unstable_bindgen::RpcPreconnectedClient(Some(Self::request_fd), param)
|
||||
as *mut AIBinder;
|
||||
new_spibinder(binder).ok_or(GetServiceError::ConnectionFailed)
|
||||
}
|
||||
}
|
||||
|
||||
fn as_void_ptr(&mut self) -> *mut raw::c_void {
|
||||
self as *mut _ as *mut raw::c_void
|
||||
}
|
||||
|
||||
fn new_vsock_fd(&self) -> i32 {
|
||||
match self.vm.connectVsock(self.port as i32) {
|
||||
Ok(vsock) => {
|
||||
// Ownership of the fd is transferred to binder
|
||||
vsock.into_raw_fd()
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Vsock connection failed: {}", e);
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn request_fd(param: *mut raw::c_void) -> raw::c_int {
|
||||
// SAFETY: This is only ever called by RpcPreconnectedClient, within the lifetime of the
|
||||
// VsockFactory, with param taking the value returned by as_void_ptr (so a properly aligned
|
||||
// non-null pointer to an initialized instance).
|
||||
let vsock_factory = param as *mut Self;
|
||||
vsock_factory.as_ref().unwrap().new_vsock_fd()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue