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    RequestType, ResponseType, UsagePublisher, UsageResponsePublisher,
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 =
30    (UsageResponsePublisher<FactoryResetInfo>, FactoryResetWatchResponder);
31type HangingGetFn = fn(&FactoryResetInfo, SubscriberObject) -> bool;
32pub(crate) type HangingGet = server::HangingGet<FactoryResetInfo, SubscriberObject, HangingGetFn>;
33pub(crate) type Publisher = server::Publisher<FactoryResetInfo, SubscriberObject, HangingGetFn>;
34pub(crate) type Subscriber = server::Subscriber<FactoryResetInfo, SubscriberObject, HangingGetFn>;
35
36pub struct FactoryResetFidlHandler {
37    hanging_get: HangingGet,
38    controller_tx: UnboundedSender<Request>,
39    usage_publisher: UsagePublisher<FactoryResetInfo>,
40}
41
42impl FactoryResetFidlHandler {
43    pub(crate) fn new(
44        factory_reset_controller: &mut FactoryResetController,
45        usage_publisher: UsagePublisher<FactoryResetInfo>,
46        initial_value: FactoryResetInfo,
47    ) -> (Self, UnboundedReceiver<Request>) {
48        let hanging_get = HangingGet::new(initial_value, Self::hanging_get);
49        factory_reset_controller.register_publisher(hanging_get.new_publisher());
50        let (controller_tx, controller_rx) = mpsc::unbounded();
51        (Self { hanging_get, controller_tx, usage_publisher }, controller_rx)
52    }
53
54    fn hanging_get(
55        info: &FactoryResetInfo,
56        (usage_responder, responder): SubscriberObject,
57    ) -> bool {
58        usage_responder.respond(format!("{info:?}"), ResponseType::OkSome);
59        if let Err(e) = responder.send(&FactoryResetSettings::from(*info)) {
60            log::warn!("Failed to respond to watch request: {e:?}");
61            return false;
62        }
63        true
64    }
65
66    pub fn handle_stream(&mut self, mut stream: FactoryResetRequestStream) {
67        let request_handler = RequestHandler {
68            subscriber: self.hanging_get.new_subscriber(),
69            controller_tx: self.controller_tx.clone(),
70            usage_publisher: self.usage_publisher.clone(),
71        };
72        fasync::Task::local(async move {
73            while let Some(Ok(request)) = stream.next().await {
74                request_handler.handle_request(request).await;
75            }
76        })
77        .detach();
78    }
79}
80
81#[derive(Debug)]
82enum HandlerError {
83    AlreadySubscribed,
84    MissingArg,
85    ControllerStopped,
86    Controller(FactoryResetError),
87}
88
89impl From<&HandlerError> for ResponseType {
90    fn from(error: &HandlerError) -> Self {
91        match error {
92            HandlerError::AlreadySubscribed => ResponseType::AlreadySubscribed,
93            HandlerError::MissingArg => ResponseType::InvalidArgument,
94            HandlerError::ControllerStopped => ResponseType::UnexpectedError,
95            HandlerError::Controller(e) => ResponseType::from(e),
96        }
97    }
98}
99
100struct RequestHandler {
101    subscriber: Subscriber,
102    controller_tx: UnboundedSender<Request>,
103    usage_publisher: UsagePublisher<FactoryResetInfo>,
104}
105
106impl RequestHandler {
107    async fn handle_request(&self, request: FactoryResetRequest) {
108        match request {
109            FactoryResetRequest::Watch { responder } => {
110                let usage_res = self.usage_publisher.request("Watch".to_string(), RequestType::Get);
111                if let Err((usage_res, responder)) =
112                    self.subscriber.register2((usage_res, responder))
113                {
114                    let e = HandlerError::AlreadySubscribed;
115                    usage_res.respond(format!("Err({e:?})"), ResponseType::from(&e));
116                    drop(responder);
117                }
118            }
119            FactoryResetRequest::Set { settings, responder } => {
120                let usage_res = self
121                    .usage_publisher
122                    .request(format!("Set{{settings:{settings:?}}}"), RequestType::Set);
123                if let Err(e) = self.set(settings).await {
124                    usage_res.respond(format!("Err({e:?}"), ResponseType::from(&e));
125                    let _ = responder.send(Err(SettingsError::Failed));
126                } else {
127                    usage_res.respond("Ok(())".to_string(), ResponseType::OkNone);
128                    let _ = responder.send(Ok(()));
129                }
130            }
131        }
132    }
133
134    async fn set(&self, settings: FactoryResetSettings) -> Result<(), HandlerError> {
135        let (set_tx, set_rx) = oneshot::channel();
136        let local_reset_allowed =
137            settings.is_local_reset_allowed.ok_or(HandlerError::MissingArg)?;
138        self.controller_tx
139            .unbounded_send(Request::Set(FactoryResetInfo::new(local_reset_allowed), set_tx))
140            .map_err(|_| HandlerError::ControllerStopped)?;
141        set_rx
142            .await
143            .map_err(|_| HandlerError::ControllerStopped)
144            .and_then(|res| res.map_err(HandlerError::Controller))
145    }
146}