blob: 5a52baa30698c85be0a8221946d0f9d8163d4bb1 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::base::{SettingInfo, SettingType};
use crate::display::types::{LowLightMode, SetDisplayInfo, Theme, ThemeMode, ThemeType};
use crate::fidl_common::FidlResponseErrorLogger;
use crate::fidl_hanging_get_responder;
use crate::fidl_process;
use crate::fidl_processor::settings::RequestContext;
use crate::handler::base::Request;
use crate::request_respond;
use fidl::endpoints::ProtocolMarker;
use fidl_fuchsia_settings::{
DisplayMarker, DisplayRequest, DisplaySettings, DisplayWatchLightSensorResponder,
DisplayWatchResponder, Error, LightSensorData, LowLightMode as FidlLowLightMode,
Theme as FidlTheme, ThemeMode as FidlThemeMode, ThemeType as FidlThemeType,
};
use fuchsia_async as fasync;
fidl_hanging_get_responder!(
DisplayMarker,
DisplaySettings,
DisplayWatchResponder,
LightSensorData,
DisplayWatchLightSensorResponder,
);
impl From<SettingInfo> for LightSensorData {
fn from(response: SettingInfo) -> Self {
if let SettingInfo::LightSensor(data) = response {
let mut sensor_data = fidl_fuchsia_settings::LightSensorData::EMPTY;
sensor_data.illuminance_lux = Some(data.illuminance);
sensor_data.color = Some(data.color);
sensor_data
} else {
panic!("incorrect value sent to display");
}
}
}
impl From<FidlThemeMode> for ThemeMode {
fn from(fidl: FidlThemeMode) -> Self {
// TODO(fxbug.dev/61432): consider using TryFrom instead of panicking
ThemeMode::from_bits(FidlThemeMode::bits(&fidl))
.expect("failed to convert FidlThemeMode to ThemeMode")
}
}
impl From<ThemeMode> for FidlThemeMode {
fn from(fidl: ThemeMode) -> Self {
// TODO(fxbug.dev/61432): consider using TryFrom instead of panicking
FidlThemeMode::from_bits(ThemeMode::bits(&fidl))
.expect("failed to convert ThemeMode to FidlThemeMode")
}
}
impl From<FidlLowLightMode> for LowLightMode {
fn from(fidl_low_light_mode: FidlLowLightMode) -> Self {
match fidl_low_light_mode {
FidlLowLightMode::Disable => LowLightMode::Disable,
FidlLowLightMode::DisableImmediately => LowLightMode::DisableImmediately,
FidlLowLightMode::Enable => LowLightMode::Enable,
}
}
}
impl From<FidlThemeType> for ThemeType {
fn from(fidl_theme_type: FidlThemeType) -> Self {
match fidl_theme_type {
FidlThemeType::Default => ThemeType::Default,
FidlThemeType::Light => ThemeType::Light,
FidlThemeType::Dark => ThemeType::Dark,
}
}
}
impl From<FidlTheme> for Theme {
fn from(fidl_theme: FidlTheme) -> Self {
Self {
theme_type: fidl_theme.theme_type.map(Into::into),
theme_mode: fidl_theme.theme_mode.map(Into::into).unwrap_or_else(ThemeMode::empty),
}
}
}
impl From<SettingInfo> for DisplaySettings {
fn from(response: SettingInfo) -> Self {
if let SettingInfo::Brightness(info) = response {
let mut display_settings = fidl_fuchsia_settings::DisplaySettings::EMPTY;
display_settings.auto_brightness = Some(info.auto_brightness);
display_settings.adjusted_auto_brightness = Some(info.auto_brightness_value);
display_settings.brightness_value = Some(info.manual_brightness_value);
display_settings.screen_enabled = Some(info.screen_enabled);
display_settings.low_light_mode = Some(match info.low_light_mode {
LowLightMode::Enable => FidlLowLightMode::Enable,
LowLightMode::Disable => FidlLowLightMode::Disable,
LowLightMode::DisableImmediately => FidlLowLightMode::DisableImmediately,
});
display_settings.theme = Some(FidlTheme {
theme_type: match info.theme {
Some(Theme { theme_type: Some(theme_type), .. }) => match theme_type {
ThemeType::Unknown => None,
ThemeType::Default => Some(FidlThemeType::Default),
ThemeType::Light => Some(FidlThemeType::Light),
ThemeType::Dark => Some(FidlThemeType::Dark),
},
_ => None,
},
theme_mode: match info.theme {
Some(Theme { theme_mode, .. }) if !theme_mode.is_empty() => {
Some(FidlThemeMode::from(theme_mode))
}
_ => None,
},
..FidlTheme::EMPTY
});
display_settings
} else {
panic!("incorrect value sent to display");
}
}
}
fn to_request(settings: DisplaySettings) -> Option<Request> {
let set_display_info = SetDisplayInfo {
manual_brightness_value: settings.brightness_value,
auto_brightness_value: settings.adjusted_auto_brightness,
auto_brightness: settings.auto_brightness,
screen_enabled: settings.screen_enabled,
low_light_mode: settings.low_light_mode.map(Into::into),
theme: settings.theme.map(Into::into),
};
match set_display_info {
// No values being set is invalid
SetDisplayInfo {
manual_brightness_value: None,
auto_brightness_value: None,
auto_brightness: None,
screen_enabled: None,
low_light_mode: None,
theme: None,
} => None,
_ => Some(Request::SetDisplayInfo(set_display_info)),
}
}
fidl_process!(
Display,
SettingType::Display,
process_request,
SettingType::LightSensor,
LightSensorData,
DisplayWatchLightSensorResponder,
process_sensor_request,
);
async fn process_request(
context: RequestContext<DisplaySettings, DisplayWatchResponder>,
req: DisplayRequest,
) -> Result<Option<DisplayRequest>, anyhow::Error> {
// Support future expansion of FIDL.
#[allow(unreachable_patterns)]
match req {
DisplayRequest::Set { settings, responder } => {
if let Some(request) = to_request(settings) {
fasync::Task::spawn(async move {
request_respond!(
context,
responder,
SettingType::Display,
request,
Ok(()),
Err(Error::Failed),
DisplayMarker
);
})
.detach();
} else {
responder
.send(&mut Err(Error::Unsupported))
.log_fidl_response_error(DisplayMarker::DEBUG_NAME);
}
}
DisplayRequest::Watch { responder } => {
context.watch(responder, true).await;
}
_ => {
return Ok(Some(req));
}
}
Ok(None)
}
async fn process_sensor_request(
context: RequestContext<LightSensorData, DisplayWatchLightSensorResponder>,
req: DisplayRequest,
) -> Result<Option<DisplayRequest>, anyhow::Error> {
if let DisplayRequest::WatchLightSensor { delta, responder } = req {
context
.watch_with_change_fn(
// Bucket watch requests to the nearest 0.01.
format!("{:.2}", delta),
Box::new(move |old_data: &LightSensorData, new_data: &LightSensorData| {
if let (Some(old_lux), Some(new_lux)) =
(old_data.illuminance_lux, new_data.illuminance_lux)
{
(new_lux - old_lux).abs() >= delta
} else {
true
}
}),
responder,
true,
)
.await;
} else {
return Ok(Some(req));
}
Ok(None)
}