aflags: add initial enable and disable commands

Bug: 324436145
Test: adb shell aflags enable --help
Change-Id: I6b4af4bccbbc6000a9dcb78c3130f836b0f85bd0
diff --git a/tools/aconfig/aflags/src/main.rs b/tools/aconfig/aflags/src/main.rs
index 1e2a7a0..ef0195f 100644
--- a/tools/aconfig/aflags/src/main.rs
+++ b/tools/aconfig/aflags/src/main.rs
@@ -16,7 +16,7 @@
 
 //! `aflags` is a device binary to read and write aconfig flags.
 
-use anyhow::Result;
+use anyhow::{anyhow, Result};
 use clap::Parser;
 
 mod device_config_source;
@@ -63,8 +63,15 @@
     value_picked_from: ValuePickedFrom,
 }
 
+impl Flag {
+    fn qualified_name(&self) -> String {
+        format!("{}.{}", self.package, self.name)
+    }
+}
+
 trait FlagSource {
     fn list_flags() -> Result<Vec<Flag>>;
+    fn override_flag(namespace: &str, qualified_name: &str, value: &str) -> Result<()>;
 }
 
 const ABOUT_TEXT: &str = "Tool for reading and writing flags.
@@ -94,6 +101,18 @@
 enum Command {
     /// List all aconfig flags on this device.
     List,
+
+    /// Enable an aconfig flag on this device, on the next boot.
+    Enable {
+        /// <package>.<flag_name>
+        qualified_name: String,
+    },
+
+    /// Disable an aconfig flag on this device, on the next boot.
+    Disable {
+        /// <package>.<flag_name>
+        qualified_name: String,
+    },
 }
 
 struct PaddingInfo {
@@ -125,6 +144,23 @@
     format!("{pkg:p0$}{name:p1$}{val:p2$}{value_picked_from:p3$}{perm:p4$}{container}\n")
 }
 
+fn set_flag(qualified_name: &str, value: &str) -> Result<()> {
+    let flags_binding = DeviceConfigSource::list_flags()?;
+    let flag = flags_binding.iter().find(|f| f.qualified_name() == qualified_name).ok_or(
+        anyhow!("no aconfig flag '{qualified_name}'. Does the flag have an .aconfig definition?"),
+    )?;
+
+    if let FlagPermission::ReadOnly = flag.permission {
+        return Err(anyhow!(
+            "could not write flag '{qualified_name}', it is read-only for the current release configuration.",
+        ));
+    }
+
+    DeviceConfigSource::override_flag(&flag.namespace, qualified_name, value)?;
+
+    Ok(())
+}
+
 fn list() -> Result<String> {
     let flags = DeviceConfigSource::list_flags()?;
     let padding_info = PaddingInfo {
@@ -154,10 +190,13 @@
 fn main() {
     let cli = Cli::parse();
     let output = match cli.command {
-        Command::List => list(),
+        Command::List => list().map(Some),
+        Command::Enable { qualified_name } => set_flag(&qualified_name, "true").map(|_| None),
+        Command::Disable { qualified_name } => set_flag(&qualified_name, "false").map(|_| None),
     };
     match output {
-        Ok(text) => println!("{text}"),
-        Err(msg) => println!("Error: {}", msg),
+        Ok(Some(text)) => println!("{text}"),
+        Ok(None) => (),
+        Err(message) => println!("Error: {message}"),
     }
 }