1use super::AudioInfoLoader;
5use crate::audio::types::{
6 AudioInfo, AudioStream, AudioStreamType, SetAudioStream, AUDIO_STREAM_TYPE_COUNT,
7};
8use crate::audio::{create_default_modified_counters, ModifiedCounters, StreamVolumeControl};
9use crate::base::SettingType;
10use crate::handler::base::Request;
11use crate::handler::setting_handler::persist::{controller as data_controller, ClientProxy};
12use crate::handler::setting_handler::{
13 controller, ControllerError, ControllerStateResult, Event, SettingHandlerResult, State,
14};
15use crate::{trace, trace_guard};
16use async_trait::async_trait;
17use futures::lock::Mutex;
18use settings_storage::device_storage::{DeviceStorage, DeviceStorageCompatible};
19use settings_storage::storage_factory::{DefaultLoader, StorageAccess, StorageFactory};
20use settings_storage::UpdateState;
21use std::collections::HashMap;
22use std::marker::PhantomData;
23use std::rc::Rc;
24use {fuchsia_async as fasync, fuchsia_trace as ftrace};
25
26type VolumeControllerHandle = Rc<Mutex<VolumeController>>;
27
28pub(crate) struct VolumeController {
29 client: ClientProxy,
30 store: Rc<DeviceStorage>,
31 audio_service_connected: bool,
32 stream_volume_controls: HashMap<AudioStreamType, StreamVolumeControl>,
33 modified_counters: ModifiedCounters,
34 audio_info_loader: AudioInfoLoader,
35}
36
37enum UpdateFrom {
38 AudioInfo(AudioInfo),
39 NewStreams(Vec<SetAudioStream>),
40}
41
42impl VolumeController {
43 async fn create_with(
44 client: ClientProxy,
45 audio_info_loader: AudioInfoLoader,
46 storage_factory: Rc<impl StorageFactory<Storage = DeviceStorage>>,
47 ) -> VolumeControllerHandle {
48 let store = storage_factory.get_store().await;
49 Rc::new(Mutex::new(Self {
50 client,
51 store,
52 stream_volume_controls: HashMap::new(),
53 audio_service_connected: false,
54 modified_counters: create_default_modified_counters(),
55 audio_info_loader,
56 }))
57 }
58
59 async fn restore(&mut self, id: ftrace::Id) -> ControllerStateResult {
61 self.restore_volume_state(true, id).await
62 }
63
64 async fn restore_volume_state(
68 &mut self,
69 push_to_audio_core: bool,
70 id: ftrace::Id,
71 ) -> ControllerStateResult {
72 let audio_info = self.store.get::<AudioInfo>().await;
73 let _ = self
75 .update_volume_streams(UpdateFrom::AudioInfo(audio_info), push_to_audio_core, id)
76 .await?;
77 Ok(())
78 }
79
80 async fn get_info(&self) -> Result<AudioInfo, ControllerError> {
81 let mut audio_info = self.store.get::<AudioInfo>().await;
82
83 audio_info.modified_counters = Some(self.modified_counters.clone());
84 Ok(audio_info)
85 }
86
87 async fn set_volume(
88 &mut self,
89 volume: Vec<SetAudioStream>,
90 id: ftrace::Id,
91 ) -> SettingHandlerResult {
92 let guard = trace_guard!(id, c"set volume updating counters");
93 for stream in &volume {
95 let _ = self.modified_counters.insert(
98 stream.stream_type,
99 self.modified_counters
100 .get(&stream.stream_type)
101 .map_or(0, |flag| flag.wrapping_add(1)),
102 );
103 }
104 drop(guard);
105
106 if !(self.update_volume_streams(UpdateFrom::NewStreams(volume), true, id).await?) {
107 trace!(id, c"set volume notifying");
108 let info = self.get_info().await?.into();
109 self.client.notify(Event::Changed(info)).await;
110 }
111
112 Ok(None)
113 }
114
115 async fn get_streams_array_from_map(
116 &self,
117 stream_map: &HashMap<AudioStreamType, StreamVolumeControl>,
118 ) -> [AudioStream; AUDIO_STREAM_TYPE_COUNT] {
119 let mut streams: [AudioStream; AUDIO_STREAM_TYPE_COUNT] =
120 self.audio_info_loader.default_value().streams;
121 for stream in &mut streams {
122 if let Some(volume_control) = stream_map.get(&stream.stream_type) {
123 *stream = volume_control.stored_stream;
124 }
125 }
126
127 streams
128 }
129
130 async fn update_volume_streams(
137 &mut self,
138 update_from: UpdateFrom,
139 push_to_audio_core: bool,
140 id: ftrace::Id,
141 ) -> Result<bool, ControllerError> {
142 let mut new_vec = vec![];
143 trace!(id, c"update volume streams");
144 let calculating_guard = trace_guard!(id, c"check and bind");
145 let (stored_value, new_streams) = match &update_from {
146 UpdateFrom::AudioInfo(audio_info) => (None, audio_info.streams.iter()),
147 UpdateFrom::NewStreams(streams) => {
148 trace!(id, c"reading setting");
149 let stored_value = self.store.get::<AudioInfo>().await;
150 for set_stream in streams.iter() {
151 let stored_stream = stored_value
152 .streams
153 .iter()
154 .find(|stream| stream.stream_type == set_stream.stream_type)
155 .ok_or_else(|| {
156 ControllerError::InvalidArgument(
157 SettingType::Audio,
158 "stream".into(),
159 format!("{set_stream:?}").into(),
160 )
161 })?;
162 new_vec.push(AudioStream {
163 stream_type: stored_stream.stream_type,
164 source: set_stream.source,
165 user_volume_level: set_stream
166 .user_volume_level
167 .unwrap_or(stored_stream.user_volume_level),
168 user_volume_muted: set_stream
169 .user_volume_muted
170 .unwrap_or(stored_stream.user_volume_muted),
171 });
172 }
173 (Some(stored_value), new_vec.iter())
174 }
175 };
176
177 if push_to_audio_core {
178 let guard = trace_guard!(id, c"push to core");
179 self.check_and_bind_volume_controls(
180 id,
181 self.audio_info_loader.default_value().streams.iter(),
182 )
183 .await?;
184 drop(guard);
185
186 trace!(id, c"setting core");
187 for stream in new_streams {
188 if let Some(volume_control) =
189 self.stream_volume_controls.get_mut(&stream.stream_type)
190 {
191 volume_control.set_volume(id, *stream).await?;
192 }
193 }
194 } else {
195 trace!(id, c"without push to core");
196 self.check_and_bind_volume_controls(id, new_streams).await?;
197 }
198 drop(calculating_guard);
199
200 if let Some(mut stored_value) = stored_value {
201 let guard = trace_guard!(id, c"updating streams and counters");
202 stored_value.streams =
203 self.get_streams_array_from_map(&self.stream_volume_controls).await;
204 stored_value.modified_counters = Some(self.modified_counters.clone());
205 drop(guard);
206
207 let guard = trace_guard!(id, c"writing setting");
208 let write_result = self.client.storage_write(&self.store, stored_value, id).await;
209 drop(guard);
210 Ok(write_result
211 .as_ref()
212 .map_or(false, |update_state| UpdateState::Updated == *update_state))
213 } else {
214 Ok(false)
215 }
216 }
217
218 async fn check_and_bind_volume_controls(
220 &mut self,
221 id: ftrace::Id,
222 streams: impl Iterator<Item = &AudioStream>,
223 ) -> ControllerStateResult {
224 trace!(id, c"check and bind fn");
225 if self.audio_service_connected {
226 return Ok(());
227 }
228
229 let guard = trace_guard!(id, c"connecting to service");
230 let service_result = self
231 .client
232 .get_service_context()
233 .connect::<fidl_fuchsia_media::AudioCoreMarker>()
234 .await;
235
236 let audio_service = service_result.map_err(|e| {
237 ControllerError::ExternalFailure(
238 SettingType::Audio,
239 "fuchsia.media.audio".into(),
240 "connect for audio_core".into(),
241 format!("{e:?}").into(),
242 )
243 })?;
244
245 drop(guard);
249 let mut stream_tuples = Vec::new();
250 for stream in streams {
251 trace!(id, c"create stream volume control");
252 let client = self.client.clone();
253
254 stream_tuples.push((
256 stream.stream_type,
257 StreamVolumeControl::create(
258 id,
259 &audio_service,
260 *stream,
261 Some(Rc::new(move || {
262 let client = client.clone();
266 fasync::Task::local(async move {
267 trace!(id, c"stream exit");
268 client
269 .notify(Event::Exited(Err(ControllerError::UnexpectedError(
270 "stream_volume_control exit".into(),
271 ))))
272 .await;
273 })
274 .detach();
275 })),
276 None,
277 )
278 .await?,
279 ));
280 }
281
282 stream_tuples.into_iter().for_each(|(stream_type, stream_volume_control)| {
283 let _ = self.stream_volume_controls.insert(stream_type, stream_volume_control);
285 });
286 self.audio_service_connected = true;
287
288 Ok(())
289 }
290}
291
292pub(crate) struct AudioController<F> {
293 volume: VolumeControllerHandle,
294 _phantom: PhantomData<F>,
295}
296
297impl<F> StorageAccess for AudioController<F> {
298 type Storage = DeviceStorage;
299 type Data = AudioInfo;
300 const STORAGE_KEY: &'static str = AudioInfo::KEY;
301}
302
303#[async_trait(?Send)]
304impl<F> data_controller::CreateWithAsync for AudioController<F>
305where
306 F: StorageFactory<Storage = DeviceStorage>,
307{
308 type Data = (Rc<F>, AudioInfoLoader);
309 async fn create_with(client: ClientProxy, data: Self::Data) -> Result<Self, ControllerError> {
310 Ok(AudioController {
311 volume: VolumeController::create_with(client, data.1, data.0).await,
312 _phantom: PhantomData,
313 })
314 }
315}
316
317#[async_trait(?Send)]
318impl<F> controller::Handle for AudioController<F> {
319 async fn handle(&self, request: Request) -> Option<SettingHandlerResult> {
320 match request {
321 Request::Restore => Some({
322 let id = ftrace::Id::new();
323 trace!(id, c"controller restore");
324 self.volume.lock().await.restore(id).await.map(|_| None)
325 }),
326 Request::SetVolume(volume, id) => {
327 trace!(id, c"controller set");
328 for audio_stream in &volume {
330 if !audio_stream.has_valid_volume_level() {
331 return Some(Err(ControllerError::InvalidArgument(
332 SettingType::Audio,
333 "stream".into(),
334 format!("{audio_stream:?}").into(),
335 )));
336 }
337 }
338 Some(self.volume.lock().await.set_volume(volume, id).await)
339 }
340 Request::Get => {
341 Some(self.volume.lock().await.get_info().await.map(|info| Some(info.into())))
342 }
343 _ => None,
344 }
345 }
346
347 async fn change_state(&mut self, state: State) -> Option<ControllerStateResult> {
348 match state {
349 State::Startup => {
350 Some({
352 let id = ftrace::Id::new();
353 trace!(id, c"controller startup");
354 self.volume.lock().await.restore_volume_state(false, id).await
355 })
356 }
357 _ => None,
358 }
359 }
360}