Skip to main content

settings_do_not_disturb/
do_not_disturb_controller.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.
4
5use 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}