1use anyhow::Error;
6use serde::{Deserialize, Serialize};
7
8use crate::base::{Merge, SettingInfo, SettingType};
9use crate::display::display_configuration::{
10 ConfigurationThemeMode, ConfigurationThemeType, DisplayConfiguration,
11};
12use crate::display::types::{DisplayInfo, LowLightMode, Theme, ThemeBuilder, ThemeMode, ThemeType};
13use crate::handler::base::Request;
14use crate::handler::setting_handler::persist::{controller as data_controller, ClientProxy};
15use crate::handler::setting_handler::{controller, ControllerError, SettingHandlerResult};
16use crate::service_context::ExternalServiceProxy;
17use async_trait::async_trait;
18use fidl_fuchsia_ui_brightness::{
19 ControlMarker as BrightnessControlMarker, ControlProxy as BrightnessControlProxy,
20};
21use fuchsia_trace as ftrace;
22use settings_common::call;
23use settings_common::config::default_settings::DefaultSetting;
24use settings_storage::device_storage::{DeviceStorage, DeviceStorageCompatible};
25use settings_storage::storage_factory::{DefaultLoader, NoneT, StorageAccess, StorageFactory};
26use settings_storage::UpdateState;
27use std::marker::PhantomData;
28use std::rc::Rc;
29use std::sync::Mutex;
30
31pub(super) const DEFAULT_MANUAL_BRIGHTNESS_VALUE: f32 = 0.5;
32pub(super) const DEFAULT_AUTO_BRIGHTNESS_VALUE: f32 = 0.5;
33
34pub(crate) const DEFAULT_DISPLAY_INFO: DisplayInfo = DisplayInfo::new(
36 false, DEFAULT_MANUAL_BRIGHTNESS_VALUE, DEFAULT_AUTO_BRIGHTNESS_VALUE, true, LowLightMode::Disable, None, );
43
44pub struct DisplayInfoLoader {
48 display_configuration: Mutex<DefaultSetting<DisplayConfiguration, &'static str>>,
49}
50
51impl DisplayInfoLoader {
52 pub(crate) fn new(default_setting: DefaultSetting<DisplayConfiguration, &'static str>) -> Self {
53 Self { display_configuration: Mutex::new(default_setting) }
54 }
55}
56
57impl DefaultLoader for DisplayInfoLoader {
58 type Result = DisplayInfo;
59
60 fn default_value(&self) -> Self::Result {
61 let mut default_display_info = DEFAULT_DISPLAY_INFO;
62
63 if let Ok(Some(display_configuration)) =
64 self.display_configuration.lock().unwrap().get_cached_value()
65 {
66 default_display_info.theme = Some(Theme {
67 theme_type: Some(match display_configuration.theme.theme_type {
68 ConfigurationThemeType::Light => ThemeType::Light,
69 }),
70 theme_mode: if display_configuration
71 .theme
72 .theme_mode
73 .contains(&ConfigurationThemeMode::Auto)
74 {
75 ThemeMode::AUTO
76 } else {
77 ThemeMode::empty()
78 },
79 });
80 }
81
82 default_display_info
83 }
84}
85
86impl DeviceStorageCompatible for DisplayInfo {
87 type Loader = DisplayInfoLoader;
88 const KEY: &'static str = "display_info";
89
90 fn try_deserialize_from(value: &str) -> Result<Self, Error> {
91 Self::extract(value).or_else(|_| DisplayInfoV5::try_deserialize_from(value).map(Self::from))
92 }
93}
94
95impl From<DisplayInfo> for SettingInfo {
96 fn from(info: DisplayInfo) -> SettingInfo {
97 SettingInfo::Brightness(info)
98 }
99}
100
101impl From<&DisplayInfo> for SettingType {
102 fn from(_: &DisplayInfo) -> SettingType {
103 SettingType::Display
104 }
105}
106
107impl From<DisplayInfoV5> for DisplayInfo {
108 fn from(v5: DisplayInfoV5) -> Self {
109 DisplayInfo {
110 auto_brightness: v5.auto_brightness,
111 auto_brightness_value: DEFAULT_AUTO_BRIGHTNESS_VALUE,
112 manual_brightness_value: v5.manual_brightness_value,
113 screen_enabled: v5.screen_enabled,
114 low_light_mode: v5.low_light_mode,
115 theme: v5.theme,
116 }
117 }
118}
119
120#[async_trait(?Send)]
121pub(crate) trait BrightnessManager: Sized {
122 async fn from_client(client: &ClientProxy) -> Result<Self, ControllerError>;
123 async fn update_brightness(
124 &self,
125 info: DisplayInfo,
126 client: &ClientProxy,
127 store: &DeviceStorage,
128 always_send: bool,
131 ) -> SettingHandlerResult;
132}
133
134#[async_trait(?Send)]
135impl BrightnessManager for () {
136 async fn from_client(_: &ClientProxy) -> Result<Self, ControllerError> {
137 Ok(())
138 }
139
140 async fn update_brightness(
143 &self,
144 info: DisplayInfo,
145 client: &ClientProxy,
146 store: &DeviceStorage,
147 _: bool,
148 ) -> SettingHandlerResult {
149 let id = ftrace::Id::new();
150 if !info.is_finite() {
151 return Err(ControllerError::InvalidArgument(
152 SettingType::Display,
153 "display_info".into(),
154 format!("{info:?}").into(),
155 ));
156 }
157 client.storage_write(&store, info, id).await.map(|_| None).map_err(|e| {
158 log::error!("Failed to update display info {e:?}");
159 ControllerError::WriteFailure(SettingType::Display)
160 })
161 }
162}
163
164pub(crate) struct ExternalBrightnessControl {
165 brightness_service: ExternalServiceProxy<BrightnessControlProxy>,
166}
167
168#[async_trait(?Send)]
169impl BrightnessManager for ExternalBrightnessControl {
170 async fn from_client(client: &ClientProxy) -> Result<Self, ControllerError> {
171 client
172 .get_service_context()
173 .connect::<BrightnessControlMarker>()
174 .await
175 .map(|brightness_service| Self { brightness_service })
176 .map_err(|_| {
177 ControllerError::InitFailure("could not connect to brightness service".into())
178 })
179 }
180
181 async fn update_brightness(
182 &self,
183 info: DisplayInfo,
184 client: &ClientProxy,
185 store: &DeviceStorage,
186 always_send: bool,
187 ) -> SettingHandlerResult {
188 let id = ftrace::Id::new();
189 if !info.is_finite() {
190 return Err(ControllerError::InvalidArgument(
191 SettingType::Display,
192 "display_info".into(),
193 format!("{info:?}").into(),
194 ));
195 }
196 let update_state =
197 client.storage_write::<DisplayInfo>(&store, info.clone(), id).await.map_err(|e| {
198 log::error!("Failed to update display info {e:?}");
199 ControllerError::WriteFailure(SettingType::Display)
200 })?;
201 if update_state == UpdateState::Unchanged && !always_send {
202 return Ok(None);
203 }
204
205 if info.auto_brightness {
206 call!(self.brightness_service => set_auto_brightness())
207 } else {
208 call!(self.brightness_service => set_manual_brightness(info.manual_brightness_value))
209 }
210 .map(|_| None)
211 .map_err(|e| {
212 ControllerError::ExternalFailure(
213 SettingType::Display,
214 "brightness_service".into(),
215 "set_brightness".into(),
216 format!("{e:?}").into(),
217 )
218 })
219 }
220}
221
222pub(crate) struct DisplayController<F, T = ()>
223where
224 T: BrightnessManager,
225{
226 brightness_manager: T,
227 client: ClientProxy,
228 store: Rc<DeviceStorage>,
229 _phantom: PhantomData<F>,
230}
231
232impl<F, T> StorageAccess for DisplayController<F, T>
233where
234 T: BrightnessManager,
235{
236 type Storage = DeviceStorage;
237 type Data = DisplayInfo;
238 const STORAGE_KEY: &'static str = DisplayInfo::KEY;
239}
240
241#[async_trait(?Send)]
242impl<F, T> data_controller::CreateWithAsync for DisplayController<F, T>
243where
244 T: BrightnessManager,
245 F: StorageFactory<Storage = DeviceStorage>,
246{
247 type Data = Rc<F>;
248 async fn create_with(client: ClientProxy, data: Self::Data) -> Result<Self, ControllerError> {
249 let brightness_manager = <T as BrightnessManager>::from_client(&client).await?;
250 let store = data.get_store().await;
251 Ok(Self { brightness_manager, client, store, _phantom: PhantomData })
252 }
253}
254
255#[async_trait(?Send)]
256impl<F, T> controller::Handle for DisplayController<F, T>
257where
258 T: BrightnessManager,
259{
260 async fn handle(&self, request: Request) -> Option<SettingHandlerResult> {
261 match request {
262 Request::Restore => {
263 let display_info = self.store.get::<DisplayInfo>().await;
264 assert!(display_info.is_finite());
265
266 Some(
268 self.brightness_manager
269 .update_brightness(display_info, &self.client, &self.store, true)
270 .await,
271 )
272 }
273 Request::SetDisplayInfo(mut set_display_info) => {
274 let display_info = self.store.get::<DisplayInfo>().await;
275 assert!(display_info.is_finite());
276
277 if let Some(theme) = set_display_info.theme {
278 set_display_info.theme = self.build_theme(theme, &display_info);
279 }
280
281 Some(
282 self.brightness_manager
283 .update_brightness(
284 display_info.merge(set_display_info),
285 &self.client,
286 &self.store,
287 false,
288 )
289 .await,
290 )
291 }
292 Request::Get => {
293 Some(Ok(Some(SettingInfo::Brightness(self.store.get::<DisplayInfo>().await))))
294 }
295 _ => None,
296 }
297 }
298}
299
300impl<F, T> DisplayController<F, T>
301where
302 T: BrightnessManager,
303{
304 fn build_theme(&self, incoming_theme: Theme, display_info: &DisplayInfo) -> Option<Theme> {
305 let existing_theme_type = display_info.theme.and_then(|theme| theme.theme_type);
306 let new_theme_type = incoming_theme.theme_type.or(existing_theme_type);
307
308 ThemeBuilder::new()
309 .set_theme_type(new_theme_type)
310 .set_theme_mode(incoming_theme.theme_mode)
311 .build()
312 }
313}
314
315#[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize)]
318pub struct DisplayInfoV1 {
319 pub manual_brightness_value: f32,
321 pub auto_brightness: bool,
322 pub low_light_mode: LowLightMode,
323}
324
325impl DisplayInfoV1 {
326 const fn new(
327 auto_brightness: bool,
328 manual_brightness_value: f32,
329 low_light_mode: LowLightMode,
330 ) -> DisplayInfoV1 {
331 DisplayInfoV1 { manual_brightness_value, auto_brightness, low_light_mode }
332 }
333}
334
335impl DeviceStorageCompatible for DisplayInfoV1 {
336 type Loader = NoneT;
337 const KEY: &'static str = "display_infoV1";
338}
339
340impl Default for DisplayInfoV1 {
341 fn default() -> Self {
342 DisplayInfoV1::new(
343 false, DEFAULT_MANUAL_BRIGHTNESS_VALUE, LowLightMode::Disable, )
347 }
348}
349
350#[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize)]
353pub struct DisplayInfoV2 {
354 pub manual_brightness_value: f32,
355 pub auto_brightness: bool,
356 pub low_light_mode: LowLightMode,
357 pub theme_mode: ThemeModeV1,
358}
359
360impl DisplayInfoV2 {
361 const fn new(
362 auto_brightness: bool,
363 manual_brightness_value: f32,
364 low_light_mode: LowLightMode,
365 theme_mode: ThemeModeV1,
366 ) -> DisplayInfoV2 {
367 DisplayInfoV2 { manual_brightness_value, auto_brightness, low_light_mode, theme_mode }
368 }
369}
370
371impl DeviceStorageCompatible for DisplayInfoV2 {
372 type Loader = NoneT;
373 const KEY: &'static str = "display_infoV2";
374
375 fn try_deserialize_from(value: &str) -> Result<Self, Error> {
376 Self::extract(value).or_else(|_| DisplayInfoV1::try_deserialize_from(value).map(Self::from))
377 }
378}
379
380impl Default for DisplayInfoV2 {
381 fn default() -> Self {
382 DisplayInfoV2::new(
383 false, DEFAULT_MANUAL_BRIGHTNESS_VALUE, LowLightMode::Disable, ThemeModeV1::Unknown, )
388 }
389}
390
391impl From<DisplayInfoV1> for DisplayInfoV2 {
392 fn from(v1: DisplayInfoV1) -> Self {
393 DisplayInfoV2 {
394 auto_brightness: v1.auto_brightness,
395 manual_brightness_value: v1.manual_brightness_value,
396 low_light_mode: v1.low_light_mode,
397 theme_mode: ThemeModeV1::Unknown,
398 }
399 }
400}
401
402#[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize)]
403pub enum ThemeModeV1 {
404 Unknown,
405 Default,
406 Light,
407 Dark,
408 Auto,
410}
411
412impl From<ThemeModeV1> for ThemeType {
413 fn from(theme_mode_v1: ThemeModeV1) -> Self {
414 match theme_mode_v1 {
415 ThemeModeV1::Default => ThemeType::Default,
416 ThemeModeV1::Light => ThemeType::Light,
417 ThemeModeV1::Dark => ThemeType::Dark,
418 ThemeModeV1::Unknown | ThemeModeV1::Auto => ThemeType::Unknown,
420 }
421 }
422}
423
424#[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize)]
425pub struct DisplayInfoV3 {
426 pub manual_brightness_value: f32,
428 pub auto_brightness: bool,
429 pub screen_enabled: bool,
430 pub low_light_mode: LowLightMode,
431 pub theme_mode: ThemeModeV1,
432}
433
434impl DisplayInfoV3 {
435 const fn new(
436 auto_brightness: bool,
437 manual_brightness_value: f32,
438 screen_enabled: bool,
439 low_light_mode: LowLightMode,
440 theme_mode: ThemeModeV1,
441 ) -> DisplayInfoV3 {
442 DisplayInfoV3 {
443 manual_brightness_value,
444 auto_brightness,
445 screen_enabled,
446 low_light_mode,
447 theme_mode,
448 }
449 }
450}
451
452impl DeviceStorageCompatible for DisplayInfoV3 {
453 type Loader = NoneT;
454 const KEY: &'static str = "display_info";
455
456 fn try_deserialize_from(value: &str) -> Result<Self, Error> {
457 Self::extract(value).or_else(|_| DisplayInfoV2::try_deserialize_from(value).map(Self::from))
458 }
459}
460
461impl Default for DisplayInfoV3 {
462 fn default() -> Self {
463 DisplayInfoV3::new(
464 false, DEFAULT_MANUAL_BRIGHTNESS_VALUE, true, LowLightMode::Disable, ThemeModeV1::Unknown, )
470 }
471}
472
473impl From<DisplayInfoV2> for DisplayInfoV3 {
474 fn from(v2: DisplayInfoV2) -> Self {
475 DisplayInfoV3 {
476 auto_brightness: v2.auto_brightness,
477 manual_brightness_value: v2.manual_brightness_value,
478 screen_enabled: true,
479 low_light_mode: v2.low_light_mode,
480 theme_mode: v2.theme_mode,
481 }
482 }
483}
484
485#[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize)]
486pub struct DisplayInfoV4 {
487 pub manual_brightness_value: f32,
489 pub auto_brightness: bool,
490 pub screen_enabled: bool,
491 pub low_light_mode: LowLightMode,
492 pub theme_type: ThemeType,
493}
494
495impl DisplayInfoV4 {
496 const fn new(
497 auto_brightness: bool,
498 manual_brightness_value: f32,
499 screen_enabled: bool,
500 low_light_mode: LowLightMode,
501 theme_type: ThemeType,
502 ) -> DisplayInfoV4 {
503 DisplayInfoV4 {
504 manual_brightness_value,
505 auto_brightness,
506 screen_enabled,
507 low_light_mode,
508 theme_type,
509 }
510 }
511}
512
513impl From<DisplayInfoV3> for DisplayInfoV4 {
514 fn from(v3: DisplayInfoV3) -> Self {
515 DisplayInfoV4 {
516 auto_brightness: v3.auto_brightness,
517 manual_brightness_value: v3.manual_brightness_value,
518 screen_enabled: v3.screen_enabled,
519 low_light_mode: v3.low_light_mode,
520 theme_type: ThemeType::from(v3.theme_mode),
523 }
524 }
525}
526
527impl DeviceStorageCompatible for DisplayInfoV4 {
528 type Loader = NoneT;
529 const KEY: &'static str = "display_info";
530
531 fn try_deserialize_from(value: &str) -> Result<Self, Error> {
532 Self::extract(value).or_else(|_| DisplayInfoV3::try_deserialize_from(value).map(Self::from))
533 }
534}
535
536impl Default for DisplayInfoV4 {
537 fn default() -> Self {
538 DisplayInfoV4::new(
539 false, DEFAULT_MANUAL_BRIGHTNESS_VALUE, true, LowLightMode::Disable, ThemeType::Unknown, )
545 }
546}
547
548#[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize)]
549#[serde(deny_unknown_fields)]
550pub struct DisplayInfoV5 {
551 pub manual_brightness_value: f32,
553 pub auto_brightness: bool,
554 pub screen_enabled: bool,
555 pub low_light_mode: LowLightMode,
556 pub theme: Option<Theme>,
557}
558
559impl DisplayInfoV5 {
560 const fn new(
561 auto_brightness: bool,
562 manual_brightness_value: f32,
563 screen_enabled: bool,
564 low_light_mode: LowLightMode,
565 theme: Option<Theme>,
566 ) -> DisplayInfoV5 {
567 DisplayInfoV5 {
568 manual_brightness_value,
569 auto_brightness,
570 screen_enabled,
571 low_light_mode,
572 theme,
573 }
574 }
575}
576
577impl From<DisplayInfoV4> for DisplayInfoV5 {
578 fn from(v4: DisplayInfoV4) -> Self {
579 DisplayInfoV5 {
580 auto_brightness: v4.auto_brightness,
581 manual_brightness_value: v4.manual_brightness_value,
582 screen_enabled: v4.screen_enabled,
583 low_light_mode: v4.low_light_mode,
584 theme: Some(Theme::new(Some(v4.theme_type), ThemeMode::empty())),
586 }
587 }
588}
589
590impl DeviceStorageCompatible for DisplayInfoV5 {
591 type Loader = NoneT;
592 const KEY: &'static str = "display_info";
593
594 fn try_deserialize_from(value: &str) -> Result<Self, Error> {
595 Self::extract(value).or_else(|_| DisplayInfoV4::try_deserialize_from(value).map(Self::from))
596 }
597}
598
599impl Default for DisplayInfoV5 {
600 fn default() -> Self {
601 DisplayInfoV5::new(
602 false, DEFAULT_MANUAL_BRIGHTNESS_VALUE, true, LowLightMode::Disable, Some(Theme::new(Some(ThemeType::Unknown), ThemeMode::empty())), )
608 }
609}
610
611#[cfg(test)]
612mod tests {
613 use super::*;
614
615 #[fuchsia::test]
616 fn test_display_migration_v1_to_v2() {
617 let v1 = DisplayInfoV1 {
618 manual_brightness_value: 0.6,
619 auto_brightness: true,
620 low_light_mode: LowLightMode::Enable,
621 };
622
623 let serialized_v1 = v1.serialize_to();
624 let v2 = DisplayInfoV2::try_deserialize_from(&serialized_v1)
625 .expect("deserialization should succeed");
626
627 assert_eq!(
628 v2,
629 DisplayInfoV2 {
630 manual_brightness_value: v1.manual_brightness_value,
631 auto_brightness: v1.auto_brightness,
632 low_light_mode: v1.low_light_mode,
633 theme_mode: DisplayInfoV2::default().theme_mode,
634 }
635 );
636 }
637
638 #[fuchsia::test]
639 fn test_display_migration_v2_to_v3() {
640 let v2 = DisplayInfoV2 {
641 manual_brightness_value: 0.7,
642 auto_brightness: true,
643 low_light_mode: LowLightMode::Enable,
644 theme_mode: ThemeModeV1::Default,
645 };
646
647 let serialized_v2 = v2.serialize_to();
648 let v3 = DisplayInfoV3::try_deserialize_from(&serialized_v2)
649 .expect("deserialization should succeed");
650
651 assert_eq!(
652 v3,
653 DisplayInfoV3 {
654 manual_brightness_value: v2.manual_brightness_value,
655 auto_brightness: v2.auto_brightness,
656 screen_enabled: DisplayInfoV3::default().screen_enabled,
657 low_light_mode: v2.low_light_mode,
658 theme_mode: v2.theme_mode,
659 }
660 );
661 }
662
663 #[fuchsia::test]
664 fn test_display_migration_v3_to_v4() {
665 let v3 = DisplayInfoV3 {
666 manual_brightness_value: 0.7,
667 auto_brightness: true,
668 low_light_mode: LowLightMode::Enable,
669 theme_mode: ThemeModeV1::Light,
670 screen_enabled: false,
671 };
672
673 let serialized_v3 = v3.serialize_to();
674 let v4 = DisplayInfoV4::try_deserialize_from(&serialized_v3)
675 .expect("deserialization should succeed");
676
677 assert_eq!(
679 v4,
680 DisplayInfoV4 {
681 manual_brightness_value: v3.manual_brightness_value,
682 auto_brightness: v3.auto_brightness,
683 low_light_mode: v3.low_light_mode,
684 theme_type: ThemeType::Light,
685 screen_enabled: v3.screen_enabled,
686 }
687 );
688 }
689
690 #[fuchsia::test]
691 fn test_display_migration_v4_to_v5() {
692 let v4 = DisplayInfoV4 {
693 manual_brightness_value: 0.7,
694 auto_brightness: true,
695 low_light_mode: LowLightMode::Enable,
696 theme_type: ThemeType::Dark,
697 screen_enabled: false,
698 };
699
700 let serialized_v4 = v4.serialize_to();
701 let v5 = DisplayInfoV5::try_deserialize_from(&serialized_v4)
702 .expect("deserialization should succeed");
703
704 assert_eq!(
705 v5,
706 DisplayInfoV5 {
707 manual_brightness_value: v4.manual_brightness_value,
708 auto_brightness: v4.auto_brightness,
709 low_light_mode: v4.low_light_mode,
710 theme: Some(Theme::new(Some(v4.theme_type), ThemeMode::empty())),
711 screen_enabled: v4.screen_enabled,
712 }
713 );
714 }
715
716 #[fuchsia::test]
717 fn test_display_migration_v1_to_current() {
718 let v1 = DisplayInfoV1 {
719 manual_brightness_value: 0.6,
720 auto_brightness: true,
721 low_light_mode: LowLightMode::Enable,
722 };
723
724 let serialized_v1 = v1.serialize_to();
725 let current = DisplayInfo::try_deserialize_from(&serialized_v1)
726 .expect("deserialization should succeed");
727
728 assert_eq!(
729 current,
730 DisplayInfo {
731 manual_brightness_value: v1.manual_brightness_value,
732 auto_brightness: v1.auto_brightness,
733 low_light_mode: v1.low_light_mode,
734 theme: Some(Theme::new(Some(ThemeType::Unknown), ThemeMode::empty())),
735 screen_enabled: DisplayInfoV3::default().screen_enabled,
737 auto_brightness_value: DEFAULT_DISPLAY_INFO.auto_brightness_value,
738 }
739 );
740 }
741
742 #[fuchsia::test]
743 fn test_display_migration_v2_to_current() {
744 let v2 = DisplayInfoV2 {
745 manual_brightness_value: 0.6,
746 auto_brightness: true,
747 low_light_mode: LowLightMode::Enable,
748 theme_mode: ThemeModeV1::Light,
749 };
750
751 let serialized_v2 = v2.serialize_to();
752 let current = DisplayInfo::try_deserialize_from(&serialized_v2)
753 .expect("deserialization should succeed");
754
755 assert_eq!(
756 current,
757 DisplayInfo {
758 manual_brightness_value: v2.manual_brightness_value,
759 auto_brightness: v2.auto_brightness,
760 low_light_mode: v2.low_light_mode,
761 theme: Some(Theme::new(Some(ThemeType::Light), ThemeMode::empty())),
762 screen_enabled: DisplayInfoV3::default().screen_enabled,
764 auto_brightness_value: DEFAULT_DISPLAY_INFO.auto_brightness_value,
765 }
766 );
767 }
768
769 #[fuchsia::test]
770 fn test_display_migration_v3_to_current() {
771 let v3 = DisplayInfoV3 {
772 manual_brightness_value: 0.6,
773 auto_brightness: true,
774 low_light_mode: LowLightMode::Enable,
775 theme_mode: ThemeModeV1::Light,
776 screen_enabled: false,
777 };
778
779 let serialized_v3 = v3.serialize_to();
780 let current = DisplayInfo::try_deserialize_from(&serialized_v3)
781 .expect("deserialization should succeed");
782
783 assert_eq!(
784 current,
785 DisplayInfo {
786 manual_brightness_value: v3.manual_brightness_value,
787 auto_brightness: v3.auto_brightness,
788 low_light_mode: v3.low_light_mode,
789 theme: Some(Theme::new(Some(ThemeType::Light), ThemeMode::empty())),
790 screen_enabled: v3.screen_enabled,
792 auto_brightness_value: DEFAULT_DISPLAY_INFO.auto_brightness_value,
793 }
794 );
795 }
796
797 #[fuchsia::test]
798 fn test_display_migration_v4_to_current() {
799 let v4 = DisplayInfoV4 {
800 manual_brightness_value: 0.6,
801 auto_brightness: true,
802 low_light_mode: LowLightMode::Enable,
803 theme_type: ThemeType::Light,
804 screen_enabled: false,
805 };
806
807 let serialized_v4 = v4.serialize_to();
808 let current = DisplayInfo::try_deserialize_from(&serialized_v4)
809 .expect("deserialization should succeed");
810
811 assert_eq!(
812 current,
813 DisplayInfo {
814 manual_brightness_value: v4.manual_brightness_value,
815 auto_brightness: v4.auto_brightness,
816 low_light_mode: v4.low_light_mode,
817 theme: Some(Theme::new(Some(ThemeType::Light), ThemeMode::empty())),
818 screen_enabled: v4.screen_enabled,
819 auto_brightness_value: DEFAULT_DISPLAY_INFO.auto_brightness_value,
820 }
821 );
822 }
823
824 #[fuchsia::test]
825 fn test_display_migration_v5_to_current() {
826 let v5 = DisplayInfoV5 {
827 manual_brightness_value: 0.6,
828 auto_brightness: true,
829 low_light_mode: LowLightMode::Enable,
830 theme: Some(Theme::new(Some(ThemeType::Light), ThemeMode::AUTO)),
831 screen_enabled: false,
832 };
833
834 let serialized_v5 = v5.serialize_to();
835 let current = DisplayInfo::try_deserialize_from(&serialized_v5)
836 .expect("deserialization should succeed");
837
838 assert_eq!(
839 current,
840 DisplayInfo {
841 manual_brightness_value: v5.manual_brightness_value,
842 auto_brightness: v5.auto_brightness,
843 low_light_mode: v5.low_light_mode,
844 theme: Some(Theme::new(Some(ThemeType::Light), ThemeMode::AUTO)),
845 screen_enabled: v5.screen_enabled,
846 auto_brightness_value: DEFAULT_DISPLAY_INFO.auto_brightness_value,
847 }
848 );
849 }
850}