[SetUI][Agent] Remove individual stage contexts.

This changelist removes the initialization stage context
and moves the available components to the overall
agent context.

The test_available_components test is no longer
relevant without the components in stage contexts.
Pipelining available components is still covered by
the restore agent test.

Fixed: 52428
Test: fx test -o setui_service_tests
Change-Id: I5158b0f7981ec25bab95fe4e233bebd23218d725
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/402559
Commit-Queue: Bryce Lee <brycelee@google.com>
Reviewed-by: Chip Fukuhara <cfukuhara@google.com>
Testability-Review: Chip Fukuhara <cfukuhara@google.com>
diff --git a/garnet/bin/setui/src/agent/authority_impl.rs b/garnet/bin/setui/src/agent/authority_impl.rs
index 1960dfd..f5cb21e 100644
--- a/garnet/bin/setui/src/agent/authority_impl.rs
+++ b/garnet/bin/setui/src/agent/authority_impl.rs
@@ -9,8 +9,10 @@
 use crate::internal::switchboard;
 use crate::message::base::{Audience, MessengerType};
 use crate::service_context::ServiceContextHandle;
+use crate::switchboard::base::SettingType;
 use anyhow::{format_err, Error};
 use async_trait::async_trait;
+use std::collections::HashSet;
 
 /// AuthorityImpl is the default implementation of the Authority trait. It
 /// provides the ability to execute agents sequentially or simultaneously for a
@@ -26,6 +28,8 @@
     messenger: agent::message::Messenger,
     // Factory to generate event messengers
     event_factory: event::message::Factory,
+    // Available components
+    available_components: HashSet<SettingType>,
 }
 
 impl AuthorityImpl {
@@ -33,6 +37,7 @@
         messenger_factory: agent::message::Factory,
         switchboard_messenger_factory: switchboard::message::Factory,
         event_factory: event::message::Factory,
+        available_components: HashSet<SettingType>,
     ) -> Result<AuthorityImpl, Error> {
         let messenger_result = messenger_factory.create(MessengerType::Unbound).await;
 
@@ -47,6 +52,7 @@
             switchboard_messenger_factory,
             messenger: client,
             event_factory,
+            available_components,
         });
     }
 
@@ -128,6 +134,7 @@
                     blueprint.get_descriptor(),
                     self.switchboard_messenger_factory.clone(),
                     self.event_factory.clone(),
+                    self.available_components.clone(),
                 )
                 .await,
             )
diff --git a/garnet/bin/setui/src/agent/base.rs b/garnet/bin/setui/src/agent/base.rs
index d7883c3..bf55667 100644
--- a/garnet/bin/setui/src/agent/base.rs
+++ b/garnet/bin/setui/src/agent/base.rs
@@ -37,11 +37,11 @@
     Component(&'static str),
 }
 
-/// TODO(fxb/52428): Move lifecycle stage context contents here.
 pub struct Context {
     pub receptor: Receptor,
     publisher: event::Publisher,
     switchboard_messenger_factory: switchboard::message::Factory,
+    pub available_components: HashSet<SettingType>,
 }
 
 impl Context {
@@ -50,12 +50,14 @@
         descriptor: Descriptor,
         switchboard_messenger_factory: switchboard::message::Factory,
         event_factory: event::message::Factory,
+        available_components: HashSet<SettingType>,
     ) -> Self {
         Self {
             receptor,
             publisher: event::Publisher::create(&event_factory, event::Address::Agent(descriptor))
                 .await,
             switchboard_messenger_factory,
+            available_components,
         }
     }
 
@@ -79,22 +81,12 @@
 /// The scope of an agent's life. Initialization components should
 /// only run at the beginning of the service. Service components follow
 /// initialization and run for the duration of the service.
-#[derive(Clone, Debug)]
+#[derive(Clone, Copy, Debug, PartialEq)]
 pub enum Lifespan {
-    Initialization(InitializationContext),
+    Initialization,
     Service,
 }
 
