settings_do_not_disturb/
do_not_disturb_controller.rs1use crate::do_not_disturb_fidl_handler::Publisher;
6use crate::types::DoNotDisturbInfo;
7use anyhow::{Context, Error};
8use fuchsia_async as fasync;
9use futures::StreamExt;
10use futures::channel::mpsc::UnboundedReceiver;
11use futures::channel::oneshot::Sender;
12use settings_common::inspect::event::{ResponseType, SettingValuePublisher};
13use settings_storage::UpdateState;
14use settings_storage::device_storage::{DeviceStorage, DeviceStorageCompatible};
15use settings_storage::storage_factory::{NoneT, StorageAccess, StorageFactory};
16use std::rc::Rc;
17
18impl DeviceStorageCompatible for DoNotDisturbInfo {
19 type Loader = NoneT;
20 const KEY: &'static str = "do_not_disturb_info";
21}
22
23impl Default for DoNotDisturbInfo {
24 fn default() -> Self {
25 DoNotDisturbInfo::new(false, false)
26 }
27}
28
29impl StorageAccess for DoNotDisturbController {
30 type Storage = DeviceStorage;
31 type Data = DoNotDisturbInfo;
32 const STORAGE_KEY: &'static str = DoNotDisturbInfo::KEY;
33}
34
35#[derive(thiserror::Error, Debug)]
36pub(crate) enum DoNotDisturbError {
37 #[error("Write failed for DoNotDisturb: {0:?}")]
38 WriteFailure(Error),
39}
40
41impl From<&DoNotDisturbError> for ResponseType {
42 fn from(error: &DoNotDisturbError) -> Self {
43 match error {
44 DoNotDisturbError::WriteFailure(..) => ResponseType::StorageFailure,
45 }
46 }
47}
48
49pub(crate) enum Request {
50 Set(DoNotDisturbInfo, Sender<Result<(), DoNotDisturbError>>),
51}
52
53pub struct DoNotDisturbController {
54 store: Rc<DeviceStorage>,
55 publisher: Option<Publisher>,
56 setting_value_publisher: SettingValuePublisher<DoNotDisturbInfo>,
57}
58
59impl DoNotDisturbController {
60 pub(crate) async fn new<F>(
61 storage_factory: Rc<F>,
62 setting_value_publisher: SettingValuePublisher<DoNotDisturbInfo>,
63 ) -> DoNotDisturbController
64 where
65 F: StorageFactory<Storage = DeviceStorage>,
66 {
67 Self { store: storage_factory.get_store().await, publisher: None, setting_value_publisher }
68 }
69
70 pub(crate) fn register_publisher(&mut self, publisher: Publisher) {
71 self.publisher = Some(publisher);
72 }
73
74 fn publish(&self, info: DoNotDisturbInfo) {
75 let _ = self.setting_value_publisher.publish(&info);
76 if let Some(publisher) = self.publisher.as_ref() {
77 publisher.set(info);
78 }
79 }
80
81 pub(crate) async fn handle(
82 self,
83 mut request_rx: UnboundedReceiver<Request>,
84 ) -> fasync::Task<()> {
85 fasync::Task::local(async move {
86 while let Some(request) = request_rx.next().await {
87 let Request::Set(info, tx) = request;
88 let res = self.set(info).await.map(|info| {
89 if let Some(info) = info {
90 self.publish(info);
91 }
92 });
93 let _ = tx.send(res);
94 }
95 })
96 }
97
98 pub(crate) async fn restore(&self) -> DoNotDisturbInfo {
99 self.store.get::<DoNotDisturbInfo>().await
100 }
101
102 async fn set(
103 &self,
104 dnd_info: DoNotDisturbInfo,
105 ) -> Result<Option<DoNotDisturbInfo>, DoNotDisturbError> {
106 let mut stored_value = self.store.get::<DoNotDisturbInfo>().await;
107 if dnd_info.user_dnd.is_some() {
108 stored_value.user_dnd = dnd_info.user_dnd;
109 }
110 if dnd_info.night_mode_dnd.is_some() {
111 stored_value.night_mode_dnd = dnd_info.night_mode_dnd;
112 }
113 self.store
114 .write(&stored_value)
115 .await
116 .map(|state| (UpdateState::Updated == state).then_some(stored_value))
117 .context("writing do not disturb to storage")
118 .map_err(DoNotDisturbError::WriteFailure)
119 }
120}