blob: 8394e36af6e25385efb04e2810ade7d0f39eb4d3 [file] [log] [blame]
Andrew Walbrand6dce6f2021-03-05 16:39:08 +00001// Copyright 2021, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Implementation of the AIDL interface of the Virt Manager.
16
17use crate::config::load_vm_config;
18use crate::crosvm::VmInstance;
19use crate::{Cid, FIRST_GUEST_CID};
20use android_system_virtmanager::aidl::android::system::virtmanager::IVirtManager::IVirtManager;
21use android_system_virtmanager::aidl::android::system::virtmanager::IVirtualMachine::{
22 BnVirtualMachine, IVirtualMachine,
23};
24use android_system_virtmanager::binder::{self, Interface, StatusCode, Strong};
25use log::error;
26use std::sync::{Arc, Mutex};
27
28pub const BINDER_SERVICE_IDENTIFIER: &str = "android.system.virtmanager";
29
30/// Implementation of `IVirtManager`, the entry point of the AIDL service.
31#[derive(Debug, Default)]
32pub struct VirtManager {
Andrew Walbran9c01baa2021-03-08 18:23:50 +000033 state: Mutex<State>,
Andrew Walbrand6dce6f2021-03-05 16:39:08 +000034}
35
36impl Interface for VirtManager {}
37
38impl IVirtManager for VirtManager {
39 /// Create and start a new VM with the given configuration, assigning it the next available CID.
40 ///
41 /// Returns a binder `IVirtualMachine` object referring to it, as a handle for the client.
42 fn startVm(&self, config_path: &str) -> binder::Result<Strong<dyn IVirtualMachine>> {
43 let state = &mut *self.state.lock().unwrap();
44 let cid = state.next_cid;
45 let instance = start_vm(config_path, cid)?;
46 // TODO(qwandor): keep track of which CIDs are currently in use so that we can reuse them.
47 state.next_cid = state.next_cid.checked_add(1).ok_or(StatusCode::UNKNOWN_ERROR)?;
48 Ok(VirtualMachine::create(Arc::new(instance)))
49 }
50}
51
52/// Implementation of the AIDL `IVirtualMachine` interface. Used as a handle to a VM.
53#[derive(Debug)]
54struct VirtualMachine {
55 instance: Arc<VmInstance>,
56}
57
58impl VirtualMachine {
59 fn create(instance: Arc<VmInstance>) -> Strong<dyn IVirtualMachine> {
60 let binder = VirtualMachine { instance };
61 BnVirtualMachine::new_binder(binder)
62 }
63}
64
65impl Interface for VirtualMachine {}
66
67impl IVirtualMachine for VirtualMachine {
68 fn getCid(&self) -> binder::Result<i32> {
69 Ok(self.instance.cid as i32)
70 }
71}
72
73/// The mutable state of the Virt Manager. There should only be one instance of this struct.
74#[derive(Debug)]
75struct State {
76 next_cid: Cid,
77}
78
79impl Default for State {
80 fn default() -> Self {
81 State { next_cid: FIRST_GUEST_CID }
82 }
83}
84
85/// Start a new VM instance from the given VM config filename. This assumes the VM is not already
86/// running.
87fn start_vm(config_path: &str, cid: Cid) -> binder::Result<VmInstance> {
88 let config = load_vm_config(config_path).map_err(|e| {
89 error!("Failed to load VM config {}: {:?}", config_path, e);
90 StatusCode::BAD_VALUE
91 })?;
92 Ok(VmInstance::start(&config, cid).map_err(|e| {
93 error!("Failed to start VM {}: {:?}", config_path, e);
94 StatusCode::UNKNOWN_ERROR
95 })?)
96}