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