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