-#[derive(Clone, Debug)]
-pub struct InitializationContext {
-    pub available_components: HashSet<SettingType>,
-}
-
-impl InitializationContext {
-    pub fn new(components: HashSet<SettingType>) -> Self {
-        Self { available_components: components }
-    }
-}
 /// Struct of information passed to the agent during each invocation.
 #[derive(Clone, Debug)]
 pub struct Invocation {
diff --git a/garnet/bin/setui/src/agent/earcons/agent.rs b/garnet/bin/setui/src/agent/earcons/agent.rs
index 141f998..2f423eb 100644
--- a/garnet/bin/setui/src/agent/earcons/agent.rs
+++ b/garnet/bin/setui/src/agent/earcons/agent.rs
@@ -61,34 +61,34 @@
 
     async fn handle(&mut self, invocation: Invocation) -> InvocationResult {
         // Only process service lifespans.
-        if let Lifespan::Initialization(_context) = invocation.lifespan {
-            let common_earcons_params = CommonEarconsParams {
-                service_context: invocation.service_context,
-                sound_player_added_files: Arc::new(Mutex::new(HashSet::new())),
-                sound_player_connection: self.sound_player_connection.clone(),
-            };
-
-            if VolumeChangeHandler::create(
-                common_earcons_params.clone(),
-                self.switchboard_messenger.clone(),
-            )
-            .await
-            .is_err()
-            {
-                // For now, report back as an error to prevent issues on
-                // platforms that don't support the handler's dependencies.
-                fx_log_err!("Could not set up VolumeChangeHandler");
-            }
-
-            fasync::spawn(async move {
-                // Watch for bluetooth connections and play sounds on change.
-                let bluetooth_connection_active = Arc::new(AtomicBool::new(true));
-                watch_bluetooth_connections(common_earcons_params, bluetooth_connection_active);
-            });
-
-            return Ok(());
-        } else {
+        if Lifespan::Initialization != invocation.lifespan {
             return Err(AgentError::UnhandledLifespan);
         }
+
+        let common_earcons_params = CommonEarconsParams {
+            service_context: invocation.service_context,
+            sound_player_added_files: Arc::new(Mutex::new(HashSet::new())),
+            sound_player_connection: self.sound_player_connection.clone(),
+        };
+
+        if VolumeChangeHandler::create(
+            common_earcons_params.clone(),
+            self.switchboard_messenger.clone(),
+        )
+        .await
+        .is_err()
+        {
+            // For now, report back as an error to prevent issues on
+            // platforms that don't support the handler's dependencies.
+            fx_log_err!("Could not set up VolumeChangeHandler");
+        }
+
+        fasync::spawn(async move {
+            // Watch for bluetooth connections and play sounds on change.
+            let bluetooth_connection_active = Arc::new(AtomicBool::new(true));
+            watch_bluetooth_connections(common_earcons_params, bluetooth_connection_active);
+        });
+
+        return Ok(());
     }
 }
diff --git a/garnet/bin/setui/src/agent/restore_agent.rs b/garnet/bin/setui/src/agent/restore_agent.rs
index 4dbe46b..7e0f54e 100644
--- a/garnet/bin/setui/src/agent/restore_agent.rs
+++ b/garnet/bin/setui/src/agent/restore_agent.rs
@@ -10,10 +10,11 @@
 use crate::internal::event::{restore, Event, Publisher};
 use crate::internal::switchboard;
 use crate::message::base::{Audience, MessageEvent};
-use crate::switchboard::base::{SettingRequest, SwitchboardError};
+use crate::switchboard::base::{SettingRequest, SettingType, SwitchboardError};
 use fuchsia_async as fasync;
 use fuchsia_syslog::{fx_log_err, fx_log_info};
 use futures::StreamExt;
+use std::collections::HashSet;
 
 blueprint_definition!(
     crate::agent::base::Descriptor::Component("restore_agent"),
@@ -24,6 +25,7 @@
 pub struct RestoreAgent {
     switchboard_messenger: switchboard::message::Messenger,
     event_publisher: Publisher,
+    available_components: HashSet<SettingType>,
 }
 
 impl RestoreAgent {
@@ -40,6 +42,7 @@
         let mut agent = RestoreAgent {
             switchboard_messenger: messenger,
             event_publisher: context.get_publisher(),
+            available_components: context.available_components.clone(),
         };
 
         fasync::spawn(async move {
@@ -52,9 +55,9 @@
     }
 
     async fn handle(&mut self, invocation: Invocation) -> InvocationResult {
-        match invocation.lifespan.clone() {
-            Lifespan::Initialization(context) => {
-                for component in context.available_components {
+        match invocation.lifespan {
+            Lifespan::Initialization => {
+                for component in self.available_components.clone() {
                     let mut receptor = self
                         .switchboard_messenger
                         .message(
diff --git a/garnet/bin/setui/src/lib.rs b/garnet/bin/setui/src/lib.rs
index 3d13f05..5167ed7 100644
--- a/garnet/bin/setui/src/lib.rs
+++ b/garnet/bin/setui/src/lib.rs
@@ -9,9 +9,7 @@
     crate::accessibility::accessibility_controller::AccessibilityController,
     crate::account::account_controller::AccountController,
     crate::agent::authority_impl::AuthorityImpl,
-    crate::agent::base::{
-        Authority, BlueprintHandle as AgentBlueprintHandle, InitializationContext, Lifespan,
-    },
+    crate::agent::base::{Authority, BlueprintHandle as AgentBlueprintHandle, Lifespan},
     crate::audio::audio_controller::AudioController,
     crate::config::base::ControllerFlag,
     crate::device::device_controller::DeviceController,
@@ -446,6 +444,7 @@
         internal::agent::message::create_hub(),
         switchboard_messenger_factory.clone(),
         event_messenger_factory.clone(),
+        components.clone(),
     )
     .await?;
 
@@ -575,11 +574,7 @@
 
     // Execute initialization agents sequentially
     if agent_authority
-        .execute_lifespan(
-            Lifespan::Initialization(InitializationContext { available_components: components }),
-            service_context_handle.clone(),
-            true,
-        )
+        .execute_lifespan(Lifespan::Initialization, service_context_handle.clone(), true)
         .await
         .is_err()
     {
diff --git a/garnet/bin/setui/src/tests/agent_tests.rs b/garnet/bin/setui/src/tests/agent_tests.rs
index 1b3b521..538881e 100644
--- a/garnet/bin/setui/src/tests/agent_tests.rs
+++ b/garnet/bin/setui/src/tests/agent_tests.rs
@@ -5,8 +5,7 @@
 #[cfg(test)]
 use crate::agent::authority_impl::AuthorityImpl;
 use crate::agent::base::{
-    AgentError, Authority, BlueprintHandle, Context, InitializationContext, Invocation,
-    InvocationResult, Lifespan,
+    AgentError, Authority, BlueprintHandle, Context, Invocation, InvocationResult, Lifespan,
 };
 use crate::internal::agent;
 use crate::internal::event;
@@ -117,7 +116,7 @@
 
     async fn handle(&mut self, invocation: Invocation) -> InvocationResult {
         match invocation.lifespan.clone() {
-            Lifespan::Initialization(_) => {
+            Lifespan::Initialization => {
                 if self.lifespan_target != LifespanTarget::Initialization {
                     return Err(AgentError::UnhandledLifespan);
                 }
@@ -208,6 +207,7 @@
         agent::message::create_hub(),
         switchboard::message::create_hub(),
         event::message::create_hub(),
+        HashSet::new(),
     )
     .await
     .unwrap()
@@ -248,11 +248,7 @@
 
     // Ensure lifespan execution completes.
     assert!(authority
-        .execute_lifespan(
-            Lifespan::Initialization(InitializationContext::new(HashSet::new(),)),
-            service_context,
-            true,
-        )
+        .execute_lifespan(Lifespan::Initialization, service_context, true,)
         .await
         .is_ok());
 }
@@ -289,11 +285,7 @@
 
     // Execute lifespan non-sequentially.
     assert!(authority
-        .execute_lifespan(
-            Lifespan::Initialization(InitializationContext::new(HashSet::new(),)),
-            service_context,
-            false,
-        )
+        .execute_lifespan(Lifespan::Initialization, service_context, false,)
         .await
         .is_ok());
 }
@@ -339,70 +331,13 @@
 
     // Execute lifespan sequentially. Should fail since agent 2 returns an error.
     assert!(authority
-        .execute_lifespan(
-            Lifespan::Initialization(InitializationContext::new(HashSet::new(),)),
-            service_context,
-            true,
-        )
+        .execute_lifespan(Lifespan::Initialization, service_context, true,)
         .await
         .is_err());
 
     assert!(agent2_lock.lock().await.last_invocation().is_none());
 }
 
-/// Checks to see if available components are passed properly from
-/// execute_lifespan.
-#[fuchsia_async::run_until_stalled(test)]
-async fn test_available_components() {
-    let (tx, mut rx) = futures::channel::mpsc::unbounded::<(u32, Invocation, AckSender)>();
-    let mut authority = create_authority().await;
-    let service_context = ServiceContext::create(None);
-    let mut rng = rand::thread_rng();
-
-    let agent_id = TestAgent::create_and_register(
-        rng.gen(),
-        LifespanTarget::Initialization,
-        &mut authority,
-        tx.clone(),
-    )
-    .await
-    .unwrap()
-    .lock()
-    .await
-    .id();
-
-    let mut available_components = HashSet::new();
-
-    available_components.insert(SettingType::Display);
-    available_components.insert(SettingType::Intl);
-
-    let available_components_clone = available_components.clone();
-    fasync::spawn(async move {
-        // Ensure the first agent received an invocation and verify components match
-        if let Some((id, invocation, tx)) = rx.next().await {
-            assert_eq!(agent_id, id);
-            if let Lifespan::Initialization(context) = invocation.lifespan.clone() {
-                assert_eq!(available_components_clone, context.available_components);
-                assert!(tx.send(Ok(())).is_ok());
-            } else {
-                panic!("should have encountered initialization lifespan");
-            }
-        } else {
-            panic!("did not receive expected response from agent");
-        }
-    });
-
-    // Execute lifespan sequentially
-    assert!(authority
-        .execute_lifespan(
-            Lifespan::Initialization(InitializationContext::new(available_components.clone(),)),
-            service_context,
-            true,
-        )
-        .await
-        .is_ok());
-}
-
 async fn create_agents(
     count: u32,
     lifespan_target: LifespanTarget,