settings/audio/
audio_default_settings.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::audio::types::{
6    AudioInfo, AudioSettingSource, AudioStream, AudioStreamType, AUDIO_STREAM_TYPE_COUNT,
7};
8use crate::base::SettingInfo;
9use settings_common::config::default_settings::DefaultSetting;
10use settings_common::inspect::config_logger::InspectConfigLogger;
11use settings_storage::storage_factory::DefaultLoader;
12use std::collections::HashMap;
13use std::rc::Rc;
14use std::sync::Mutex;
15
16const DEFAULT_VOLUME_LEVEL: f32 = 0.5;
17const DEFAULT_VOLUME_MUTED: bool = false;
18
19const DEFAULT_STREAMS: [AudioStream; AUDIO_STREAM_TYPE_COUNT] = [
20    create_default_audio_stream(AudioStreamType::Background),
21    create_default_audio_stream(AudioStreamType::Media),
22    create_default_audio_stream(AudioStreamType::Interruption),
23    create_default_audio_stream(AudioStreamType::SystemAgent),
24    create_default_audio_stream(AudioStreamType::Communication),
25    create_default_audio_stream(AudioStreamType::Accessibility),
26];
27
28const DEFAULT_AUDIO_INFO: AudioInfo =
29    AudioInfo { streams: DEFAULT_STREAMS, modified_counters: None };
30
31/// A mapping from stream type to an arbitrary numerical value. This number will
32/// change from the number sent in the previous update if the stream type's
33/// volume has changed.
34pub type ModifiedCounters = HashMap<AudioStreamType, usize>;
35
36pub(crate) fn create_default_modified_counters() -> ModifiedCounters {
37    IntoIterator::into_iter([
38        AudioStreamType::Background,
39        AudioStreamType::Media,
40        AudioStreamType::Interruption,
41        AudioStreamType::SystemAgent,
42        AudioStreamType::Communication,
43        AudioStreamType::Accessibility,
44    ])
45    .map(|stream_type| (stream_type, 0))
46    .collect()
47}
48
49pub(crate) const fn create_default_audio_stream(stream_type: AudioStreamType) -> AudioStream {
50    AudioStream {
51        stream_type,
52        source: AudioSettingSource::User,
53        user_volume_level: DEFAULT_VOLUME_LEVEL,
54        user_volume_muted: DEFAULT_VOLUME_MUTED,
55    }
56}
57
58pub fn build_audio_default_settings(
59    config_logger: Rc<Mutex<InspectConfigLogger>>,
60) -> DefaultSetting<AudioInfo, &'static str> {
61    DefaultSetting::new(
62        Some(DEFAULT_AUDIO_INFO),
63        "/config/data/audio_config_data.json",
64        config_logger,
65    )
66}
67
68/// Returns a default audio [`AudioInfo`] that is derived from
69/// [`DEFAULT_AUDIO_INFO`] with any fields specified in the
70/// audio configuration set.
71///
72/// [`DEFAULT_AUDIO_INFO`]: static@DEFAULT_AUDIO_INFO
73#[derive(Clone)]
74pub struct AudioInfoLoader {
75    audio_default_settings: Rc<Mutex<DefaultSetting<AudioInfo, &'static str>>>,
76}
77
78impl AudioInfoLoader {
79    pub(crate) fn new(audio_default_settings: DefaultSetting<AudioInfo, &'static str>) -> Self {
80        Self { audio_default_settings: Rc::new(Mutex::new(audio_default_settings)) }
81    }
82}
83
84impl DefaultLoader for AudioInfoLoader {
85    type Result = AudioInfo;
86
87    fn default_value(&self) -> Self::Result {
88        let mut default_audio_info: AudioInfo = DEFAULT_AUDIO_INFO.clone();
89
90        if let Ok(Some(audio_configuration)) =
91            self.audio_default_settings.lock().unwrap().get_cached_value()
92        {
93            default_audio_info.streams = audio_configuration.streams;
94        }
95        default_audio_info
96    }
97}
98
99impl From<AudioInfo> for SettingInfo {
100    fn from(audio: AudioInfo) -> SettingInfo {
101        SettingInfo::Audio(audio)
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108    use crate::audio::types::{AudioInfoV1, AudioInfoV2, AudioInfoV3};
109    use fuchsia_async::TestExecutor;
110    use fuchsia_inspect::component;
111    use settings_storage::device_storage::DeviceStorageCompatible;
112    use settings_test_common::helpers::move_executor_forward_and_get;
113
114    const CONFIG_AUDIO_INFO: AudioInfo = AudioInfo {
115        streams: [
116            AudioStream {
117                stream_type: AudioStreamType::Background,
118                source: AudioSettingSource::System,
119                user_volume_level: 0.6,
120                user_volume_muted: true,
121            },
122            AudioStream {
123                stream_type: AudioStreamType::Media,
124                source: AudioSettingSource::System,
125                user_volume_level: 0.7,
126                user_volume_muted: true,
127            },
128            AudioStream {
129                stream_type: AudioStreamType::Interruption,
130                source: AudioSettingSource::System,
131                user_volume_level: 0.2,
132                user_volume_muted: true,
133            },
134            AudioStream {
135                stream_type: AudioStreamType::SystemAgent,
136                source: AudioSettingSource::User,
137                user_volume_level: 0.3,
138                user_volume_muted: true,
139            },
140            AudioStream {
141                stream_type: AudioStreamType::Communication,
142                source: AudioSettingSource::User,
143                user_volume_level: 0.4,
144                user_volume_muted: false,
145            },
146            AudioStream {
147                stream_type: AudioStreamType::Accessibility,
148                source: AudioSettingSource::User,
149                user_volume_level: 0.35,
150                user_volume_muted: false,
151            },
152        ],
153        modified_counters: None,
154    };
155
156    /// Construct default audio settings and its dependencies.
157    fn make_default_settings() -> DefaultSetting<AudioInfo, &'static str> {
158        let config_logger =
159            Rc::new(Mutex::new(InspectConfigLogger::new(component::inspector().root())));
160        build_audio_default_settings(config_logger)
161    }
162
163    /// Load default settings from disk.
164    fn load_default_settings(
165        default_settings: &mut DefaultSetting<AudioInfo, &'static str>,
166    ) -> AudioInfo {
167        default_settings
168            .load_default_value()
169            .expect("if config exists, it should be parseable")
170            .expect("default value should always exist")
171    }
172
173    #[fuchsia::test(allow_stalls = false)]
174    async fn test_audio_config() {
175        let mut default_settings = make_default_settings();
176        let current_from_storage = load_default_settings(&mut default_settings);
177        // Ensure that settings are read from storage.
178        assert_eq!(CONFIG_AUDIO_INFO, current_from_storage);
179    }
180
181    #[fuchsia::test(allow_stalls = false)]
182    async fn test_audio_info_migration_v1_to_v2() {
183        let mut default_settings = make_default_settings();
184        let mut v1_settings =
185            AudioInfoV1::default_value(load_default_settings(&mut default_settings));
186        let updated_mic_mute_val = !v1_settings.input.mic_mute;
187        v1_settings.input.mic_mute = updated_mic_mute_val;
188        v1_settings.streams[0].user_volume_level = 0.9;
189        v1_settings.streams[0].user_volume_muted = false;
190
191        let serialized_v1 = serde_json::to_string(&v1_settings).expect("default should serialize");
192        let v2_from_v1 = AudioInfoV2::try_deserialize_from(&serialized_v1)
193            .expect("deserialization should succeed");
194
195        // Ensure that changes made in v1 are migrated to v2.
196        assert_eq!(v2_from_v1.input.mic_mute, updated_mic_mute_val);
197        assert_eq!(v2_from_v1.streams[0].user_volume_level, 0.9);
198        assert_eq!(v2_from_v1.streams[0].user_volume_muted, false);
199    }
200
201    #[fuchsia::test(allow_stalls = false)]
202    async fn test_audio_info_migration_v2_to_v3() {
203        let mut default_settings = make_default_settings();
204        let mut v2_settings =
205            AudioInfoV1::default_value(load_default_settings(&mut default_settings));
206        v2_settings.streams[0].user_volume_level = 0.9;
207        v2_settings.streams[0].user_volume_muted = false;
208
209        let serialized_v2 = serde_json::to_string(&v2_settings).expect("default should serialize");
210        let v3_from_v2 = AudioInfoV3::try_deserialize_from(&serialized_v2)
211            .expect("deserialization should succeed");
212
213        // Ensure that changes made in v2 are migrated to v3.
214        assert_eq!(v3_from_v2.streams[0].user_volume_level, 0.9);
215        assert_eq!(v3_from_v2.streams[0].user_volume_muted, false);
216    }
217
218    #[fuchsia::test]
219    fn test_audio_info_migration_v3_to_current() {
220        let mut executor = TestExecutor::new_with_fake_time();
221        let mut default_settings = make_default_settings();
222        let current_defaults = load_default_settings(&mut default_settings);
223
224        let mut v3_settings = move_executor_forward_and_get(
225            &mut executor,
226            async { AudioInfoV3::default_value(current_defaults) },
227            "Unable to get V3 default value",
228        );
229        v3_settings.streams[0].user_volume_level = 0.9;
230        v3_settings.streams[0].user_volume_muted = false;
231
232        let serialized_v3 = serde_json::to_string(&v3_settings).expect("default should serialize");
233        let current_from_v3 = AudioInfo::try_deserialize_from(&serialized_v3)
234            .expect("deserialization should succeed");
235
236        // Ensure that changes made in v3 are migrated to current.
237        assert_eq!(current_from_v3.streams[0].user_volume_level, 0.9);
238        assert_eq!(current_from_v3.streams[0].user_volume_muted, false);
239        // Ensure that migrating from v3 picks up a default for the new stream type.
240        assert_eq!(current_from_v3.streams[5], DEFAULT_AUDIO_INFO.streams[5]);
241    }
242
243    #[fuchsia::test]
244    fn test_audio_info_migration_v2_to_current() {
245        let mut executor = TestExecutor::new_with_fake_time();
246        let mut default_settings = make_default_settings();
247        let current_defaults = load_default_settings(&mut default_settings);
248
249        let mut v2_settings = move_executor_forward_and_get(
250            &mut executor,
251            async { AudioInfoV2::default_value(current_defaults) },
252            "Unable to get V2 default value",
253        );
254        let updated_mic_mute_val = !v2_settings.input.mic_mute;
255        v2_settings.input.mic_mute = updated_mic_mute_val;
256        v2_settings.streams[0].user_volume_level = 0.9;
257        v2_settings.streams[0].user_volume_muted = false;
258
259        let serialized_v2 = serde_json::to_string(&v2_settings).expect("default should serialize");
260        let current_from_v2 = AudioInfo::try_deserialize_from(&serialized_v2)
261            .expect("deserialization should succeed");
262
263        // Ensure that changes made in v2 are migrated to current.
264        assert_eq!(current_from_v2.streams[0].user_volume_level, 0.9);
265        assert_eq!(current_from_v2.streams[0].user_volume_muted, false);
266        // Ensure that migrating from v2 picks up a default for the new stream type.
267        assert_eq!(current_from_v2.streams[5], DEFAULT_AUDIO_INFO.streams[5]);
268    }
269
270    #[fuchsia::test]
271    fn test_audio_info_migration_v1_to_current() {
272        let mut executor = TestExecutor::new_with_fake_time();
273        let mut default_settings = make_default_settings();
274        let current_defaults = load_default_settings(&mut default_settings);
275
276        let mut v1_settings = move_executor_forward_and_get(
277            &mut executor,
278            async { AudioInfoV1::default_value(current_defaults) },
279            "Unable to get V1 default value",
280        );
281        let updated_mic_mute_val = !v1_settings.input.mic_mute;
282        v1_settings.input.mic_mute = updated_mic_mute_val;
283        v1_settings.streams[0].user_volume_level = 0.9;
284        v1_settings.streams[0].user_volume_muted = false;
285
286        let serialized_v1 = serde_json::to_string(&v1_settings).expect("default should serialize");
287        let current_from_v1 = AudioInfo::try_deserialize_from(&serialized_v1)
288            .expect("deserialization should succeed");
289
290        // Ensure that changes made in v1 are migrated to current.
291        assert_eq!(current_from_v1.streams[0].user_volume_level, 0.9);
292        assert_eq!(current_from_v1.streams[0].user_volume_muted, false);
293        // Ensure that migrating from v1 picks up a default for the new stream type.
294        assert_eq!(current_from_v1.streams[5], DEFAULT_AUDIO_INFO.streams[5]);
295    }
296}