settings/display/
display_fidl_handler.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4use crate::base::{SettingInfo, SettingType};
5use crate::display::types::{LowLightMode, SetDisplayInfo, Theme, ThemeMode, ThemeType};
6use crate::handler::base::Request;
7use crate::ingress::{request, watch, Scoped};
8use crate::job::source::{Error as JobError, ErrorResponder};
9use crate::job::Job;
10use fidl::endpoints::{ControlHandle, Responder};
11use fidl_fuchsia_settings::{
12    DisplayRequest, DisplaySetResponder, DisplaySetResult, DisplaySettings, DisplayWatchResponder,
13    LowLightMode as FidlLowLightMode, Theme as FidlTheme, ThemeMode as FidlThemeMode,
14    ThemeType as FidlThemeType,
15};
16
17impl From<FidlThemeMode> for ThemeMode {
18    fn from(fidl: FidlThemeMode) -> Self {
19        ThemeMode::from_bits(FidlThemeMode::bits(&fidl))
20            .expect("failed to convert FidlThemeMode to ThemeMode")
21    }
22}
23
24impl From<ThemeMode> for FidlThemeMode {
25    fn from(fidl: ThemeMode) -> Self {
26        FidlThemeMode::from_bits(ThemeMode::bits(&fidl))
27            .expect("failed to convert ThemeMode to FidlThemeMode")
28    }
29}
30
31impl From<FidlLowLightMode> for LowLightMode {
32    fn from(fidl_low_light_mode: FidlLowLightMode) -> Self {
33        match fidl_low_light_mode {
34            FidlLowLightMode::Disable => LowLightMode::Disable,
35            FidlLowLightMode::DisableImmediately => LowLightMode::DisableImmediately,
36            FidlLowLightMode::Enable => LowLightMode::Enable,
37        }
38    }
39}
40
41impl From<FidlThemeType> for ThemeType {
42    fn from(fidl_theme_type: FidlThemeType) -> Self {
43        match fidl_theme_type {
44            FidlThemeType::Default => ThemeType::Default,
45            FidlThemeType::Light => ThemeType::Light,
46            FidlThemeType::Dark => ThemeType::Dark,
47        }
48    }
49}
50
51impl From<FidlTheme> for Theme {
52    fn from(fidl_theme: FidlTheme) -> Self {
53        Self {
54            theme_type: fidl_theme.theme_type.map(Into::into),
55            theme_mode: fidl_theme.theme_mode.map(Into::into).unwrap_or_else(ThemeMode::empty),
56        }
57    }
58}
59
60impl From<SettingInfo> for DisplaySettings {
61    fn from(response: SettingInfo) -> Self {
62        if let SettingInfo::Brightness(info) = response {
63            fidl_fuchsia_settings::DisplaySettings {
64                auto_brightness: Some(info.auto_brightness),
65                adjusted_auto_brightness: Some(info.auto_brightness_value),
66                brightness_value: Some(info.manual_brightness_value),
67                screen_enabled: Some(info.screen_enabled),
68                low_light_mode: Some(match info.low_light_mode {
69                    LowLightMode::Enable => FidlLowLightMode::Enable,
70                    LowLightMode::Disable => FidlLowLightMode::Disable,
71                    LowLightMode::DisableImmediately => FidlLowLightMode::DisableImmediately,
72                }),
73                theme: Some(FidlTheme {
74                    theme_type: match info.theme {
75                        Some(Theme { theme_type: Some(theme_type), .. }) => match theme_type {
76                            ThemeType::Unknown => None,
77                            ThemeType::Default => Some(FidlThemeType::Default),
78                            ThemeType::Light => Some(FidlThemeType::Light),
79                            ThemeType::Dark => Some(FidlThemeType::Dark),
80                        },
81                        _ => None,
82                    },
83                    theme_mode: match info.theme {
84                        Some(Theme { theme_mode, .. }) if !theme_mode.is_empty() => {
85                            Some(FidlThemeMode::from(theme_mode))
86                        }
87                        _ => None,
88                    },
89                    ..Default::default()
90                }),
91                ..Default::default()
92            }
93        } else {
94            panic!("incorrect value sent to display");
95        }
96    }
97}
98
99impl ErrorResponder for DisplaySetResponder {
100    fn id(&self) -> &'static str {
101        "Display_Set"
102    }
103
104    fn respond(self: Box<Self>, error: fidl_fuchsia_settings::Error) -> Result<(), fidl::Error> {
105        self.send(Err(error))
106    }
107}
108
109impl request::Responder<Scoped<DisplaySetResult>> for DisplaySetResponder {
110    fn respond(self, Scoped(response): Scoped<DisplaySetResult>) {
111        let _ = self.send(response);
112    }
113}
114
115impl watch::Responder<DisplaySettings, zx::Status> for DisplayWatchResponder {
116    fn respond(self, response: Result<DisplaySettings, zx::Status>) {
117        match response {
118            Ok(settings) => {
119                let _ = self.send(&settings);
120            }
121            Err(error) => {
122                self.control_handle().shutdown_with_epitaph(error);
123            }
124        }
125    }
126}
127
128fn to_request(settings: DisplaySettings) -> Option<Request> {
129    let set_display_info = SetDisplayInfo {
130        manual_brightness_value: settings.brightness_value,
131        auto_brightness_value: settings.adjusted_auto_brightness,
132        auto_brightness: settings.auto_brightness,
133        screen_enabled: settings.screen_enabled,
134        low_light_mode: settings.low_light_mode.map(Into::into),
135        theme: settings.theme.map(Into::into),
136    };
137    match set_display_info {
138        // No values being set is invalid
139        SetDisplayInfo {
140            manual_brightness_value: None,
141            auto_brightness_value: None,
142            auto_brightness: None,
143            screen_enabled: None,
144            low_light_mode: None,
145            theme: None,
146        } => None,
147        _ => Some(Request::SetDisplayInfo(set_display_info)),
148    }
149}
150
151impl TryFrom<DisplayRequest> for Job {
152    type Error = JobError;
153    fn try_from(req: DisplayRequest) -> Result<Self, Self::Error> {
154        // Support future expansion of FIDL
155        #[allow(unreachable_patterns)]
156        match req {
157            DisplayRequest::Set { settings, responder } => match to_request(settings) {
158                Some(request) => {
159                    Ok(request::Work::new(SettingType::Display, request, responder).into())
160                }
161                None => Err(JobError::InvalidInput(Box::new(responder))),
162            },
163            DisplayRequest::Watch { responder } => {
164                Ok(watch::Work::new_job(SettingType::Display, responder))
165            }
166            _ => {
167                log::warn!("Received a call to an unsupported API: {:?}", req);
168                Err(JobError::Unsupported)
169            }
170        }
171    }
172}