| // 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 serde::{Deserialize, Serialize}; |
| |
| use crate::base::{Merge, SettingInfo, SettingType}; |
| use crate::call; |
| use crate::config::default_settings::DefaultSetting; |
| use crate::display::display_configuration::{ |
| ConfigurationThemeMode, ConfigurationThemeType, DisplayConfiguration, |
| }; |
| use crate::display::types::{DisplayInfo, LowLightMode, Theme, ThemeBuilder, ThemeMode, ThemeType}; |
| use crate::handler::base::Request; |
| use crate::handler::device_storage::{DeviceStorageAccess, DeviceStorageCompatible}; |
| use crate::handler::setting_handler::persist::{controller as data_controller, ClientProxy}; |
| use crate::handler::setting_handler::{ |
| controller, ControllerError, IntoHandlerResult, SettingHandlerResult, |
| }; |
| use crate::service_context::ExternalServiceProxy; |
| use async_trait::async_trait; |
| use fidl_fuchsia_ui_brightness::{ |
| ControlMarker as BrightnessControlMarker, ControlProxy as BrightnessControlProxy, |
| }; |
| use lazy_static::lazy_static; |
| use std::sync::Mutex; |
| |
| pub const DEFAULT_MANUAL_BRIGHTNESS_VALUE: f32 = 0.5; |
| pub const DEFAULT_AUTO_BRIGHTNESS_VALUE: f32 = 0.5; |
| |
| lazy_static! { |
| /// Default display used if no configuration is available. |
| pub static ref DEFAULT_DISPLAY_INFO: DisplayInfo = DisplayInfo::new( |
| false, /*auto_brightness_enabled*/ |
| DEFAULT_MANUAL_BRIGHTNESS_VALUE, /*manual_brightness_value*/ |
| DEFAULT_AUTO_BRIGHTNESS_VALUE, /*auto_brightness_value*/ |
| true, /*screen_enabled*/ |
| LowLightMode::Disable, /*low_light_mode*/ |
| None, /*theme*/ |
| ); |
| } |
| |
| lazy_static! { |
| /// Reference to a display configuration. |
| pub static ref DISPLAY_CONFIGURATION: Mutex<DefaultSetting<DisplayConfiguration, &'static str>> = |
| Mutex::new(DefaultSetting::new(None, "/config/data/display_configuration.json", None, false)); |
| } |
| |
| /// Returns a default display [`DisplayInfo`] that is derived from |
| /// [`DEFAULT_DISPLAY_INFO`] with any fields specified in the |
| /// display configuration set. |
| pub fn default_display_info() -> DisplayInfo { |
| let mut default_display_info = DEFAULT_DISPLAY_INFO.clone(); |
| |
| if let Some(display_configuration) = DISPLAY_CONFIGURATION.lock().unwrap().get_default_value() { |
| default_display_info.theme = Some(Theme { |
| theme_type: Some(match display_configuration.theme.theme_type { |
| ConfigurationThemeType::Light => ThemeType::Light, |
| }), |
| theme_mode: if display_configuration |
| .theme |
| .theme_mode |
| .contains(&ConfigurationThemeMode::Auto) |
| { |
| ThemeMode::AUTO |
| } else { |
| ThemeMode::empty() |
| }, |
| }); |
| } |
| |
| default_display_info |
| } |
| |
| impl DeviceStorageCompatible for DisplayInfo { |
| const KEY: &'static str = "display_info"; |
| |
| fn default_value() -> Self { |
| default_display_info() |
| } |
| |
| fn deserialize_from(value: &String) -> Self { |
| Self::extract(&value) |
| .unwrap_or_else(|_| Self::from(DisplayInfoV5::deserialize_from(&value))) |
| } |
| } |
| |
| impl Into<SettingInfo> for DisplayInfo { |
| fn into(self) -> SettingInfo { |
| SettingInfo::Brightness(self) |
| } |
| } |
| |
| impl From<DisplayInfoV5> for DisplayInfo { |
| fn from(v5: DisplayInfoV5) -> Self { |
| DisplayInfo { |
| auto_brightness: v5.auto_brightness, |
| auto_brightness_value: DEFAULT_AUTO_BRIGHTNESS_VALUE, |
| manual_brightness_value: v5.manual_brightness_value, |
| screen_enabled: v5.screen_enabled, |
| low_light_mode: v5.low_light_mode, |
| theme: v5.theme, |
| } |
| } |
| } |
| |
| #[async_trait] |
| pub trait BrightnessManager: Sized { |
| async fn from_client(client: &ClientProxy) -> Result<Self, ControllerError>; |
| async fn update_brightness( |
| &self, |
| info: DisplayInfo, |
| client: &ClientProxy, |
| ) -> SettingHandlerResult; |
| } |
| |
| #[async_trait] |
| impl BrightnessManager for () { |
| async fn from_client(_: &ClientProxy) -> Result<Self, ControllerError> { |
| Ok(()) |
| } |
| |
| // This does not send the brightness value on anywhere, it simply stores it. |
| // External services will pick up the value and set it on the brightness manager. |
| async fn update_brightness( |
| &self, |
| info: DisplayInfo, |
| client: &ClientProxy, |
| ) -> SettingHandlerResult { |
| client.write_setting(info.into(), false).await.into_handler_result() |
| } |
| } |
| |
| pub struct ExternalBrightnessControl { |
| brightness_service: ExternalServiceProxy<BrightnessControlProxy>, |
| } |
| |
| #[async_trait] |
| impl BrightnessManager for ExternalBrightnessControl { |
| async fn from_client(client: &ClientProxy) -> Result<Self, ControllerError> { |
| client |
| .get_service_context() |
| .connect::<BrightnessControlMarker>() |
| .await |
| .map(|brightness_service| Self { brightness_service }) |
| .map_err(|_| { |
| ControllerError::InitFailure("could not connect to brightness service".into()) |
| }) |
| } |
| |
| async fn update_brightness( |
| &self, |
| info: DisplayInfo, |
| client: &ClientProxy, |
| ) -> SettingHandlerResult { |
| client.write_setting(info.into(), false).await?; |
| |
| if info.auto_brightness { |
| self.brightness_service.call(BrightnessControlProxy::set_auto_brightness) |
| } else { |
| call!(self.brightness_service => set_manual_brightness(info.manual_brightness_value)) |
| } |
| .map(|_| None) |
| .map_err(|_| { |
| ControllerError::ExternalFailure( |
| SettingType::Display, |
| "brightness_service".into(), |
| "set_brightness".into(), |
| ) |
| }) |
| } |
| } |
| |
| pub struct DisplayController<T = ()> |
| where |
| T: BrightnessManager, |
| { |
| client: ClientProxy, |
| brightness_manager: T, |
| } |
| |
| impl<T> DeviceStorageAccess for DisplayController<T> |
| where |
| T: BrightnessManager, |
| { |
| const STORAGE_KEYS: &'static [&'static str] = &[DisplayInfo::KEY]; |
| } |
| |
| #[async_trait] |
| impl<T> data_controller::Create for DisplayController<T> |
| where |
| T: BrightnessManager, |
| { |
| /// Creates the controller |
| async fn create(client: ClientProxy) -> Result<Self, ControllerError> { |
| let brightness_manager = <T as BrightnessManager>::from_client(&client).await?; |
| Ok(Self { client, brightness_manager }) |
| } |
| } |
| |
| #[async_trait] |
| impl<T> controller::Handle for DisplayController<T> |
| where |
| T: BrightnessManager + Send + Sync, |
| { |
| async fn handle(&self, request: Request) -> Option<SettingHandlerResult> { |
| match request { |
| Request::Restore => { |
| let display_info = self.client.read_setting::<DisplayInfo>().await; |
| |
| // Load and set value. |
| Some(self.brightness_manager.update_brightness(display_info, &self.client).await) |
| } |
| Request::SetDisplayInfo(mut set_display_info) => { |
| let display_info = self.client.read_setting::<DisplayInfo>().await; |
| |
| if let Some(theme) = set_display_info.theme { |
| set_display_info.theme = self.build_theme(theme, &display_info); |
| } |
| |
| Some( |
| self.brightness_manager |
| .update_brightness(display_info.merge(set_display_info), &self.client) |
| .await, |
| ) |
| } |
| Request::Get => { |
| Some(self.client.read_setting_info::<DisplayInfo>().await.into_handler_result()) |
| } |
| _ => None, |
| } |
| } |
| } |
| |
| impl<T> DisplayController<T> |
| where |
| T: BrightnessManager, |
| { |
| fn build_theme(&self, incoming_theme: Theme, display_info: &DisplayInfo) -> Option<Theme> { |
| let mut theme_builder = ThemeBuilder::new(); |
| |
| let existing_theme_type = display_info.theme.map_or(None, |theme| theme.theme_type); |
| |
| let new_theme_type = incoming_theme.theme_type.or(existing_theme_type); |
| |
| // Temporarily, if no theme type has ever been set, and the |
| // theme mode is Auto, we also set the theme type to Auto |
| // to support clients that haven't migrated. |
| // TODO(fxb/64775): Remove this assignment. |
| let mode_adjusted_new_theme_type = match new_theme_type { |
| None | Some(ThemeType::Unknown) |
| if incoming_theme.theme_mode.contains(ThemeMode::AUTO) => |
| { |
| Some(ThemeType::Auto) |
| } |
| _ => new_theme_type, |
| }; |
| |
| theme_builder.set_theme_type(mode_adjusted_new_theme_type); |
| |
| theme_builder.set_theme_mode( |
| incoming_theme.theme_mode |
| // Temporarily, if the theme type is auto we also set the |
| // theme mode to auto until all clients are sending setUI |
| // theme mode Auto. |
| // TODO(fxb/64775): Remove this or clause. |
| | match incoming_theme.theme_type { |
| Some(ThemeType::Auto) => ThemeMode::AUTO, |
| _ => ThemeMode::empty(), |
| }, |
| ); |
| |
| theme_builder.build() |
| } |
| } |
| |
| /// The following struct should never be modified. It represents an old |
| /// version of the display settings. |
| #[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize)] |
| pub struct DisplayInfoV1 { |
| /// The last brightness value that was manually set. |
| pub manual_brightness_value: f32, |
| pub auto_brightness: bool, |
| pub low_light_mode: LowLightMode, |
| } |
| |
| impl DisplayInfoV1 { |
| pub const fn new( |
| auto_brightness: bool, |
| manual_brightness_value: f32, |
| low_light_mode: LowLightMode, |
| ) -> DisplayInfoV1 { |
| DisplayInfoV1 { manual_brightness_value, auto_brightness, low_light_mode } |
| } |
| } |
| |
| impl DeviceStorageCompatible for DisplayInfoV1 { |
| const KEY: &'static str = "display_infoV1"; |
| |
| fn default_value() -> Self { |
| DisplayInfoV1::new( |
| false, /*auto_brightness_enabled*/ |
| DEFAULT_MANUAL_BRIGHTNESS_VALUE, /*brightness_value*/ |
| LowLightMode::Disable, /*low_light_mode*/ |
| ) |
| } |
| } |
| |
| /// The following struct should never be modified. It represents an old |
| /// version of the display settings. |
| #[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize)] |
| pub struct DisplayInfoV2 { |
| pub manual_brightness_value: f32, |
| pub auto_brightness: bool, |
| pub low_light_mode: LowLightMode, |
| pub theme_mode: ThemeModeV1, |
| } |
| |
| impl DisplayInfoV2 { |
| pub const fn new( |
| auto_brightness: bool, |
| manual_brightness_value: f32, |
| low_light_mode: LowLightMode, |
| theme_mode: ThemeModeV1, |
| ) -> DisplayInfoV2 { |
| DisplayInfoV2 { manual_brightness_value, auto_brightness, low_light_mode, theme_mode } |
| } |
| } |
| |
| impl DeviceStorageCompatible for DisplayInfoV2 { |
| const KEY: &'static str = "display_infoV2"; |
| |
| fn default_value() -> Self { |
| DisplayInfoV2::new( |
| false, /*auto_brightness_enabled*/ |
| DEFAULT_MANUAL_BRIGHTNESS_VALUE, /*brightness_value*/ |
| LowLightMode::Disable, /*low_light_mode*/ |
| ThemeModeV1::Unknown, /*theme_mode*/ |
| ) |
| } |
| |
| fn deserialize_from(value: &String) -> Self { |
| Self::extract(&value) |
| .unwrap_or_else(|_| Self::from(DisplayInfoV1::deserialize_from(&value))) |
| } |
| } |
| |
| impl From<DisplayInfoV1> for DisplayInfoV2 { |
| fn from(v1: DisplayInfoV1) -> Self { |
| DisplayInfoV2 { |
| auto_brightness: v1.auto_brightness, |
| manual_brightness_value: v1.manual_brightness_value, |
| low_light_mode: v1.low_light_mode, |
| theme_mode: ThemeModeV1::Unknown, |
| } |
| } |
| } |
| |
| #[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize)] |
| pub enum ThemeModeV1 { |
| Unknown, |
| Default, |
| Light, |
| Dark, |
| /// Product can choose a theme based on ambient cues. |
| Auto, |
| } |
| |
| impl From<ThemeModeV1> for ThemeType { |
| fn from(theme_mode_v1: ThemeModeV1) -> Self { |
| match theme_mode_v1 { |
| ThemeModeV1::Unknown => ThemeType::Unknown, |
| ThemeModeV1::Default => ThemeType::Default, |
| ThemeModeV1::Light => ThemeType::Light, |
| ThemeModeV1::Dark => ThemeType::Dark, |
| ThemeModeV1::Auto => ThemeType::Auto, |
| } |
| } |
| } |
| |
| #[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize)] |
| pub struct DisplayInfoV3 { |
| /// The last brightness value that was manually set. |
| pub manual_brightness_value: f32, |
| pub auto_brightness: bool, |
| pub screen_enabled: bool, |
| pub low_light_mode: LowLightMode, |
| pub theme_mode: ThemeModeV1, |
| } |
| |
| impl DisplayInfoV3 { |
| pub const fn new( |
| auto_brightness: bool, |
| manual_brightness_value: f32, |
| screen_enabled: bool, |
| low_light_mode: LowLightMode, |
| theme_mode: ThemeModeV1, |
| ) -> DisplayInfoV3 { |
| DisplayInfoV3 { |
| manual_brightness_value, |
| auto_brightness, |
| screen_enabled, |
| low_light_mode, |
| theme_mode, |
| } |
| } |
| } |
| |
| impl DeviceStorageCompatible for DisplayInfoV3 { |
| const KEY: &'static str = "display_info"; |
| |
| fn default_value() -> Self { |
| DisplayInfoV3::new( |
| false, /*auto_brightness_enabled*/ |
| DEFAULT_MANUAL_BRIGHTNESS_VALUE, /*brightness_value*/ |
| true, /*screen_enabled*/ |
| LowLightMode::Disable, /*low_light_mode*/ |
| ThemeModeV1::Unknown, /*theme_mode*/ |
| ) |
| } |
| |
| fn deserialize_from(value: &String) -> Self { |
| Self::extract(&value) |
| .unwrap_or_else(|_| Self::from(DisplayInfoV2::deserialize_from(&value))) |
| } |
| } |
| |
| impl From<DisplayInfoV2> for DisplayInfoV3 { |
| fn from(v2: DisplayInfoV2) -> Self { |
| DisplayInfoV3 { |
| auto_brightness: v2.auto_brightness, |
| manual_brightness_value: v2.manual_brightness_value, |
| screen_enabled: true, |
| low_light_mode: v2.low_light_mode, |
| theme_mode: v2.theme_mode, |
| } |
| } |
| } |
| |
| #[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize)] |
| pub struct DisplayInfoV4 { |
| /// The last brightness value that was manually set. |
| pub manual_brightness_value: f32, |
| pub auto_brightness: bool, |
| pub screen_enabled: bool, |
| pub low_light_mode: LowLightMode, |
| pub theme_type: ThemeType, |
| } |
| |
| impl DisplayInfoV4 { |
| pub const fn new( |
| auto_brightness: bool, |
| manual_brightness_value: f32, |
| screen_enabled: bool, |
| low_light_mode: LowLightMode, |
| theme_type: ThemeType, |
| ) -> DisplayInfoV4 { |
| DisplayInfoV4 { |
| manual_brightness_value, |
| auto_brightness, |
| screen_enabled, |
| low_light_mode, |
| theme_type, |
| } |
| } |
| } |
| |
| impl From<DisplayInfoV3> for DisplayInfoV4 { |
| fn from(v3: DisplayInfoV3) -> Self { |
| DisplayInfoV4 { |
| auto_brightness: v3.auto_brightness, |
| manual_brightness_value: v3.manual_brightness_value, |
| screen_enabled: v3.screen_enabled, |
| low_light_mode: v3.low_light_mode, |
| // In v4, the field formerly known as theme_mode was renamed to |
| // theme_type. |
| theme_type: ThemeType::from(v3.theme_mode), |
| } |
| } |
| } |
| |
| impl DeviceStorageCompatible for DisplayInfoV4 { |
| const KEY: &'static str = "display_info"; |
| |
| fn default_value() -> Self { |
| DisplayInfoV4::new( |
| false, /*auto_brightness_enabled*/ |
| DEFAULT_MANUAL_BRIGHTNESS_VALUE, /*brightness_value*/ |
| true, /*screen_enabled*/ |
| LowLightMode::Disable, /*low_light_mode*/ |
| ThemeType::Unknown, /*theme_type*/ |
| ) |
| } |
| |
| fn deserialize_from(value: &String) -> Self { |
| Self::extract(&value) |
| .unwrap_or_else(|_| Self::from(DisplayInfoV3::deserialize_from(&value))) |
| } |
| } |
| |
| #[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize)] |
| #[serde(deny_unknown_fields)] |
| pub struct DisplayInfoV5 { |
| /// The last brightness value that was manually set. |
| pub manual_brightness_value: f32, |
| pub auto_brightness: bool, |
| pub screen_enabled: bool, |
| pub low_light_mode: LowLightMode, |
| pub theme: Option<Theme>, |
| } |
| |
| impl DisplayInfoV5 { |
| pub const fn new( |
| auto_brightness: bool, |
| manual_brightness_value: f32, |
| screen_enabled: bool, |
| low_light_mode: LowLightMode, |
| theme: Option<Theme>, |
| ) -> DisplayInfoV5 { |
| DisplayInfoV5 { |
| manual_brightness_value, |
| auto_brightness, |
| screen_enabled, |
| low_light_mode, |
| theme, |
| } |
| } |
| } |
| |
| impl From<DisplayInfoV4> for DisplayInfoV5 { |
| fn from(v4: DisplayInfoV4) -> Self { |
| DisplayInfoV5 { |
| auto_brightness: v4.auto_brightness, |
| manual_brightness_value: v4.manual_brightness_value, |
| screen_enabled: v4.screen_enabled, |
| low_light_mode: v4.low_light_mode, |
| theme: Some(Theme::new( |
| Some(v4.theme_type), |
| if v4.theme_type == ThemeType::Auto { ThemeMode::AUTO } else { ThemeMode::empty() }, |
| )), |
| } |
| } |
| } |
| |
| impl DeviceStorageCompatible for DisplayInfoV5 { |
| const KEY: &'static str = "display_info"; |
| |
| fn default_value() -> Self { |
| DisplayInfoV5::new( |
| false, /*auto_brightness_enabled*/ |
| DEFAULT_MANUAL_BRIGHTNESS_VALUE, /*brightness_value*/ |
| true, /*screen_enabled*/ |
| LowLightMode::Disable, /*low_light_mode*/ |
| Some(Theme::new(Some(ThemeType::Unknown), ThemeMode::empty())), /*theme_type*/ |
| ) |
| } |
| |
| fn deserialize_from(value: &String) -> Self { |
| Self::extract(&value) |
| .unwrap_or_else(|_| Self::from(DisplayInfoV4::deserialize_from(&value))) |
| } |
| } |
| |
| #[test] |
| fn test_display_migration_v1_to_v2() { |
| let v1 = DisplayInfoV1 { |
| manual_brightness_value: 0.6, |
| auto_brightness: true, |
| low_light_mode: LowLightMode::Enable, |
| }; |
| |
| let serialized_v1 = v1.serialize_to(); |
| let v2 = DisplayInfoV2::deserialize_from(&serialized_v1); |
| |
| assert_eq!( |
| v2, |
| DisplayInfoV2 { |
| manual_brightness_value: v1.manual_brightness_value, |
| auto_brightness: v1.auto_brightness, |
| low_light_mode: v1.low_light_mode, |
| theme_mode: DisplayInfoV2::default_value().theme_mode, |
| } |
| ); |
| } |
| |
| #[test] |
| fn test_display_migration_v2_to_v3() { |
| let v2 = DisplayInfoV2 { |
| manual_brightness_value: 0.7, |
| auto_brightness: true, |
| low_light_mode: LowLightMode::Enable, |
| theme_mode: ThemeModeV1::Default, |
| }; |
| |
| let serialized_v2 = v2.serialize_to(); |
| let v3 = DisplayInfoV3::deserialize_from(&serialized_v2); |
| |
| assert_eq!( |
| v3, |
| DisplayInfoV3 { |
| manual_brightness_value: v2.manual_brightness_value, |
| auto_brightness: v2.auto_brightness, |
| screen_enabled: DisplayInfoV3::default_value().screen_enabled, |
| low_light_mode: v2.low_light_mode, |
| theme_mode: v2.theme_mode, |
| } |
| ); |
| } |
| |
| #[test] |
| fn test_display_migration_v3_to_v4() { |
| let v3 = DisplayInfoV3 { |
| manual_brightness_value: 0.7, |
| auto_brightness: true, |
| low_light_mode: LowLightMode::Enable, |
| theme_mode: ThemeModeV1::Light, |
| screen_enabled: false, |
| }; |
| |
| let serialized_v3 = v3.serialize_to(); |
| let v4 = DisplayInfoV4::deserialize_from(&serialized_v3); |
| |
| // In v4, the field formally known as theme_mode is theme_type. |
| assert_eq!( |
| v4, |
| DisplayInfoV4 { |
| manual_brightness_value: v3.manual_brightness_value, |
| auto_brightness: v3.auto_brightness, |
| low_light_mode: v3.low_light_mode, |
| theme_type: ThemeType::Light, |
| screen_enabled: v3.screen_enabled, |
| } |
| ); |
| } |
| |
| #[test] |
| fn test_display_migration_v4_to_v5() { |
| let v4 = DisplayInfoV4 { |
| manual_brightness_value: 0.7, |
| auto_brightness: true, |
| low_light_mode: LowLightMode::Enable, |
| theme_type: ThemeType::Auto, |
| screen_enabled: false, |
| }; |
| |
| let serialized_v4 = v4.serialize_to(); |
| let v5 = DisplayInfoV5::deserialize_from(&serialized_v4); |
| |
| assert_eq!( |
| v5, |
| DisplayInfoV5 { |
| manual_brightness_value: v4.manual_brightness_value, |
| auto_brightness: v4.auto_brightness, |
| low_light_mode: v4.low_light_mode, |
| theme: Some(Theme::new(Some(v4.theme_type), ThemeMode::AUTO)), |
| screen_enabled: v4.screen_enabled, |
| } |
| ); |
| } |
| |
| #[test] |
| fn test_display_migration_v1_to_current() { |
| let v1 = DisplayInfoV1 { |
| manual_brightness_value: 0.6, |
| auto_brightness: true, |
| low_light_mode: LowLightMode::Enable, |
| }; |
| |
| let serialized_v1 = v1.serialize_to(); |
| let current = DisplayInfo::deserialize_from(&serialized_v1); |
| |
| assert_eq!( |
| current, |
| DisplayInfo { |
| manual_brightness_value: v1.manual_brightness_value, |
| auto_brightness: v1.auto_brightness, |
| low_light_mode: v1.low_light_mode, |
| theme: Some(Theme::new(Some(ThemeType::Unknown), ThemeMode::empty())), |
| // screen_enabled was added in v3. |
| screen_enabled: DisplayInfoV3::default_value().screen_enabled, |
| auto_brightness_value: DEFAULT_DISPLAY_INFO.auto_brightness_value, |
| } |
| ); |
| } |
| |
| #[test] |
| fn test_display_migration_v2_to_current() { |
| let v2 = DisplayInfoV2 { |
| manual_brightness_value: 0.6, |
| auto_brightness: true, |
| low_light_mode: LowLightMode::Enable, |
| theme_mode: ThemeModeV1::Light, |
| }; |
| |
| let serialized_v2 = v2.serialize_to(); |
| let current = DisplayInfo::deserialize_from(&serialized_v2); |
| |
| assert_eq!( |
| current, |
| DisplayInfo { |
| manual_brightness_value: v2.manual_brightness_value, |
| auto_brightness: v2.auto_brightness, |
| low_light_mode: v2.low_light_mode, |
| theme: Some(Theme::new(Some(ThemeType::Light), ThemeMode::empty())), |
| // screen_enabled was added in v3. |
| screen_enabled: DisplayInfoV3::default_value().screen_enabled, |
| auto_brightness_value: DEFAULT_DISPLAY_INFO.auto_brightness_value, |
| } |
| ); |
| } |
| |
| #[test] |
| fn test_display_migration_v3_to_current() { |
| let v3 = DisplayInfoV3 { |
| manual_brightness_value: 0.6, |
| auto_brightness: true, |
| low_light_mode: LowLightMode::Enable, |
| theme_mode: ThemeModeV1::Light, |
| screen_enabled: false, |
| }; |
| |
| let serialized_v3 = v3.serialize_to(); |
| let current = DisplayInfo::deserialize_from(&serialized_v3); |
| |
| assert_eq!( |
| current, |
| DisplayInfo { |
| manual_brightness_value: v3.manual_brightness_value, |
| auto_brightness: v3.auto_brightness, |
| low_light_mode: v3.low_light_mode, |
| theme: Some(Theme::new(Some(ThemeType::Light), ThemeMode::empty())), |
| // screen_enabled was added in v3. |
| screen_enabled: v3.screen_enabled, |
| auto_brightness_value: DEFAULT_DISPLAY_INFO.auto_brightness_value, |
| } |
| ); |
| } |
| |
| #[test] |
| fn test_display_migration_v4_to_current() { |
| let v4 = DisplayInfoV4 { |
| manual_brightness_value: 0.6, |
| auto_brightness: true, |
| low_light_mode: LowLightMode::Enable, |
| theme_type: ThemeType::Light, |
| screen_enabled: false, |
| }; |
| |
| let serialized_v4 = v4.serialize_to(); |
| let current = DisplayInfo::deserialize_from(&serialized_v4); |
| |
| assert_eq!( |
| current, |
| DisplayInfo { |
| manual_brightness_value: v4.manual_brightness_value, |
| auto_brightness: v4.auto_brightness, |
| low_light_mode: v4.low_light_mode, |
| theme: Some(Theme::new(Some(ThemeType::Light), ThemeMode::empty())), |
| screen_enabled: v4.screen_enabled, |
| auto_brightness_value: DEFAULT_DISPLAY_INFO.auto_brightness_value, |
| } |
| ); |
| } |
| |
| #[test] |
| fn test_display_migration_v5_to_current() { |
| let v5 = DisplayInfoV5 { |
| manual_brightness_value: 0.6, |
| auto_brightness: true, |
| low_light_mode: LowLightMode::Enable, |
| theme: Some(Theme::new(Some(ThemeType::Light), ThemeMode::AUTO)), |
| screen_enabled: false, |
| }; |
| |
| let serialized_v5 = v5.serialize_to(); |
| let current = DisplayInfo::deserialize_from(&serialized_v5); |
| |
| assert_eq!( |
| current, |
| DisplayInfo { |
| manual_brightness_value: v5.manual_brightness_value, |
| auto_brightness: v5.auto_brightness, |
| low_light_mode: v5.low_light_mode, |
| theme: Some(Theme::new(Some(ThemeType::Light), ThemeMode::AUTO)), |
| screen_enabled: v5.screen_enabled, |
| auto_brightness_value: DEFAULT_DISPLAY_INFO.auto_brightness_value, |
| } |
| ); |
| } |