1 // 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 //! Android VM control tool. 16 17 mod run; 18 mod sync; 19 20 use android_system_virtmanager::aidl::android::system::virtmanager::IVirtManager::IVirtManager; 21 use android_system_virtmanager::binder::{get_interface, ProcessState, Strong}; 22 use anyhow::{Context, Error}; 23 use run::command_run; 24 use std::path::PathBuf; 25 use structopt::clap::AppSettings; 26 use structopt::StructOpt; 27 28 const VIRT_MANAGER_BINDER_SERVICE_IDENTIFIER: &str = "android.system.virtmanager"; 29 30 #[derive(StructOpt)] 31 #[structopt(no_version, global_settings = &[AppSettings::DisableVersion])] 32 enum Opt { 33 /// Run a virtual machine 34 Run { 35 /// Path to VM config JSON 36 #[structopt(parse(from_os_str))] 37 config: PathBuf, 38 39 /// Detach VM from the terminal and run in the background 40 #[structopt(short, long)] 41 daemonize: bool, 42 }, 43 /// Stop a virtual machine running in the background 44 Stop { 45 /// CID of the virtual machine 46 cid: u32, 47 }, 48 /// List running virtual machines 49 List, 50 } 51 52 fn main() -> Result<(), Error> { 53 env_logger::init(); 54 let opt = Opt::from_args(); 55 56 // We need to start the thread pool for Binder to work properly, especially link_to_death. 57 ProcessState::start_thread_pool(); 58 59 let virt_manager = get_interface(VIRT_MANAGER_BINDER_SERVICE_IDENTIFIER) 60 .context("Failed to find Virt Manager service")?; 61 62 match opt { 63 Opt::Run { config, daemonize } => command_run(virt_manager, &config, daemonize), 64 Opt::Stop { cid } => command_stop(virt_manager, cid), 65 Opt::List => command_list(virt_manager), 66 } 67 } 68 69 /// Retrieve reference to a previously daemonized VM and stop it. 70 fn command_stop(virt_manager: Strong<dyn IVirtManager>, cid: u32) -> Result<(), Error> { 71 virt_manager 72 .debugDropVmRef(cid as i32) 73 .context("Failed to get VM from Virt Manager")? 74 .context("CID does not correspond to a running background VM")?; 75 Ok(()) 76 } 77 78 /// List the VMs currently running. 79 fn command_list(virt_manager: Strong<dyn IVirtManager>) -> Result<(), Error> { 80 let vms = virt_manager.debugListVms().context("Failed to get list of VMs")?; 81 println!("Running VMs: {:#?}", vms); 82 Ok(()) 83 } 84