recovery_util/ota/
action.rs1use crate::crash::CrashReporter;
6use crate::ota::actions::factory_reset::FactoryResetAction;
7use crate::ota::actions::finalize_reinstall::FinalizeReinstallAction;
8use crate::ota::actions::get_wifi_networks::GetWifiNetworksAction;
9use crate::ota::actions::ota_reinstall::OtaReinstallAction;
10use crate::ota::actions::reboot_device::RebootAction;
11use crate::ota::actions::set_sharing_consent::SetSharingConsentAction;
12use crate::ota::actions::wifi_connect::WifiConnectAction;
13use crate::ota::controller::EventSender;
14use crate::ota::state_machine::{State, StateHandler};
15use fuchsia_async as fasync;
16use ota_lib::OtaManager;
17use std::rc::Rc;
18use std::sync::Arc;
19
20pub struct Action {
24 event_sender: EventSender,
25 ota_manager: Arc<dyn OtaManager>,
26 crash_reporter: Option<Rc<CrashReporter>>,
27}
28
29impl Action {
30 pub fn new(
31 event_sender: EventSender,
32 ota_manager: Arc<dyn OtaManager>,
33 crash_reporter: Option<Rc<CrashReporter>>,
34 ) -> Self {
35 Self { event_sender, ota_manager, crash_reporter }
36 }
37}
38
39impl StateHandler for Action {
40 fn handle_state(&mut self, state: State) {
41 let event_sender = Box::new(self.event_sender.clone());
42 match state {
43 State::GetWiFiNetworks => GetWifiNetworksAction::run(event_sender),
44 State::Connecting(network, password) => {
45 WifiConnectAction::run(event_sender, network, password, self.crash_reporter.clone())
46 }
47 State::Rebooting(delay) => RebootAction::run(event_sender, delay),
48 State::ReinstallConfirm { desired: user_data_sharing_consent, reported } => {
49 SetSharingConsentAction::run(event_sender, user_data_sharing_consent, reported)
50 }
51 State::ExecuteReinstall => {
52 OtaReinstallAction::run(event_sender, self.ota_manager.clone())
53 }
54 State::ReinstallRunning { status: Some(status), .. } => {
55 let ota_manager = self.ota_manager.clone();
57 fasync::Task::local(async move {
58 ota_manager.complete_ota(status).await;
59 })
60 .detach();
61 }
62 State::FinalizeReinstall(status) => FinalizeReinstallAction::run(event_sender, status),
63 State::FactoryReset => FactoryResetAction::run(event_sender),
64 _ => {}
66 };
67 }
68}
69
70#[cfg(test)]
71mod test {
72 use super::{Action, StateHandler};
73 use crate::ota::controller::EventSender;
74 use crate::ota::state_machine::{Event, OtaStatus, State};
75 use anyhow::Error;
76 use async_trait::async_trait;
77 use fuchsia_sync::Mutex;
78 use futures::channel::{mpsc, oneshot};
79 use ota_lib::OtaManager;
80 use std::sync::Arc;
81
82 struct FakeOtaManager {
83 sender: Mutex<Option<oneshot::Sender<OtaStatus>>>,
84 }
85
86 impl FakeOtaManager {
87 pub fn new() -> (Arc<Self>, oneshot::Receiver<OtaStatus>) {
88 let (tx, rx) = oneshot::channel();
89 (Arc::new(Self { sender: Mutex::new(Some(tx)) }), rx)
90 }
91 }
92
93 #[async_trait]
94 impl OtaManager for FakeOtaManager {
95 async fn start_and_wait_for_result(&self) -> Result<(), Error> {
96 Ok(())
97 }
98 async fn stop(&self) -> Result<(), Error> {
99 Ok(())
100 }
101 async fn complete_ota(&self, status: OtaStatus) {
102 self.sender.lock().take().expect("only one event expected").send(status).unwrap();
103 }
104 }
105
106 #[fuchsia::test]
107 async fn reinstall_progress_with_ota_status_completes_ota() {
108 let (sender, _receiver) = mpsc::channel::<Event>(10);
109 let event_sender = EventSender::new(sender);
110
111 for status in [OtaStatus::Succeeded, OtaStatus::Failed, OtaStatus::Cancelled] {
113 let (ota_manager, on_complete_ota) = FakeOtaManager::new();
114 let mut action = Action::new(event_sender.clone(), ota_manager, None);
115
116 action.handle_state(State::ReinstallRunning {
117 status: Some(status.clone()),
118 progress: 100,
119 });
120 assert_eq!(status, on_complete_ota.await.unwrap());
121 }
122 }
123}