[API] Add new service to notify host from microdroid manager

This CL adds a new service to notify the host from
microdroid manager instead of the payload process.

Bug: 243512047
Test: MicrodroidTests microdroid_manager_test
Change-Id: Ic634944f6dd5266c084f495787bf4568a4d18ed3
This commit is contained in:
Alice Wang 2022-10-04 15:24:10 +00:00
parent 249b6b4b25
commit 59a9e56fa4
7 changed files with 114 additions and 13 deletions

View File

@ -9,11 +9,10 @@ rust_ffi_static {
include_dirs: ["include"],
prefer_rlib: true,
rustlibs: [
"android.system.virtualmachineservice-rust",
"android.system.virtualization.payload-rust",
"libandroid_logger",
"libanyhow",
"libbinder_rs",
"liblog_rust",
"librpcbinder_rs",
],
}

View File

@ -12,17 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//! This module handles the interaction with virtual machine service.
//! This module handles the interaction with virtual machine payload service.
use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::IVirtualMachineService::{
VM_BINDER_SERVICE_PORT, IVirtualMachineService};
use android_system_virtualization_payload::aidl::android::system::virtualization::payload::IVmPayloadService::IVmPayloadService;
use anyhow::{Context, Result};
use binder::Strong;
use binder::{wait_for_interface, Strong};
use log::{error, info, Level};
use rpcbinder::get_vsock_rpc_interface;
/// The CID representing the host VM
const VMADDR_CID_HOST: u32 = 2;
const VM_PAYLOAD_SERVICE_NAME: &str = "virtual_machine_payload_service";
/// Notifies the host that the payload is ready.
/// Returns true if the notification succeeds else false.
@ -43,10 +41,10 @@ pub extern "C" fn notify_payload_ready() -> bool {
/// Notifies the host that the payload is ready.
/// Returns a `Result` containing error information if failed.
fn try_notify_payload_ready() -> Result<()> {
get_vm_service()?.notifyPayloadReady().context("Cannot notify payload ready")
get_vm_payload_service()?.notifyPayloadReady().context("Cannot notify payload ready")
}
fn get_vm_service() -> Result<Strong<dyn IVirtualMachineService>> {
get_vsock_rpc_interface(VMADDR_CID_HOST, VM_BINDER_SERVICE_PORT as u32)
.context("Connecting to IVirtualMachineService")
fn get_vm_payload_service() -> Result<Strong<dyn IVmPayloadService>> {
wait_for_interface(VM_PAYLOAD_SERVICE_NAME)
.context(format!("Failed to connect to service: {}", VM_PAYLOAD_SERVICE_NAME))
}

View File

@ -14,6 +14,7 @@ rust_defaults {
"android.system.virtualizationcommon-rust",
"android.system.virtualizationservice-rust",
"android.system.virtualmachineservice-rust",
"android.system.virtualization.payload-rust",
"libanyhow",
"libapexutil_rust",
"libapkverify",

View File

@ -0,0 +1,17 @@
package {
default_applicable_licenses: ["Android-Apache-2.0"],
}
aidl_interface {
name: "android.system.virtualization.payload",
srcs: ["android/system/virtualization/payload/*.aidl"],
unstable: true,
backend: {
rust: {
enabled: true,
apex_available: [
"com.android.virt",
],
},
},
}

View File

@ -0,0 +1,26 @@
/*
* 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.
*/
package android.system.virtualization.payload;
/**
* This interface regroups the tasks that payloads delegate to
* Microdroid Manager for execution.
*/
interface IVmPayloadService {
/** Notifies that the payload is ready to serve. */
void notifyPayloadReady();
}

View File

@ -17,8 +17,10 @@
mod instance;
mod ioutil;
mod payload;
mod vm_payload_service;
use crate::instance::{ApexData, ApkData, InstanceDisk, MicrodroidData, RootHash};
use crate::vm_payload_service::register_vm_payload_service;
use android_hardware_security_dice::aidl::android::hardware::security::dice::{
Config::Config, InputValues::InputValues, Mode::Mode,
};
@ -29,7 +31,7 @@ use android_system_virtualmachineservice::aidl::android::system::virtualmachines
};
use anyhow::{anyhow, bail, ensure, Context, Error, Result};
use apkverify::{get_public_key_der, verify, V4Signature};
use binder::{wait_for_interface, Strong};
use binder::{ProcessState, wait_for_interface, Strong};
use diced_utils::cbor::{encode_header, encode_number};
use glob::glob;
use itertools::sorted;
@ -386,6 +388,8 @@ fn try_run_payload(service: &Strong<dyn IVirtualMachineService>) -> Result<i32>
}
system_properties::write("dev.bootcomplete", "1").context("set dev.bootcomplete")?;
register_vm_payload_service(service.clone())?;
ProcessState::start_thread_pool();
exec_task(task, service)
}

View File

@ -0,0 +1,56 @@
// 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.
//! Implementation of the AIDL interface `IVmPayloadService`.
use android_system_virtualization_payload::aidl::android::system::virtualization::payload::IVmPayloadService::{BnVmPayloadService, IVmPayloadService};
use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::IVirtualMachineService::IVirtualMachineService;
use anyhow::{Context, Result};
use binder::{Interface, BinderFeatures, Strong, add_service};
const VM_PAYLOAD_SERVICE_NAME: &str = "virtual_machine_payload_service";
/// Implementation of `IVmPayloadService`.
struct VmPayloadService {
virtual_machine_service: Strong<dyn IVirtualMachineService>,
}
impl IVmPayloadService for VmPayloadService {
fn notifyPayloadReady(&self) -> binder::Result<()> {
self.virtual_machine_service.notifyPayloadReady()
}
}
impl Interface for VmPayloadService {}
impl VmPayloadService {
/// Creates a new `VmPayloadService` instance from the `IVirtualMachineService` reference.
fn new(vm_service: Strong<dyn IVirtualMachineService>) -> Self {
Self { virtual_machine_service: vm_service }
}
}
/// Registers the `IVmPayloadService` service.
pub(crate) fn register_vm_payload_service(
vm_service: Strong<dyn IVirtualMachineService>,
) -> Result<()> {
let vm_payload_binder = BnVmPayloadService::new_binder(
VmPayloadService::new(vm_service),
BinderFeatures::default(),
);
add_service(VM_PAYLOAD_SERVICE_NAME, vm_payload_binder.as_binder())
.with_context(|| format!("Failed to register service {}", VM_PAYLOAD_SERVICE_NAME))?;
log::info!("{} is running", VM_PAYLOAD_SERVICE_NAME);
Ok(())
}