settings_factory_reset/
factory_reset_fidl_handler.rs1use 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}