Skip to main content

settings_factory_reset/
factory_reset_fidl_handler.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use super::factory_reset_controller::{FactoryResetController, FactoryResetError, Request};
6use super::types::FactoryResetInfo;
7use async_utils::hanging_get::server;
8use fidl_fuchsia_settings::{
9    Error as SettingsError, FactoryResetRequest, FactoryResetRequestStream, FactoryResetSettings,
10    FactoryResetWatchResponder,
11};
12use fuchsia_async as fasync;
13use futures::StreamExt;
14use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
15use futures::channel::oneshot;
16use settings_common::inspect::event::{
17    HangingGetObserver, RequestType, ResponseType, UsagePublisher,
18};
19
20impl From<FactoryResetInfo> for FactoryResetSettings {
21    fn from(info: FactoryResetInfo) -> Self {
22        FactoryResetSettings {
23            is_local_reset_allowed: Some(info.is_local_reset_allowed),
24            ..Default::default()
25        }
26    }
27}
28
29pub(crate) type SubscriberObject = HangingGetObserver<FactoryResetInfo, FactoryResetWatchResponder>;
30type HangingGetFn = fn(&FactoryResetInfo, SubscriberObject) -> bool;
31pub(crate) type HangingGet = server::HangingGet<FactoryResetInfo, SubscriberObject, HangingGetFn>;
32pub(crate) type Publisher = server::Publisher<FactoryResetInfo, SubscriberObject, HangingGetFn>;
33pub(crate) type Subscriber = server::Subscriber<FactoryResetInfo, SubscriberObject, HangingGetFn>;
34
35pub struct FactoryResetFidlHandler {
36    hanging_get: HangingGet,
37    controller_tx: UnboundedSender<Request>,
38    usage_publisher: UsagePublisher<FactoryResetInfo>,
39}
40
41impl FactoryResetFidlHandler {
42    pub(crate) fn new(
43        factory_reset_controller: &mut FactoryResetController,
44        usage_publisher: UsagePublisher<FactoryResetInfo>,
45        initial_value: FactoryResetInfo,
46    ) -> (Self, UnboundedReceiver<Request>) {
47        let hanging_get = HangingGet::new(initial_value, Self::hanging_get);
48        factory_reset_controller.register_publisher(hanging_get.new_publisher());
49        let (controller_tx, controller_rx) = mpsc::unbounded();
50        (Self { hanging_get, controller_tx, usage_publisher }, controller_rx)
51    }
52
53    fn hanging_get(info: &FactoryResetInfo, observer: SubscriberObject) -> bool {
54        let (usage_responder, responder) = observer.into_parts();
55        usage_responder.respond(format!("{info:?}"), ResponseType::OkSome);
56        if let Err(e) = responder.send(&FactoryResetSettings::from(*info)) {
57            log::warn!("Failed to respond to watch request: {e:?}");
58            return false;
59        }
60        true
61    }
62
63    pub fn handle_stream(&mut self, mut stream: FactoryResetRequestStream) {
64        let request_handler = RequestHandler {
65            subscriber: self.hanging_get.new_subscriber(),
66            controller_tx: self.controller_tx.clone(),
67            usage_publisher: self.usage_publisher.clone(),
68        };
69        fasync::Task::local(async move {
70            while let Some(Ok(request)) = stream.next().await {
71                request_handler.handle_request(request).await;
72            }
73        })
74        .detach();
75    }
76}
77
78#[derive(Debug)]
79enum HandlerError {
80    AlreadySubscribed,
81    MissingArg,
82    ControllerStopped,
83    Controller(FactoryResetError),
84}
85
86impl From<&HandlerError> for ResponseType {
87    fn from(error: &HandlerError) -> Self {
88        match error {
89            HandlerError::AlreadySubscribed => ResponseType::AlreadySubscribed,
90            HandlerError::MissingArg => ResponseType::InvalidArgument,
91            HandlerError::ControllerStopped => ResponseType::UnexpectedError,
92            HandlerError::Controller(e) => ResponseType::from(e),
93        }
94    }
95}
96
97struct RequestHandler {
98    subscriber: Subscriber,
99    controller_tx: UnboundedSender<Request>,
100    usage_publisher: UsagePublisher<FactoryResetInfo>,
101}
102
103impl RequestHandler {
104    async fn handle_request(&self, request: FactoryResetRequest) {
105        match request {
106            FactoryResetRequest::Watch { responder } => {
107                let usage_res = self.usage_publisher.request("Watch".to_string(), RequestType::Get);
108                let observer = HangingGetObserver::new(usage_res, responder);
109                if let Err(observer) = self.subscriber.register2(observer) {
110                    let e = HandlerError::AlreadySubscribed;
111                    let (usage_res, responder) = observer.into_parts();
112                    usage_res.respond(format!("Err({e:?})"), ResponseType::from(&e));
113                    drop(responder);
114                }
115            }
116            FactoryResetRequest::Set { settings, responder } => {
117                let usage_res = self
118                    .usage_publisher
119                    .request(format!("Set{{settings:{settings:?}}}"), RequestType::Set);
120                if let Err(e) = self.set(settings).await {
121                    usage_res.respond(format!("Err({e:?}"), ResponseType::from(&e));
122                    let _ = responder.send(Err(SettingsError::Failed));
123                } else {
124                    usage_res.respond("Ok(())".to_string(), ResponseType::OkNone);
125                    let _ = responder.send(Ok(()));
126                }
127            }
128        }
129    }
130
131    async fn set(&self, settings: FactoryResetSettings) -> Result<(), HandlerError> {
132        let (set_tx, set_rx) = oneshot::channel();
133        let local_reset_allowed =
134            settings.is_local_reset_allowed.ok_or(HandlerError::MissingArg)?;
135        self.controller_tx
136            .unbounded_send(Request::Set(FactoryResetInfo::new(local_reset_allowed), set_tx))
137            .map_err(|_| HandlerError::ControllerStopped)?;
138        set_rx
139            .await
140            .map_err(|_| HandlerError::ControllerStopped)
141            .and_then(|res| res.map_err(HandlerError::Controller))
142    }
143}