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 HangingGetObserver, RequestType, ResponseType, UsagePublisher,
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 = HangingGetObserver<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, observer: SubscriberObject) -> bool {
51 let (usage_responder, responder) = observer.into_parts();
52 usage_responder.respond(format!("{info:?}"), ResponseType::OkSome);
53 if let Err(e) = responder.send(&NightModeSettings::from(*info)) {
54 log::warn!("Failed to respond to watch request: {e:?}");
55 return false;
56 }
57 true
58 }
59
60 pub fn handle_stream(&mut self, mut stream: NightModeRequestStream) {
61 let request_handler = RequestHandler {
62 subscriber: self.hanging_get.new_subscriber(),
63 controller_tx: self.controller_tx.clone(),
64 usage_publisher: self.usage_publisher.clone(),
65 };
66 fasync::Task::local(async move {
67 while let Some(Ok(request)) = stream.next().await {
68 request_handler.handle_request(request).await;
69 }
70 })
71 .detach();
72 }
73}
74
75#[derive(Debug)]
76enum HandlerError {
77 AlreadySubscribed,
78 ControllerStopped,
79 Controller(NightModeError),
80}
81
82impl From<&HandlerError> for ResponseType {
83 fn from(error: &HandlerError) -> Self {
84 match error {
85 HandlerError::AlreadySubscribed => ResponseType::AlreadySubscribed,
86 HandlerError::ControllerStopped => ResponseType::UnexpectedError,
87 HandlerError::Controller(e) => ResponseType::from(e),
88 }
89 }
90}
91
92struct RequestHandler {
93 subscriber: Subscriber,
94 controller_tx: UnboundedSender<Request>,
95 usage_publisher: UsagePublisher<NightModeInfo>,
96}
97
98impl RequestHandler {
99 async fn handle_request(&self, request: NightModeRequest) {
100 match request {
101 NightModeRequest::Watch { responder } => {
102 let usage_res = self.usage_publisher.request("Watch".to_string(), RequestType::Get);
103 let observer = HangingGetObserver::new(usage_res, responder);
104 if let Err(observer) = self.subscriber.register2(observer) {
105 let e = HandlerError::AlreadySubscribed;
106 let (usage_res, responder) = observer.into_parts();
107 usage_res.respond(format!("Err({e:?})"), ResponseType::from(&e));
108 drop(responder);
109 }
110 }
111 NightModeRequest::Set { settings, responder } => {
112 let usage_res = self
113 .usage_publisher
114 .request(format!("Set{{settings:{settings:?}}}"), RequestType::Set);
115 if let Err(e) = self.set(settings).await {
116 usage_res.respond(format!("Err({e:?}"), ResponseType::from(&e));
117 let _ = responder.send(Err(SettingsError::Failed));
118 } else {
119 usage_res.respond("Ok(())".to_string(), ResponseType::OkNone);
120 let _ = responder.send(Ok(()));
121 }
122 }
123 }
124 }
125
126 async fn set(&self, settings: NightModeSettings) -> Result<(), HandlerError> {
127 let (set_tx, set_rx) = oneshot::channel();
128 self.controller_tx
129 .unbounded_send(Request::Set(settings.night_mode_enabled, set_tx))
130 .map_err(|_| HandlerError::ControllerStopped)?;
131 set_rx
132 .await
133 .map_err(|_| HandlerError::ControllerStopped)
134 .and_then(|res| res.map_err(HandlerError::Controller))
135 }
136}