Merge "Skip AVFHostTestCases on Cuttlefish"
diff --git a/apex/sign_virt_apex.py b/apex/sign_virt_apex.py
index df95323..6863b0c 100644
--- a/apex/sign_virt_apex.py
+++ b/apex/sign_virt_apex.py
@@ -317,22 +317,6 @@
RunCommand(args, cmd)
-def SignSuperImg(args, key, super_img, work_dir):
- # unpack super.img
- UnpackSuperImg(args, super_img, work_dir)
-
- system_a_img = os.path.join(work_dir, 'system_a.img')
- vendor_a_img = os.path.join(work_dir, 'vendor_a.img')
-
- # re-sign each partition
- system_a_f = Async(AddHashTreeFooter, args, key, system_a_img)
- vendor_a_f = Async(AddHashTreeFooter, args, key, vendor_a_img)
-
- # 3. re-pack super.img
- partitions = {"system_a": system_a_img, "vendor_a": vendor_a_img}
- Async(MakeSuperImage, args, partitions, super_img, wait=[system_a_f, vendor_a_f])
-
-
def ReplaceBootloaderPubkey(args, key, bootloader, bootloader_pubkey):
if os.path.basename(bootloader) in args.key_overrides:
key = args.key_overrides[os.path.basename(bootloader)]
@@ -399,13 +383,20 @@
init_boot_img_f = Async(AddHashFooter, args, key, files['init_boot.img'])
# re-sign super.img
- super_img_f = Async(SignSuperImg, args, key, files['super.img'], unpack_dir.name)
+ # 1. unpack super.img
+ # 2. resign system and vendor
+ # 3. repack super.img out of resigned system and vendor
+ UnpackSuperImg(args, files['super.img'], unpack_dir.name)
+ system_a_f = Async(AddHashTreeFooter, args, key, system_a_img)
+ vendor_a_f = Async(AddHashTreeFooter, args, key, vendor_a_img)
+ partitions = {"system_a": system_a_img, "vendor_a": vendor_a_img}
+ Async(MakeSuperImage, args, partitions, files['super.img'], wait=[system_a_f, vendor_a_f])
# re-generate vbmeta from re-signed {boot, vendor_boot, init_boot, system_a, vendor_a}.img
Async(MakeVbmetaImage, args, key, files['vbmeta.img'],
images=[files['boot.img'], files['vendor_boot.img'],
files['init_boot.img'], system_a_img, vendor_a_img],
- wait=[boot_img_f, vendor_boot_img_f, init_boot_img_f, super_img_f])
+ wait=[boot_img_f, vendor_boot_img_f, init_boot_img_f, system_a_f, vendor_a_f])
# Re-sign bootconfigs and the uboot_env with the same key
bootconfig_sign_key = key
diff --git a/authfs/Android.bp b/authfs/Android.bp
index 7788702..523da35 100644
--- a/authfs/Android.bp
+++ b/authfs/Android.bp
@@ -16,6 +16,7 @@
"libauthfs_fsverity_metadata",
"libbinder_rs",
"libcfg_if",
+ "libclap",
"libfsverity_digests_proto_rust",
"libfuse_rust",
"liblibc",
@@ -24,7 +25,6 @@
"libopenssl",
"libprotobuf",
"librpcbinder_rs",
- "libstructopt",
"libthiserror",
],
prefer_rlib: true,
diff --git a/authfs/src/main.rs b/authfs/src/main.rs
index c09ed71..9ff0ae3 100644
--- a/authfs/src/main.rs
+++ b/authfs/src/main.rs
@@ -33,13 +33,13 @@
//! the state is not persistent, thus only new file/directory are supported.
use anyhow::{anyhow, bail, Result};
+use clap::Parser;
use log::error;
use protobuf::Message;
use std::convert::TryInto;
use std::fs::File;
use std::num::NonZeroU8;
use std::path::{Path, PathBuf};
-use structopt::StructOpt;
mod common;
mod file;
@@ -53,22 +53,21 @@
use fsverity_digests_proto::fsverity_digests::FSVerityDigests;
use fusefs::{AuthFs, AuthFsEntry, LazyVerifiedReadonlyFile};
-#[derive(StructOpt)]
+#[derive(Parser)]
struct Args {
/// Mount point of AuthFS.
- #[structopt(parse(from_os_str))]
mount_point: PathBuf,
/// CID of the VM where the service runs.
- #[structopt(long)]
+ #[clap(long)]
cid: u32,
/// Extra options to FUSE
- #[structopt(short = "o")]
+ #[clap(short = 'o')]
extra_options: Option<String>,
/// Number of threads to serve FUSE requests.
- #[structopt(short = "j")]
+ #[clap(short = 'j')]
thread_number: Option<NonZeroU8>,
/// A read-only remote file with integrity check. Can be multiple.
@@ -76,21 +75,21 @@
/// For example, `--remote-ro-file 5:sha256-1234abcd` tells the filesystem to associate the
/// file $MOUNTPOINT/5 with a remote FD 5, and has a fs-verity digest with sha256 of the hex
/// value 1234abcd.
- #[structopt(long, parse(try_from_str = parse_remote_ro_file_option))]
+ #[clap(long, value_parser = parse_remote_ro_file_option)]
remote_ro_file: Vec<OptionRemoteRoFile>,
/// A read-only remote file without integrity check. Can be multiple.
///
/// For example, `--remote-ro-file-unverified 5` tells the filesystem to associate the file
/// $MOUNTPOINT/5 with a remote FD 5.
- #[structopt(long)]
+ #[clap(long)]
remote_ro_file_unverified: Vec<i32>,
/// A new read-writable remote file with integrity check. Can be multiple.
///
/// For example, `--remote-new-rw-file 5` tells the filesystem to associate the file
/// $MOUNTPOINT/5 with a remote FD 5.
- #[structopt(long)]
+ #[clap(long)]
remote_new_rw_file: Vec<i32>,
/// A read-only directory that represents a remote directory. The directory view is constructed
@@ -107,7 +106,7 @@
/// include a file like /5/system/framework/framework.jar. "prefix/" tells the filesystem to
/// strip the path (e.g. "system/") from the mount point to match the expected location of the
/// remote FD (e.g. a directory FD of "/system" in the remote).
- #[structopt(long, parse(try_from_str = parse_remote_new_ro_dir_option))]
+ #[clap(long, value_parser = parse_remote_new_ro_dir_option)]
remote_ro_dir: Vec<OptionRemoteRoDir>,
/// A new directory that is assumed empty in the backing filesystem. New files created in this
@@ -116,14 +115,15 @@
///
/// For example, `--remote-new-rw-dir 5` tells the filesystem to associate $MOUNTPOINT/5
/// with a remote dir FD 5.
- #[structopt(long)]
+ #[clap(long)]
remote_new_rw_dir: Vec<i32>,
/// Enable debugging features.
- #[structopt(long)]
+ #[clap(long)]
debug: bool,
}
+#[derive(Clone)]
struct OptionRemoteRoFile {
/// ID to refer to the remote file.
remote_fd: i32,
@@ -132,6 +132,7 @@
digest: String,
}
+#[derive(Clone)]
struct OptionRemoteRoDir {
/// ID to refer to the remote dir.
remote_dir_fd: i32,
@@ -305,7 +306,7 @@
}
fn try_main() -> Result<()> {
- let args = Args::from_args_safe()?;
+ let args = Args::parse();
let log_level = if args.debug { log::Level::Debug } else { log::Level::Info };
android_logger::init_once(
diff --git a/compos/Android.bp b/compos/Android.bp
index 6aa9d3d..ea7c4d6 100644
--- a/compos/Android.bp
+++ b/compos/Android.bp
@@ -13,7 +13,6 @@
"libandroid_logger",
"libanyhow",
"libbinder_rs",
- "libclap",
"libcompos_common",
"liblibc",
"liblog_rust",
diff --git a/compos/composd_cmd/composd_cmd.rs b/compos/composd_cmd/composd_cmd.rs
index d5feed8..b6d82aa 100644
--- a/compos/composd_cmd/composd_cmd.rs
+++ b/compos/composd_cmd/composd_cmd.rs
@@ -31,30 +31,32 @@
},
};
use anyhow::{bail, Context, Result};
+use clap::Parser;
use compos_common::timeouts::TIMEOUTS;
use std::sync::{Arc, Condvar, Mutex};
use std::time::Duration;
+#[derive(Parser)]
+enum Actions {
+ /// Compile classpath for real. Output can be used after a reboot.
+ StagedApexCompile {},
+
+ /// Compile classpath in a debugging VM. Output is ignored.
+ TestCompile {
+ /// If any APEX is staged, prefer the staged version.
+ #[clap(long)]
+ prefer_staged: bool,
+ },
+}
+
fn main() -> Result<()> {
- #[rustfmt::skip]
- let app = clap::App::new("composd_cmd")
- .subcommand(
- clap::SubCommand::with_name("staged-apex-compile"))
- .subcommand(
- clap::SubCommand::with_name("test-compile")
- .arg(clap::Arg::with_name("prefer-staged").long("prefer-staged")),
- );
- let args = app.get_matches();
+ let action = Actions::parse();
ProcessState::start_thread_pool();
- match args.subcommand() {
- Some(("staged-apex-compile", _)) => run_staged_apex_compile()?,
- Some(("test-compile", sub_matches)) => {
- let prefer_staged = sub_matches.is_present("prefer-staged");
- run_test_compile(prefer_staged)?;
- }
- _ => panic!("Unrecognized subcommand"),
+ match action {
+ Actions::StagedApexCompile {} => run_staged_apex_compile()?,
+ Actions::TestCompile { prefer_staged } => run_test_compile(prefer_staged)?,
}
println!("All Ok!");
diff --git a/compos/verify/verify.rs b/compos/verify/verify.rs
index 2ece8f5..3abdc74 100644
--- a/compos/verify/verify.rs
+++ b/compos/verify/verify.rs
@@ -20,6 +20,7 @@
use android_logger::LogId;
use anyhow::{bail, Context, Result};
use binder::ProcessState;
+use clap::{Parser, ValueEnum};
use compos_common::compos_client::{ComposClient, VmParameters};
use compos_common::odrefresh::{
CURRENT_ARTIFACTS_SUBDIR, ODREFRESH_OUTPUT_ROOT_DIR, PENDING_ARTIFACTS_SUBDIR,
@@ -37,6 +38,24 @@
const MAX_FILE_SIZE_BYTES: u64 = 100 * 1024;
+#[derive(Parser)]
+struct Args {
+ /// Type of the VM instance
+ #[clap(long, value_enum)]
+ instance: Instance,
+
+ /// Starts the VM in debug mode
+ #[clap(long, action)]
+ debug: bool,
+}
+
+#[derive(ValueEnum, Clone)]
+enum Instance {
+ Current,
+ Pending,
+ Test,
+}
+
fn main() {
android_logger::init_once(
android_logger::Config::default()
@@ -57,23 +76,11 @@
}
fn try_main() -> Result<()> {
- let matches = clap::App::new("compos_verify")
- .arg(
- clap::Arg::with_name("instance")
- .long("instance")
- .takes_value(true)
- .required(true)
- .possible_values(&["current", "pending", "test"]),
- )
- .arg(clap::Arg::with_name("debug").long("debug"))
- .get_matches();
-
- let debug_mode = matches.is_present("debug");
- let (instance_dir, artifacts_dir) = match matches.value_of("instance").unwrap() {
- "current" => (CURRENT_INSTANCE_DIR, CURRENT_ARTIFACTS_SUBDIR),
- "pending" => (CURRENT_INSTANCE_DIR, PENDING_ARTIFACTS_SUBDIR),
- "test" => (TEST_INSTANCE_DIR, TEST_ARTIFACTS_SUBDIR),
- _ => unreachable!("Unexpected instance name"),
+ let args = Args::parse();
+ let (instance_dir, artifacts_dir) = match args.instance {
+ Instance::Current => (CURRENT_INSTANCE_DIR, CURRENT_ARTIFACTS_SUBDIR),
+ Instance::Pending => (CURRENT_INSTANCE_DIR, PENDING_ARTIFACTS_SUBDIR),
+ Instance::Test => (TEST_INSTANCE_DIR, TEST_ARTIFACTS_SUBDIR),
};
let instance_dir = Path::new(COMPOS_DATA_ROOT).join(instance_dir);
@@ -104,7 +111,7 @@
instance_image,
&idsig,
&idsig_manifest_apk,
- &VmParameters { debug_mode, ..Default::default() },
+ &VmParameters { debug_mode: args.debug, ..Default::default() },
)?;
let service = vm_instance.connect_service()?;
diff --git a/microdroid/initrd/Android.bp b/microdroid/initrd/Android.bp
index a9d0da3..d8e7069 100644
--- a/microdroid/initrd/Android.bp
+++ b/microdroid/initrd/Android.bp
@@ -7,7 +7,7 @@
srcs: ["src/main.rs"],
rustlibs: [
"libanyhow",
- "libstructopt",
+ "libclap",
],
prefer_rlib: true,
}
diff --git a/microdroid/initrd/src/main.rs b/microdroid/initrd/src/main.rs
index 1023a40..69c6ae4 100644
--- a/microdroid/initrd/src/main.rs
+++ b/microdroid/initrd/src/main.rs
@@ -14,26 +14,23 @@
//! Append bootconfig to initrd image
use anyhow::Result;
-
+use clap::Parser;
use std::fs::File;
use std::io::{Read, Write};
use std::path::PathBuf;
-use structopt::StructOpt;
const FOOTER_ALIGNMENT: usize = 4;
const ZEROS: [u8; 4] = [0u8; 4_usize];
-#[derive(StructOpt, Debug)]
+#[derive(Parser, Debug)]
struct Args {
- /// Output
- #[structopt(parse(from_os_str), long = "output")]
- output: PathBuf,
/// Initrd (without bootconfig)
- #[structopt(parse(from_os_str))]
initrd: PathBuf,
/// Bootconfig
- #[structopt(parse(from_os_str))]
bootconfigs: Vec<PathBuf>,
+ /// Output
+ #[clap(long = "output")]
+ output: PathBuf,
}
fn get_checksum(file_path: &PathBuf) -> Result<u32> {
@@ -67,7 +64,7 @@
}
fn try_main() -> Result<()> {
- let args = Args::from_args_safe()?;
+ let args = Args::parse();
attach_bootconfig(args.initrd, args.bootconfigs, args.output)?;
Ok(())
}
diff --git a/vm/Android.bp b/vm/Android.bp
index eac640e..7b016d4 100644
--- a/vm/Android.bp
+++ b/vm/Android.bp
@@ -12,6 +12,7 @@
"android.system.virtualizationservice-rust",
"libanyhow",
"libbinder_rs",
+ "libclap",
"libenv_logger",
"liblibc",
"liblog_rust",
@@ -19,7 +20,6 @@
"librustutils",
"libserde_json",
"libserde",
- "libstructopt",
"libvmconfig",
"libvmclient",
"libzip",
diff --git a/vm/src/main.rs b/vm/src/main.rs
index b35bd4b..0845897 100644
--- a/vm/src/main.rs
+++ b/vm/src/main.rs
@@ -24,110 +24,104 @@
};
use anyhow::{Context, Error};
use binder::ProcessState;
+use clap::Parser;
use create_idsig::command_create_idsig;
use create_partition::command_create_partition;
use run::{command_run, command_run_app};
use rustutils::system_properties;
use std::path::{Path, PathBuf};
-use structopt::clap::AppSettings;
-use structopt::StructOpt;
#[derive(Debug)]
struct Idsigs(Vec<PathBuf>);
-#[derive(StructOpt)]
-#[structopt(no_version, global_settings = &[AppSettings::DisableVersion])]
+#[derive(Parser)]
enum Opt {
/// Run a virtual machine with a config in APK
RunApp {
- /// Name of VM
- #[structopt(long)]
- name: Option<String>,
-
/// Path to VM Payload APK
- #[structopt(parse(from_os_str))]
apk: PathBuf,
/// Path to idsig of the APK
- #[structopt(parse(from_os_str))]
idsig: PathBuf,
/// Path to the instance image. Created if not exists.
- #[structopt(parse(from_os_str))]
instance: PathBuf,
/// Path to VM config JSON within APK (e.g. assets/vm_config.json)
config_path: String,
+ /// Name of VM
+ #[clap(long)]
+ name: Option<String>,
+
/// Detach VM from the terminal and run in the background
- #[structopt(short, long)]
+ #[clap(short, long)]
daemonize: bool,
/// Path to file for VM console output.
- #[structopt(long)]
+ #[clap(long)]
console: Option<PathBuf>,
/// Path to file for VM log output.
- #[structopt(long)]
+ #[clap(long)]
log: Option<PathBuf>,
/// Path to file where ramdump is recorded on kernel panic
- #[structopt(long)]
+ #[clap(long)]
ramdump: Option<PathBuf>,
/// Debug level of the VM. Supported values: "none" (default), "app_only", and "full".
- #[structopt(long, default_value = "none", parse(try_from_str=parse_debug_level))]
+ #[clap(long, default_value = "none", value_parser = parse_debug_level)]
debug: DebugLevel,
/// Run VM in protected mode.
- #[structopt(short, long)]
+ #[clap(short, long)]
protected: bool,
/// Memory size (in MiB) of the VM. If unspecified, defaults to the value of `memory_mib`
/// in the VM config file.
- #[structopt(short, long)]
+ #[clap(short, long)]
mem: Option<u32>,
/// Number of vCPUs in the VM. If unspecified, defaults to 1.
- #[structopt(long)]
+ #[clap(long)]
cpus: Option<u32>,
/// Comma separated list of task profile names to apply to the VM
- #[structopt(long)]
+ #[clap(long)]
task_profiles: Vec<String>,
/// Paths to extra idsig files.
- #[structopt(long = "extra-idsig")]
+ #[clap(long = "extra-idsig")]
extra_idsigs: Vec<PathBuf>,
},
/// Run a virtual machine
Run {
- /// Name of VM
- #[structopt(long)]
- name: Option<String>,
-
/// Path to VM config JSON
- #[structopt(parse(from_os_str))]
config: PathBuf,
+ /// Name of VM
+ #[clap(long)]
+ name: Option<String>,
+
/// Detach VM from the terminal and run in the background
- #[structopt(short, long)]
+ #[clap(short, long)]
daemonize: bool,
/// Number of vCPUs in the VM. If unspecified, defaults to 1.
- #[structopt(long)]
+ #[clap(long)]
cpus: Option<u32>,
/// Comma separated list of task profile names to apply to the VM
- #[structopt(long)]
+ #[clap(long)]
task_profiles: Vec<String>,
/// Path to file for VM console output.
- #[structopt(long)]
+ #[clap(long)]
console: Option<PathBuf>,
/// Path to file for VM log output.
- #[structopt(long)]
+ #[clap(long)]
log: Option<PathBuf>,
},
/// Stop a virtual machine running in the background
@@ -142,23 +136,22 @@
/// Create a new empty partition to be used as a writable partition for a VM
CreatePartition {
/// Path at which to create the image file
- #[structopt(parse(from_os_str))]
path: PathBuf,
/// The desired size of the partition, in bytes.
size: u64,
/// Type of the partition
- #[structopt(short="t", long="type", default_value="raw", parse(try_from_str=parse_partition_type))]
+ #[clap(short = 't', long = "type", default_value = "raw",
+ value_parser = parse_partition_type)]
partition_type: PartitionType,
},
/// Creates or update the idsig file by digesting the input APK file.
CreateIdsig {
/// Path to VM Payload APK
- #[structopt(parse(from_os_str))]
apk: PathBuf,
+
/// Path to idsig of the APK
- #[structopt(parse(from_os_str))]
path: PathBuf,
},
}
@@ -182,7 +175,7 @@
fn main() -> Result<(), Error> {
env_logger::init();
- let opt = Opt::from_args();
+ let opt = Opt::parse();
// We need to start the thread pool for Binder to work properly, especially link_to_death.
ProcessState::start_thread_pool();