1*c2e18aaaSAndroid Build Coastguard Worker use clap::{Args, Parser, Subcommand}; 2*c2e18aaaSAndroid Build Coastguard Worker 3*c2e18aaaSAndroid Build Coastguard Worker #[derive(Parser)] 4*c2e18aaaSAndroid Build Coastguard Worker #[command( 5*c2e18aaaSAndroid Build Coastguard Worker about = "Tool to push your rebuilt modules to your device.\nSet ANDROID_SERIAL to choose your device if there is more than one." 6*c2e18aaaSAndroid Build Coastguard Worker )] 7*c2e18aaaSAndroid Build Coastguard Worker #[command(version = "0.4")] 8*c2e18aaaSAndroid Build Coastguard Worker pub struct Cli { 9*c2e18aaaSAndroid Build Coastguard Worker #[command(subcommand)] 10*c2e18aaaSAndroid Build Coastguard Worker pub command: Commands, 11*c2e18aaaSAndroid Build Coastguard Worker #[clap(flatten)] 12*c2e18aaaSAndroid Build Coastguard Worker pub global_options: GlobalOptions, 13*c2e18aaaSAndroid Build Coastguard Worker } 14*c2e18aaaSAndroid Build Coastguard Worker 15*c2e18aaaSAndroid Build Coastguard Worker #[derive(Subcommand)] 16*c2e18aaaSAndroid Build Coastguard Worker pub enum Commands { 17*c2e18aaaSAndroid Build Coastguard Worker /// Shows the file differences between build tree and host. 18*c2e18aaaSAndroid Build Coastguard Worker /// Show the actions that would be run. 19*c2e18aaaSAndroid Build Coastguard Worker Status, 20*c2e18aaaSAndroid Build Coastguard Worker /// Updates the device (via adb push) with files from $ANDROID_PRODUCT_OUT. 21*c2e18aaaSAndroid Build Coastguard Worker /// Only pushes files listed on --partitions. 22*c2e18aaaSAndroid Build Coastguard Worker /// This does not work well when $ANDROID_PRODUCT_OUT and the device image 23*c2e18aaaSAndroid Build Coastguard Worker /// are vastly different. You should reimage the device in that case. 24*c2e18aaaSAndroid Build Coastguard Worker Update, 25*c2e18aaaSAndroid Build Coastguard Worker /// Adds module name to the list of tracked modules. 26*c2e18aaaSAndroid Build Coastguard Worker /// If an installed file under $ANDROID_PRODUCT_OUT is not 27*c2e18aaaSAndroid Build Coastguard Worker /// part of a tracked module or the base image, then it will 28*c2e18aaaSAndroid Build Coastguard Worker /// not be pushed to the device. 29*c2e18aaaSAndroid Build Coastguard Worker Track(ModuleNames), 30*c2e18aaaSAndroid Build Coastguard Worker /// Change the base module we are tracking from `droid` to something else. 31*c2e18aaaSAndroid Build Coastguard Worker TrackBase(BaseModule), 32*c2e18aaaSAndroid Build Coastguard Worker /// Removes module name from list of tracked modules. 33*c2e18aaaSAndroid Build Coastguard Worker /// See `track` for more details. 34*c2e18aaaSAndroid Build Coastguard Worker Untrack(ModuleNames), 35*c2e18aaaSAndroid Build Coastguard Worker /// Removes untracked files from the device. 36*c2e18aaaSAndroid Build Coastguard Worker Clean { 37*c2e18aaaSAndroid Build Coastguard Worker #[clap(long, short)] 38*c2e18aaaSAndroid Build Coastguard Worker force: bool, 39*c2e18aaaSAndroid Build Coastguard Worker }, 40*c2e18aaaSAndroid Build Coastguard Worker } 41*c2e18aaaSAndroid Build Coastguard Worker 42*c2e18aaaSAndroid Build Coastguard Worker #[derive(Debug, Args)] 43*c2e18aaaSAndroid Build Coastguard Worker pub struct ModuleNames { 44*c2e18aaaSAndroid Build Coastguard Worker /// List one or modules, space separated. 45*c2e18aaaSAndroid Build Coastguard Worker /// Use the module name in Android.bp 46*c2e18aaaSAndroid Build Coastguard Worker pub modules: Vec<String>, 47*c2e18aaaSAndroid Build Coastguard Worker } 48*c2e18aaaSAndroid Build Coastguard Worker 49*c2e18aaaSAndroid Build Coastguard Worker #[derive(Debug, Args)] 50*c2e18aaaSAndroid Build Coastguard Worker pub struct BaseModule { 51*c2e18aaaSAndroid Build Coastguard Worker /// The module name the system image is built from like 'droid' or 'sync'. 52*c2e18aaaSAndroid Build Coastguard Worker /// It can also be an unbundled mainline module name. 53*c2e18aaaSAndroid Build Coastguard Worker pub base: String, 54*c2e18aaaSAndroid Build Coastguard Worker } 55*c2e18aaaSAndroid Build Coastguard Worker 56*c2e18aaaSAndroid Build Coastguard Worker #[derive(Args, Debug)] 57*c2e18aaaSAndroid Build Coastguard Worker pub struct GlobalOptions { 58*c2e18aaaSAndroid Build Coastguard Worker // TODO(rbraunstein): Revisit all the command name descriptions. 59*c2e18aaaSAndroid Build Coastguard Worker // TODO(rbraunstein): Add system_other to the default list, but deal gracefully 60*c2e18aaaSAndroid Build Coastguard Worker // with it not being on the device. 61*c2e18aaaSAndroid Build Coastguard Worker /// Partitions in the product tree to sync. Repeat arg or comma-separate. 62*c2e18aaaSAndroid Build Coastguard Worker /// 63*c2e18aaaSAndroid Build Coastguard Worker /// By default this includes: "system", "system_ext", "odm", "product" 64*c2e18aaaSAndroid Build Coastguard Worker /// 65*c2e18aaaSAndroid Build Coastguard Worker /// If a partition is explicitly passed in but that does not exist in the 66*c2e18aaaSAndroid Build Coastguard Worker /// tracked files then adevice will error. 67*c2e18aaaSAndroid Build Coastguard Worker #[clap(long, short, global = true, value_delimiter = ',')] 68*c2e18aaaSAndroid Build Coastguard Worker pub partitions: Option<Vec<String>>, 69*c2e18aaaSAndroid Build Coastguard Worker // TODO(rbraunstein): Validate relative, not absolute paths. 70*c2e18aaaSAndroid Build Coastguard Worker /// If unset defaults to ANDROID_PRODUCT_OUT env variable. 71*c2e18aaaSAndroid Build Coastguard Worker #[clap(long = "product_out", global = true)] 72*c2e18aaaSAndroid Build Coastguard Worker pub product_out: Option<String>, 73*c2e18aaaSAndroid Build Coastguard Worker /// Do not make any modification if more than this many are needed 74*c2e18aaaSAndroid Build Coastguard Worker #[clap(long, short, default_value_t = 400, global = true)] 75*c2e18aaaSAndroid Build Coastguard Worker pub max_allowed_changes: usize, 76*c2e18aaaSAndroid Build Coastguard Worker /// If passed, use the device, otherwise use the only connected device or ANDROID_SERIAL env value. 77*c2e18aaaSAndroid Build Coastguard Worker #[clap(long, short, global = true)] 78*c2e18aaaSAndroid Build Coastguard Worker pub serial: Option<String>, 79*c2e18aaaSAndroid Build Coastguard Worker /// Override the type of restart that happens after an update. 80*c2e18aaaSAndroid Build Coastguard Worker #[clap(long = "restart", short, global = true, value_enum, default_value_t=RestartChoice::Auto)] 81*c2e18aaaSAndroid Build Coastguard Worker pub restart_choice: RestartChoice, 82*c2e18aaaSAndroid Build Coastguard Worker /// Path to config file. Uses $HOME/.config/asuite/adevice-tracking.json if unset. 83*c2e18aaaSAndroid Build Coastguard Worker #[clap(long = "config", global = true)] 84*c2e18aaaSAndroid Build Coastguard Worker pub config_path: Option<String>, 85*c2e18aaaSAndroid Build Coastguard Worker #[clap(long = "force", global = true, alias = "force", alias = "force")] 86*c2e18aaaSAndroid Build Coastguard Worker // Force device update even if unbuilt modules are detected. 87*c2e18aaaSAndroid Build Coastguard Worker pub force: bool, 88*c2e18aaaSAndroid Build Coastguard Worker // Don't wait for device to become available after restarting it. 89*c2e18aaaSAndroid Build Coastguard Worker #[clap(long = "nowait", global = true, alias = "no_wait", alias = "no-wait")] 90*c2e18aaaSAndroid Build Coastguard Worker pub nowait: bool, 91*c2e18aaaSAndroid Build Coastguard Worker } 92*c2e18aaaSAndroid Build Coastguard Worker 93*c2e18aaaSAndroid Build Coastguard Worker #[derive(clap::ValueEnum, Clone, Debug)] 94*c2e18aaaSAndroid Build Coastguard Worker pub enum Verbosity { 95*c2e18aaaSAndroid Build Coastguard Worker /// Only show minimal information. 96*c2e18aaaSAndroid Build Coastguard Worker None, 97*c2e18aaaSAndroid Build Coastguard Worker /// Show all adb operations. 98*c2e18aaaSAndroid Build Coastguard Worker Details, 99*c2e18aaaSAndroid Build Coastguard Worker /// For debugging internals of tool and timings. 100*c2e18aaaSAndroid Build Coastguard Worker Debug, 101*c2e18aaaSAndroid Build Coastguard Worker } 102*c2e18aaaSAndroid Build Coastguard Worker 103*c2e18aaaSAndroid Build Coastguard Worker /// Allows you to choose how to reboot or to not reboot. 104*c2e18aaaSAndroid Build Coastguard Worker #[derive(clap::ValueEnum, Clone, Debug)] 105*c2e18aaaSAndroid Build Coastguard Worker pub enum RestartChoice { 106*c2e18aaaSAndroid Build Coastguard Worker /// Let the system choose the restart based on the files changed. 107*c2e18aaaSAndroid Build Coastguard Worker Auto, 108*c2e18aaaSAndroid Build Coastguard Worker /// Don't restart. 109*c2e18aaaSAndroid Build Coastguard Worker None, 110*c2e18aaaSAndroid Build Coastguard Worker /// Always do a full system reboot after updates. 111*c2e18aaaSAndroid Build Coastguard Worker Reboot, 112*c2e18aaaSAndroid Build Coastguard Worker /// Always do a framework restart restart after updates. 113*c2e18aaaSAndroid Build Coastguard Worker Restart, 114*c2e18aaaSAndroid Build Coastguard Worker } 115*c2e18aaaSAndroid Build Coastguard Worker 116*c2e18aaaSAndroid Build Coastguard Worker #[derive(Clone, Debug, PartialEq)] 117*c2e18aaaSAndroid Build Coastguard Worker pub enum Wait { 118*c2e18aaaSAndroid Build Coastguard Worker Yes, 119*c2e18aaaSAndroid Build Coastguard Worker No, 120*c2e18aaaSAndroid Build Coastguard Worker } 121*c2e18aaaSAndroid Build Coastguard Worker 122*c2e18aaaSAndroid Build Coastguard Worker impl From<Wait> for bool { from(w: Wait) -> bool123*c2e18aaaSAndroid Build Coastguard Worker fn from(w: Wait) -> bool { 124*c2e18aaaSAndroid Build Coastguard Worker match w { 125*c2e18aaaSAndroid Build Coastguard Worker Wait::Yes => true, 126*c2e18aaaSAndroid Build Coastguard Worker Wait::No => false, 127*c2e18aaaSAndroid Build Coastguard Worker } 128*c2e18aaaSAndroid Build Coastguard Worker } 129*c2e18aaaSAndroid Build Coastguard Worker } 130*c2e18aaaSAndroid Build Coastguard Worker 131*c2e18aaaSAndroid Build Coastguard Worker impl Cli { 132*c2e18aaaSAndroid Build Coastguard Worker /// Decide if the options indicate that we should wait for the device. 133*c2e18aaaSAndroid Build Coastguard Worker /// Exists in case the cli options get more complicated like --wait=false should_wait(&self) -> Wait134*c2e18aaaSAndroid Build Coastguard Worker pub fn should_wait(&self) -> Wait { 135*c2e18aaaSAndroid Build Coastguard Worker match self.global_options.nowait { 136*c2e18aaaSAndroid Build Coastguard Worker true => Wait::No, 137*c2e18aaaSAndroid Build Coastguard Worker false => Wait::Yes, 138*c2e18aaaSAndroid Build Coastguard Worker } 139*c2e18aaaSAndroid Build Coastguard Worker } 140*c2e18aaaSAndroid Build Coastguard Worker } 141*c2e18aaaSAndroid Build Coastguard Worker 142*c2e18aaaSAndroid Build Coastguard Worker #[cfg(test)] 143*c2e18aaaSAndroid Build Coastguard Worker mod tests { 144*c2e18aaaSAndroid Build Coastguard Worker use crate::cli::Wait; 145*c2e18aaaSAndroid Build Coastguard Worker 146*c2e18aaaSAndroid Build Coastguard Worker use super::Cli; 147*c2e18aaaSAndroid Build Coastguard Worker use clap::Parser; 148*c2e18aaaSAndroid Build Coastguard Worker 149*c2e18aaaSAndroid Build Coastguard Worker #[test] force_default_false()150*c2e18aaaSAndroid Build Coastguard Worker fn force_default_false() { 151*c2e18aaaSAndroid Build Coastguard Worker let cli = Cli::parse_from(["fake_prog", "update"]); 152*c2e18aaaSAndroid Build Coastguard Worker assert!(!cli.global_options.force); 153*c2e18aaaSAndroid Build Coastguard Worker } 154*c2e18aaaSAndroid Build Coastguard Worker 155*c2e18aaaSAndroid Build Coastguard Worker #[test] force_works()156*c2e18aaaSAndroid Build Coastguard Worker fn force_works() { 157*c2e18aaaSAndroid Build Coastguard Worker let cli = Cli::parse_from(["fake_prog", "update", "--force"]); 158*c2e18aaaSAndroid Build Coastguard Worker assert!(cli.global_options.force); 159*c2e18aaaSAndroid Build Coastguard Worker } 160*c2e18aaaSAndroid Build Coastguard Worker 161*c2e18aaaSAndroid Build Coastguard Worker #[test] nowait_works()162*c2e18aaaSAndroid Build Coastguard Worker fn nowait_works() { 163*c2e18aaaSAndroid Build Coastguard Worker let cli = Cli::parse_from(["fake_prog", "update", "--nowait"]); 164*c2e18aaaSAndroid Build Coastguard Worker assert!(cli.global_options.nowait); 165*c2e18aaaSAndroid Build Coastguard Worker } 166*c2e18aaaSAndroid Build Coastguard Worker 167*c2e18aaaSAndroid Build Coastguard Worker #[test] no_wait_alias_works()168*c2e18aaaSAndroid Build Coastguard Worker fn no_wait_alias_works() { 169*c2e18aaaSAndroid Build Coastguard Worker let cli = Cli::parse_from(["fake_prog", "update", "--no_wait"]); 170*c2e18aaaSAndroid Build Coastguard Worker assert!(cli.global_options.nowait); 171*c2e18aaaSAndroid Build Coastguard Worker } 172*c2e18aaaSAndroid Build Coastguard Worker 173*c2e18aaaSAndroid Build Coastguard Worker #[test] unset_nowait_is_none()174*c2e18aaaSAndroid Build Coastguard Worker fn unset_nowait_is_none() { 175*c2e18aaaSAndroid Build Coastguard Worker let cli = Cli::parse_from(["fake_prog", "update"]); 176*c2e18aaaSAndroid Build Coastguard Worker assert!(!cli.global_options.nowait); 177*c2e18aaaSAndroid Build Coastguard Worker } 178*c2e18aaaSAndroid Build Coastguard Worker 179*c2e18aaaSAndroid Build Coastguard Worker #[test] it_should_wait()180*c2e18aaaSAndroid Build Coastguard Worker fn it_should_wait() { 181*c2e18aaaSAndroid Build Coastguard Worker let cli = Cli::parse_from(["fake_prog", "update"]); 182*c2e18aaaSAndroid Build Coastguard Worker assert_eq!(Wait::Yes, cli.should_wait()); 183*c2e18aaaSAndroid Build Coastguard Worker let should_wait: bool = cli.should_wait().into(); 184*c2e18aaaSAndroid Build Coastguard Worker assert!(should_wait); 185*c2e18aaaSAndroid Build Coastguard Worker } 186*c2e18aaaSAndroid Build Coastguard Worker 187*c2e18aaaSAndroid Build Coastguard Worker #[test] it_should_not_wait()188*c2e18aaaSAndroid Build Coastguard Worker fn it_should_not_wait() { 189*c2e18aaaSAndroid Build Coastguard Worker let cli = Cli::parse_from(["fake_prog", "update", "--nowait"]); 190*c2e18aaaSAndroid Build Coastguard Worker assert_eq!(Wait::No, cli.should_wait()); 191*c2e18aaaSAndroid Build Coastguard Worker let should_wait: bool = cli.should_wait().into(); 192*c2e18aaaSAndroid Build Coastguard Worker assert!(!should_wait); 193*c2e18aaaSAndroid Build Coastguard Worker } 194*c2e18aaaSAndroid Build Coastguard Worker } 195