blob: 30d684af31998cd5404105679a4da990f39a8dd2 [file] [log] [blame]
// 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 crate::agent::storage::device_storage::DeviceStorageCompatible;
use crate::audio::types::{
AudioInfo, AudioInputInfo, AudioSettingSource, AudioStream, AudioStreamType,
};
use crate::base::SettingInfo;
use crate::config::default_settings::DefaultSetting;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Mutex;
const DEFAULT_MIC_MUTE: bool = false;
const DEFAULT_VOLUME_LEVEL: f32 = 0.5;
const DEFAULT_VOLUME_MUTED: bool = false;
const DEFAULT_STREAMS: [AudioStream; 5] = [
create_default_audio_stream(AudioStreamType::Background),
create_default_audio_stream(AudioStreamType::Media),
create_default_audio_stream(AudioStreamType::Interruption),
create_default_audio_stream(AudioStreamType::SystemAgent),
create_default_audio_stream(AudioStreamType::Communication),
];
/// A mapping from stream type to an arbitrary numerical value. This number will
/// change from the number sent in the previous update if the stream type's
/// volume has changed.
pub type ModifiedCounters = HashMap<AudioStreamType, usize>;
const DEFAULT_AUDIO_INPUT_INFO: AudioInputInfo = AudioInputInfo { mic_mute: DEFAULT_MIC_MUTE };
const DEFAULT_AUDIO_INFO: AudioInfo = AudioInfo {
streams: DEFAULT_STREAMS,
input: DEFAULT_AUDIO_INPUT_INFO,
modified_counters: None,
};
lazy_static! {
pub(crate) static ref AUDIO_DEFAULT_SETTINGS: Mutex<DefaultSetting<AudioInfo, &'static str>> =
Mutex::new(DefaultSetting::new(
Some(DEFAULT_AUDIO_INFO),
"/config/data/audio_config_data.json",
));
}
pub(crate) fn create_default_modified_counters() -> ModifiedCounters {
IntoIterator::into_iter([
AudioStreamType::Background,
AudioStreamType::Media,
AudioStreamType::Interruption,
AudioStreamType::SystemAgent,
AudioStreamType::Communication,
])
.map(|stream_type| (stream_type, 0))
.collect()
}
pub(crate) const fn create_default_audio_stream(stream_type: AudioStreamType) -> AudioStream {
AudioStream {
stream_type,
source: AudioSettingSource::User,
user_volume_level: DEFAULT_VOLUME_LEVEL,
user_volume_muted: DEFAULT_VOLUME_MUTED,
}
}
pub(crate) fn default_audio_info() -> AudioInfo {
AUDIO_DEFAULT_SETTINGS
.lock()
.unwrap()
.get_cached_value()
.expect("invalid audio default settings")
.expect("no audio default settings")
}
/// The following struct should never be modified. It represents an old
/// version of the audio settings.
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct AudioInfoV1 {
pub streams: [AudioStream; 5],
pub input: AudioInputInfo,
pub modified_timestamps: Option<HashMap<AudioStreamType, String>>,
}
impl DeviceStorageCompatible for AudioInfoV1 {
const KEY: &'static str = "audio_info";
fn default_value() -> Self {
let stream_types = [
create_default_audio_stream(AudioStreamType::Background),
create_default_audio_stream(AudioStreamType::Media),
create_default_audio_stream(AudioStreamType::Interruption),
create_default_audio_stream(AudioStreamType::SystemAgent),
create_default_audio_stream(AudioStreamType::Communication),
];
AudioInfoV1 {
streams: stream_types,
input: AudioInputInfo { mic_mute: false },
modified_timestamps: None,
}
}
}
impl DeviceStorageCompatible for AudioInfo {
const KEY: &'static str = "audio_info";
fn default_value() -> Self {
default_audio_info()
}
fn deserialize_from(value: &str) -> Self {
Self::extract(&value).unwrap_or_else(|_| Self::from(AudioInfoV1::deserialize_from(&value)))
}
}
impl From<AudioInfo> for SettingInfo {
fn from(audio: AudioInfo) -> SettingInfo {
SettingInfo::Audio(audio)
}
}
impl From<AudioInfoV1> for AudioInfo {
fn from(v1: AudioInfoV1) -> Self {
AudioInfo {
streams: v1.streams,
input: v1.input,
modified_counters: Some(create_default_modified_counters()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
const CONFIG_AUDIO_INFO: AudioInfo = AudioInfo {
streams: [
AudioStream {
stream_type: AudioStreamType::Background,
source: AudioSettingSource::System,
user_volume_level: 0.6,
user_volume_muted: true,
},
AudioStream {
stream_type: AudioStreamType::Media,
source: AudioSettingSource::System,
user_volume_level: 0.7,
user_volume_muted: true,
},
AudioStream {
stream_type: AudioStreamType::Interruption,
source: AudioSettingSource::System,
user_volume_level: 0.2,
user_volume_muted: true,
},
AudioStream {
stream_type: AudioStreamType::SystemAgent,
source: AudioSettingSource::User,
user_volume_level: 0.3,
user_volume_muted: true,
},
AudioStream {
stream_type: AudioStreamType::Communication,
source: AudioSettingSource::User,
user_volume_level: 0.4,
user_volume_muted: false,
},
],
input: AudioInputInfo { mic_mute: true },
modified_counters: None,
};
#[fuchsia_async::run_until_stalled(test)]
async fn test_audio_config() {
let settings = default_audio_info();
assert_eq!(CONFIG_AUDIO_INFO, settings);
}
#[test]
fn test_audio_info_migration_v1_to_current() {
let mut v1 = AudioInfoV1::default_value();
let updated_mic_mute_val = !v1.input.mic_mute;
v1.input.mic_mute = updated_mic_mute_val;
let serialized_v1 = v1.serialize_to();
let current = AudioInfo::deserialize_from(&serialized_v1);
assert_eq!(current.input.mic_mute, updated_mic_mute_val);
}
}