1use crate::display_controller::{DisplayController, DisplayError, Request};
6use crate::types::{DisplayInfo, LowLightMode, SetDisplayInfo, Theme, ThemeMode, ThemeType};
7use anyhow::{Error, anyhow};
8use async_utils::hanging_get::server;
9use fidl_fuchsia_settings::{
10 DisplayRequest, DisplayRequestStream, DisplaySettings, DisplayWatchResponder,
11 Error as SettingsError, LowLightMode as FidlLowLightMode, Theme as FidlTheme,
12 ThemeMode as FidlThemeMode, ThemeType as FidlThemeType,
13};
14use fuchsia_async as fasync;
15use futures::StreamExt;
16use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};
17use futures::channel::oneshot;
18use settings_common::inspect::event::{
19 HangingGetObserver, RequestType, ResponseType, UsagePublisher,
20};
21
22impl From<FidlThemeMode> for ThemeMode {
23 fn from(fidl: FidlThemeMode) -> Self {
24 ThemeMode::from_bits(FidlThemeMode::bits(&fidl))
25 .expect("failed to convert FidlThemeMode to ThemeMode")
26 }
27}
28
29impl From<ThemeMode> for FidlThemeMode {
30 fn from(fidl: ThemeMode) -> Self {
31 FidlThemeMode::from_bits(ThemeMode::bits(&fidl))
32 .expect("failed to convert ThemeMode to FidlThemeMode")
33 }
34}
35
36impl From<FidlLowLightMode> for LowLightMode {
37 fn from(fidl_low_light_mode: FidlLowLightMode) -> Self {
38 match fidl_low_light_mode {
39 FidlLowLightMode::Disable => LowLightMode::Disable,
40 FidlLowLightMode::DisableImmediately => LowLightMode::DisableImmediately,
41 FidlLowLightMode::Enable => LowLightMode::Enable,
42 }
43 }
44}
45
46impl From<FidlThemeType> for ThemeType {
47 fn from(fidl_theme_type: FidlThemeType) -> Self {
48 match fidl_theme_type {
49 FidlThemeType::Default => ThemeType::Default,
50 FidlThemeType::Light => ThemeType::Light,
51 FidlThemeType::Dark => ThemeType::Dark,
52 }
53 }
54}
55
56impl From<FidlTheme> for Theme {
57 fn from(fidl_theme: FidlTheme) -> Self {
58 Self {
59 theme_type: fidl_theme.theme_type.map(Into::into),
60 theme_mode: fidl_theme.theme_mode.map(Into::into).unwrap_or_else(ThemeMode::empty),
61 }
62 }
63}
64
65impl From<DisplayInfo> for DisplaySettings {
66 fn from(info: DisplayInfo) -> Self {
67 fidl_fuchsia_settings::DisplaySettings {
68 auto_brightness: Some(info.auto_brightness),
69 adjusted_auto_brightness: Some(info.auto_brightness_value),
70 brightness_value: Some(info.manual_brightness_value),
71 screen_enabled: Some(info.screen_enabled),
72 low_light_mode: Some(match info.low_light_mode {
73 LowLightMode::Enable => FidlLowLightMode::Enable,
74 LowLightMode::Disable => FidlLowLightMode::Disable,
75 LowLightMode::DisableImmediately => FidlLowLightMode::DisableImmediately,
76 }),
77 theme: Some(FidlTheme {
78 theme_type: match info.theme {
79 Some(Theme { theme_type: Some(theme_type), .. }) => match theme_type {
80 ThemeType::Unknown => None,
81 ThemeType::Default => Some(FidlThemeType::Default),
82 ThemeType::Light => Some(FidlThemeType::Light),
83 ThemeType::Dark => Some(FidlThemeType::Dark),
84 },
85 _ => None,
86 },
87 theme_mode: match info.theme {
88 Some(Theme { theme_mode, .. }) if !theme_mode.is_empty() => {
89 Some(FidlThemeMode::from(theme_mode))
90 }
91 _ => None,
92 },
93 ..Default::default()
94 }),
95 ..Default::default()
96 }
97 }
98}
99
100fn to_request(settings: DisplaySettings) -> Result<SetDisplayInfo, Error> {
101 let set_display_info = SetDisplayInfo {
102 manual_brightness_value: settings.brightness_value,
103 auto_brightness_value: settings.adjusted_auto_brightness,
104 auto_brightness: settings.auto_brightness,
105 screen_enabled: settings.screen_enabled,
106 low_light_mode: settings.low_light_mode.map(Into::into),
107 theme: settings.theme.map(Into::into),
108 };
109 match set_display_info {
110 SetDisplayInfo {
112 manual_brightness_value: None,
113 auto_brightness_value: None,
114 auto_brightness: None,
115 screen_enabled: None,
116 low_light_mode: None,
117 theme: None,
118 } => Err(anyhow!("No values set")),
119 _ => Ok(set_display_info),
120 }
121}
122
123pub(crate) type SubscriberObject = HangingGetObserver<DisplayInfo, DisplayWatchResponder>;
124type HangingGetFn = fn(&DisplayInfo, SubscriberObject) -> bool;
125pub(crate) type HangingGet = server::HangingGet<DisplayInfo, SubscriberObject, HangingGetFn>;
126pub(crate) type Publisher = server::Publisher<DisplayInfo, SubscriberObject, HangingGetFn>;
127pub(crate) type Subscriber = server::Subscriber<DisplayInfo, SubscriberObject, HangingGetFn>;
128
129pub struct DisplayFidlHandler {
130 hanging_get: HangingGet,
131 controller_tx: UnboundedSender<Request>,
132 usage_publisher: UsagePublisher<DisplayInfo>,
133}
134
135impl DisplayFidlHandler {
136 pub(crate) fn new<T>(
137 display_controller: &mut DisplayController<T>,
138 usage_publisher: UsagePublisher<DisplayInfo>,
139 initial_value: DisplayInfo,
140 ) -> (Self, UnboundedReceiver<Request>) {
141 let hanging_get = HangingGet::new(initial_value, Self::hanging_get);
142 display_controller.register_publisher(hanging_get.new_publisher());
143 let (controller_tx, controller_rx) = mpsc::unbounded();
144 (Self { hanging_get, controller_tx, usage_publisher }, controller_rx)
145 }
146
147 fn hanging_get(info: &DisplayInfo, observer: SubscriberObject) -> bool {
148 let (usage_responder, responder) = observer.into_parts();
149 usage_responder.respond(format!("{info:?}"), ResponseType::OkSome);
150 if let Err(e) = responder.send(&DisplaySettings::from(*info)) {
151 log::warn!("Failed to respond to watch request: {e:?}");
152 return false;
153 }
154 true
155 }
156
157 pub fn handle_stream(&mut self, mut stream: DisplayRequestStream) {
158 let request_handler = RequestHandler {
159 subscriber: self.hanging_get.new_subscriber(),
160 controller_tx: self.controller_tx.clone(),
161 usage_publisher: self.usage_publisher.clone(),
162 };
163 fasync::Task::local(async move {
164 while let Some(Ok(request)) = stream.next().await {
165 request_handler.handle_request(request).await;
166 }
167 })
168 .detach();
169 }
170}
171
172#[derive(Debug)]
173enum HandlerError {
174 AlreadySubscribed,
175 InvalidArgument(
176 #[allow(dead_code)] Error,
178 ),
179 ControllerStopped,
180 Controller(DisplayError),
181}
182
183impl From<&HandlerError> for ResponseType {
184 fn from(error: &HandlerError) -> Self {
185 match error {
186 HandlerError::AlreadySubscribed => ResponseType::AlreadySubscribed,
187 HandlerError::InvalidArgument(_) => ResponseType::InvalidArgument,
188 HandlerError::ControllerStopped => ResponseType::UnexpectedError,
189 HandlerError::Controller(e) => ResponseType::from(e),
190 }
191 }
192}
193
194struct RequestHandler {
195 subscriber: Subscriber,
196 controller_tx: UnboundedSender<Request>,
197 usage_publisher: UsagePublisher<DisplayInfo>,
198}
199
200impl RequestHandler {
201 async fn handle_request(&self, request: DisplayRequest) {
202 match request {
203 DisplayRequest::Watch { responder } => {
204 let usage_res = self.usage_publisher.request("Watch".to_string(), RequestType::Get);
205 let observer = HangingGetObserver::new(usage_res, responder);
206 if let Err(observer) = self.subscriber.register2(observer) {
207 let e = HandlerError::AlreadySubscribed;
208 let (usage_res, responder) = observer.into_parts();
209 usage_res.respond(format!("Err({e:?})"), ResponseType::from(&e));
210 drop(responder);
211 }
212 }
213 DisplayRequest::Set { settings, responder } => {
214 let usage_res = self
215 .usage_publisher
216 .request(format!("Set{{settings:{settings:?}}}"), RequestType::Set);
217 if let Err(e) = self.set(settings).await {
218 usage_res.respond(format!("Err({e:?}"), ResponseType::from(&e));
219 let _ = responder.send(Err(SettingsError::Failed));
220 } else {
221 usage_res.respond("Ok(())".to_string(), ResponseType::OkNone);
222 let _ = responder.send(Ok(()));
223 }
224 }
225 }
226 }
227
228 async fn set(&self, settings: DisplaySettings) -> Result<(), HandlerError> {
229 let (set_tx, set_rx) = oneshot::channel();
230 let info = to_request(settings).map_err(HandlerError::InvalidArgument)?;
231 self.controller_tx
232 .unbounded_send(Request::Set(info, set_tx))
233 .map_err(|_| HandlerError::ControllerStopped)?;
234 set_rx
235 .await
236 .map_err(|_| HandlerError::ControllerStopped)
237 .and_then(|res| res.map_err(HandlerError::Controller))
238 }
239}