1use crate::base::{SettingInfo, SettingType};
6use crate::handler::base::Request;
7use crate::handler::setting_handler::persist::{ClientProxy, controller as data_controller};
8use crate::handler::setting_handler::{
9 ControllerError, ControllerStateResult, IntoHandlerResult, SettingHandlerResult, State,
10 controller,
11};
12use crate::input::input_device_configuration::InputConfiguration;
13use crate::input::types::{
14 DeviceState, DeviceStateSource, InputDevice, InputDeviceType, InputInfo, InputInfoSources,
15 InputState, Microphone,
16};
17use settings_camera::connect_to_camera;
18use settings_common::config::default_settings::DefaultSetting;
19use settings_common::inspect::event::ExternalEventPublisher;
20use settings_media_buttons::MediaButtons;
21use settings_storage::device_storage::{DeviceStorage, DeviceStorageCompatible};
22use settings_storage::storage_factory::{NoneT, StorageAccess, StorageFactory};
23
24use anyhow::Error;
25use async_trait::async_trait;
26use fuchsia_trace as ftrace;
27use futures::lock::Mutex;
28use serde::{Deserialize, Serialize};
29use std::marker::PhantomData;
30use std::rc::Rc;
31
32pub(crate) const DEFAULT_CAMERA_NAME: &str = "camera";
33pub(crate) const DEFAULT_MIC_NAME: &str = "microphone";
34
35impl DeviceStorageCompatible for InputInfoSources {
36 type Loader = NoneT;
37 const KEY: &'static str = "input_info";
38
39 fn try_deserialize_from(value: &str) -> Result<Self, Error> {
40 Self::extract(value).or_else(|e| {
41 log::info!("Failed to deserialize InputInfoSources. Falling back to V2: {e:?}");
42 InputInfoSourcesV2::try_deserialize_from(value).map(Self::from)
43 })
44 }
45}
46
47impl From<InputInfoSourcesV2> for InputInfoSources {
48 fn from(v2: InputInfoSourcesV2) -> Self {
49 let mut input_state = v2.input_device_state;
50
51 input_state.set_source_state(
53 InputDeviceType::MICROPHONE,
54 DEFAULT_MIC_NAME.to_string(),
55 DeviceStateSource::HARDWARE,
56 if v2.hw_microphone.muted { DeviceState::MUTED } else { DeviceState::AVAILABLE },
57 );
58 input_state.set_source_state(
59 InputDeviceType::MICROPHONE,
60 DEFAULT_MIC_NAME.to_string(),
61 DeviceStateSource::SOFTWARE,
62 if v2.sw_microphone.muted { DeviceState::MUTED } else { DeviceState::AVAILABLE },
63 );
64
65 InputInfoSources { input_device_state: input_state }
66 }
67}
68
69impl From<InputInfoSources> for SettingInfo {
70 fn from(info: InputInfoSources) -> SettingInfo {
71 SettingInfo::Input(info.into())
72 }
73}
74
75impl From<InputInfoSources> for InputInfo {
76 fn from(info: InputInfoSources) -> InputInfo {
77 InputInfo { input_device_state: info.input_device_state }
78 }
79}
80
81impl From<InputInfo> for SettingInfo {
82 fn from(info: InputInfo) -> SettingInfo {
83 SettingInfo::Input(info)
84 }
85}
86
87impl From<&InputInfo> for SettingType {
88 fn from(_: &InputInfo) -> SettingType {
89 SettingType::Input
90 }
91}
92
93#[derive(PartialEq, Default, Debug, Clone, Serialize, Deserialize)]
94pub struct InputInfoSourcesV2 {
95 hw_microphone: Microphone,
96 sw_microphone: Microphone,
97 input_device_state: InputState,
98}
99
100impl DeviceStorageCompatible for InputInfoSourcesV2 {
101 type Loader = NoneT;
102 const KEY: &'static str = "input_info_sources_v2";
103
104 fn try_deserialize_from(value: &str) -> Result<Self, Error> {
105 Self::extract(value).or_else(|e| {
106 log::info!("Failed to deserialize InputInfoSourcesV2. Falling back to V1: {e:?}");
107 InputInfoSourcesV1::try_deserialize_from(value).map(Self::from)
108 })
109 }
110}
111
112impl From<InputInfoSourcesV1> for InputInfoSourcesV2 {
113 fn from(v1: InputInfoSourcesV1) -> Self {
114 InputInfoSourcesV2 {
115 hw_microphone: v1.hw_microphone,
116 sw_microphone: v1.sw_microphone,
117 input_device_state: InputState::new(),
118 }
119 }
120}
121
122#[derive(PartialEq, Default, Debug, Clone, Copy, Serialize, Deserialize)]
123pub struct InputInfoSourcesV1 {
124 pub hw_microphone: Microphone,
125 pub sw_microphone: Microphone,
126}
127
128impl DeviceStorageCompatible for InputInfoSourcesV1 {
129 type Loader = NoneT;
130 const KEY: &'static str = "input_info_sources_v1";
131}
132
133type InputControllerInnerHandle = Rc<Mutex<InputControllerInner>>;
134
135struct InputControllerInner {
139 client: ClientProxy,
141
142 store: Rc<DeviceStorage>,
144
145 input_device_state: InputState,
147
148 input_device_config: InputConfiguration,
150
151 external_publisher: ExternalEventPublisher,
152}
153
154impl InputControllerInner {
155 async fn get_stored_info(&self) -> InputInfo {
160 let mut input_info = InputInfo::from(self.store.get::<InputInfo>().await);
161 if input_info.input_device_state.is_empty() {
162 input_info.input_device_state = self.input_device_config.clone().into();
163 }
164 input_info
165 }
166
167 async fn get_info(&mut self) -> Result<InputInfo, ControllerError> {
169 Ok(InputInfo { input_device_state: self.input_device_state.clone() })
170 }
171
172 async fn restore(&mut self) -> ControllerStateResult {
174 let input_info = self.get_stored_info().await;
175 self.input_device_state = input_info.input_device_state;
176
177 if self.input_device_config.devices.iter().any(|d| d.device_type == InputDeviceType::CAMERA)
178 {
179 match self.get_cam_sw_state() {
180 Ok(state) => {
181 if let Err(e) = self.push_cam_sw_state(state).await {
184 log::error!("Unable to restore camera state: {e:?}");
185 self.set_cam_err_state(state);
186 }
187 }
188 Err(e) => {
189 log::error!("Unable to load cam sw state: {e:?}");
190 self.set_cam_err_state(DeviceState::ERROR);
191 }
192 }
193 }
194 Ok(())
195 }
196
197 async fn set_sw_camera_mute(&mut self, disabled: bool, name: String) -> SettingHandlerResult {
198 let mut input_info = self.get_stored_info().await;
199 input_info.input_device_state.set_source_state(
200 InputDeviceType::CAMERA,
201 name.clone(),
202 DeviceStateSource::SOFTWARE,
203 if disabled { DeviceState::MUTED } else { DeviceState::AVAILABLE },
204 );
205
206 self.input_device_state.set_source_state(
207 InputDeviceType::CAMERA,
208 name.clone(),
209 DeviceStateSource::SOFTWARE,
210 if disabled { DeviceState::MUTED } else { DeviceState::AVAILABLE },
211 );
212 let id = ftrace::Id::new();
213 self.client.storage_write(&self.store, input_info, id).await.into_handler_result()
214 }
215
216 async fn set_hw_media_buttons_state(
218 &mut self,
219 media_buttons: MediaButtons,
220 ) -> SettingHandlerResult {
221 let mut states_to_process = Vec::new();
222 if let Some(mic_mute) = media_buttons.mic_mute {
223 states_to_process.push((InputDeviceType::MICROPHONE, mic_mute));
224 }
225 if let Some(camera_disable) = media_buttons.camera_disable {
226 states_to_process.push((InputDeviceType::CAMERA, camera_disable));
227 }
228
229 let mut input_info = self.get_stored_info().await;
230
231 for (device_type, muted) in states_to_process.into_iter() {
232 let hw_state_res = input_info.input_device_state.get_source_state(
234 device_type,
235 device_type.to_string(),
236 DeviceStateSource::HARDWARE,
237 );
238
239 let mut hw_state = hw_state_res.map_err(|err| {
240 ControllerError::UnexpectedError(
241 format!("Could not fetch current hw mute state: {err:?}").into(),
242 )
243 })?;
244
245 if muted {
246 hw_state &= !DeviceState::AVAILABLE;
248 hw_state |= DeviceState::MUTED;
249 } else {
250 hw_state |= DeviceState::AVAILABLE;
252 hw_state &= !DeviceState::MUTED;
253 }
254
255 input_info.input_device_state.set_source_state(
257 device_type,
258 device_type.to_string(),
259 DeviceStateSource::HARDWARE,
260 hw_state,
261 );
262 self.input_device_state.set_source_state(
263 device_type,
264 device_type.to_string(),
265 DeviceStateSource::HARDWARE,
266 hw_state,
267 );
268 }
269
270 let id = ftrace::Id::new();
272 self.client.storage_write(&self.store, input_info, id).await.into_handler_result()
273 }
274
275 async fn set_input_states(
277 &mut self,
278 input_devices: Vec<InputDevice>,
279 source: DeviceStateSource,
280 ) -> SettingHandlerResult {
281 let mut input_info = self.get_stored_info().await;
282 let device_types = input_info.input_device_state.device_types();
283
284 let cam_state = self.get_cam_sw_state().ok();
285
286 for input_device in input_devices.iter() {
287 if !device_types.contains(&input_device.device_type) {
288 return Err(ControllerError::UnsupportedError(SettingType::Input));
289 }
290 input_info.input_device_state.insert_device(input_device.clone(), source);
291 self.input_device_state.insert_device(input_device.clone(), source);
292 }
293
294 let modified_cam_state = self.get_cam_sw_state().ok();
298 if cam_state != modified_cam_state {
299 if let Some(state) = modified_cam_state {
300 self.push_cam_sw_state(state).await?;
301 }
302 }
303
304 let id = ftrace::Id::new();
306 self.client.storage_write(&self.store, input_info, id).await.into_handler_result()
307 }
308
309 #[allow(clippy::result_large_err)] fn get_cam_sw_state(&self) -> Result<DeviceState, ControllerError> {
312 self.input_device_state
313 .get_source_state(
314 InputDeviceType::CAMERA,
315 DEFAULT_CAMERA_NAME.to_string(),
316 DeviceStateSource::SOFTWARE,
317 )
318 .map_err(|_| {
319 ControllerError::UnexpectedError("Could not find camera software state".into())
320 })
321 }
322
323 fn set_cam_err_state(&mut self, mut state: DeviceState) {
325 state.set(DeviceState::ERROR, true);
326 self.input_device_state.set_source_state(
327 InputDeviceType::CAMERA,
328 DEFAULT_CAMERA_NAME.to_string(),
329 DeviceStateSource::SOFTWARE,
330 state,
331 )
332 }
333
334 async fn push_cam_sw_state(&mut self, cam_state: DeviceState) -> Result<(), ControllerError> {
340 let is_muted = cam_state.has_state(DeviceState::MUTED);
341
342 let camera_proxy = connect_to_camera(
346 &*self.client.get_service_context().common_context(),
347 self.external_publisher.clone(),
348 )
349 .await
350 .map_err(|e| {
351 ControllerError::UnexpectedError(
352 format!("Could not connect to camera device: {e:?}").into(),
353 )
354 })?;
355
356 camera_proxy.set_software_mute_state(is_muted).await.map_err(|e| {
357 ControllerError::ExternalFailure(
358 SettingType::Input,
359 "fuchsia.camera3.Device".into(),
360 "SetSoftwareMuteState".into(),
361 format!("{e:?}").into(),
362 )
363 })
364 }
365}
366
367pub struct InputController<F> {
368 inner: InputControllerInnerHandle,
370 _phantom: PhantomData<F>,
371}
372
373impl<F> StorageAccess for InputController<F> {
374 type Storage = DeviceStorage;
375 type Data = InputInfoSources;
376 const STORAGE_KEY: &'static str = InputInfoSources::KEY;
377}
378
379impl<F> InputController<F> {
380 pub(crate) fn create_with_config(
382 client: ClientProxy,
383 input_device_config: InputConfiguration,
384 store: Rc<DeviceStorage>,
385 external_publisher: ExternalEventPublisher,
386 ) -> Result<Self, ControllerError> {
387 Ok(Self {
388 inner: Rc::new(Mutex::new(InputControllerInner {
389 client,
390 store,
391 input_device_state: InputState::new(),
392 input_device_config,
393 external_publisher,
394 })),
395 _phantom: PhantomData,
396 })
397 }
398
399 async fn has_input_device(&self, device_type: InputDeviceType) -> bool {
401 let input_device_config_state: InputState =
402 self.inner.lock().await.input_device_config.clone().into();
403 input_device_config_state.device_types().contains(&device_type)
404 }
405}
406
407#[async_trait(?Send)]
408impl<F> data_controller::CreateWithAsync for InputController<F>
409where
410 F: StorageFactory<Storage = DeviceStorage>,
411{
412 type Data = (
413 Rc<F>,
414 Rc<std::sync::Mutex<DefaultSetting<InputConfiguration, &'static str>>>,
415 ExternalEventPublisher,
416 );
417 async fn create_with(client: ClientProxy, data: Self::Data) -> Result<Self, ControllerError> {
418 if let Ok(Some(config)) = data.1.lock().unwrap().load_default_value() {
419 let store = data.0.get_store().await;
420 InputController::create_with_config(client, config, store, data.2)
421 } else {
422 Err(ControllerError::InitFailure("Invalid default input device config".into()))
423 }
424 }
425}
426
427#[async_trait(?Send)]
428impl<F> controller::Handle for InputController<F> {
429 async fn handle(&self, request: Request) -> Option<SettingHandlerResult> {
430 match request {
431 Request::Restore => Some(self.inner.lock().await.restore().await.map(|_| None)),
432 Request::Get => Some(
433 self.inner.lock().await.get_info().await.map(|info| Some(SettingInfo::Input(info))),
434 ),
435 Request::OnCameraSWState(is_muted) => {
436 let old_state = match self
437 .inner
438 .lock()
439 .await
440 .get_stored_info()
441 .await
442 .input_device_state
443 .get_source_state(
444 InputDeviceType::CAMERA,
445 DEFAULT_CAMERA_NAME.to_string(),
446 DeviceStateSource::SOFTWARE,
447 )
448 .map_err(|_| {
449 ControllerError::UnexpectedError(
450 "Could not find camera software state".into(),
451 )
452 }) {
453 Ok(state) => state,
454 Err(e) => return Some(Err(e)),
455 };
456 Some(if old_state.has_state(DeviceState::MUTED) != is_muted {
457 self.inner
458 .lock()
459 .await
460 .set_sw_camera_mute(is_muted, DEFAULT_CAMERA_NAME.to_string())
461 .await
462 } else {
463 Ok(None)
464 })
465 }
466 Request::OnButton(mut buttons) => {
467 if buttons.mic_mute.is_some()
468 && !self.has_input_device(InputDeviceType::MICROPHONE).await
469 {
470 buttons.set_mic_mute(None);
471 }
472 if buttons.camera_disable.is_some()
473 && !self.has_input_device(InputDeviceType::CAMERA).await
474 {
475 buttons.set_camera_disable(None);
476 }
477 Some(self.inner.lock().await.set_hw_media_buttons_state(buttons).await)
478 }
479 Request::SetInputStates(input_states) => Some(
480 self.inner
481 .lock()
482 .await
483 .set_input_states(input_states, DeviceStateSource::SOFTWARE)
484 .await,
485 ),
486 _ => None,
487 }
488 }
489
490 async fn change_state(&mut self, state: State) -> Option<ControllerStateResult> {
491 match state {
492 State::Startup => Some(self.inner.lock().await.restore().await),
493 _ => None,
494 }
495 }
496}
497
498#[cfg(test)]
499mod tests {
500 use super::*;
501 use crate::handler::setting_handler::ClientImpl;
502 use crate::handler::setting_handler::controller::Handle;
503 use crate::input::input_device_configuration::{InputDeviceConfiguration, SourceState};
504 use crate::service;
505 use crate::service_context::ServiceContext;
506 use fuchsia_async as fasync;
507 use fuchsia_inspect::component;
508 use futures::channel::mpsc;
509 use settings_common::inspect::config_logger::InspectConfigLogger;
510 use settings_test_common::fakes::service::ServiceRegistry;
511 use settings_test_common::storage::InMemoryStorageFactory;
512
513 #[fuchsia::test]
514 fn test_input_migration_v1_to_current() {
515 const MUTED_MIC: Microphone = Microphone { muted: true };
516 let mut v1 = InputInfoSourcesV1::default();
517 v1.sw_microphone = MUTED_MIC;
518
519 let serialized_v1 = v1.serialize_to();
520 let current = InputInfoSources::try_deserialize_from(&serialized_v1)
521 .expect("deserialization should succeed");
522 let mut expected_input_state = InputState::new();
523 expected_input_state.set_source_state(
524 InputDeviceType::MICROPHONE,
525 DEFAULT_MIC_NAME.to_string(),
526 DeviceStateSource::SOFTWARE,
527 DeviceState::MUTED,
528 );
529 expected_input_state.set_source_state(
530 InputDeviceType::MICROPHONE,
531 DEFAULT_MIC_NAME.to_string(),
532 DeviceStateSource::HARDWARE,
533 DeviceState::AVAILABLE,
534 );
535 assert_eq!(current.input_device_state, expected_input_state);
536 }
537
538 #[fuchsia::test]
539 fn test_input_migration_v1_to_v2() {
540 const MUTED_MIC: Microphone = Microphone { muted: true };
541 let mut v1 = InputInfoSourcesV1::default();
542 v1.sw_microphone = MUTED_MIC;
543
544 let serialized_v1 = v1.serialize_to();
545 let v2 = InputInfoSourcesV2::try_deserialize_from(&serialized_v1)
546 .expect("deserialization should succeed");
547
548 assert_eq!(v2.hw_microphone, Microphone { muted: false });
549 assert_eq!(v2.sw_microphone, MUTED_MIC);
550 assert_eq!(v2.input_device_state, InputState::new());
551 }
552
553 #[fuchsia::test]
554 fn test_input_migration_v2_to_current() {
555 const DEFAULT_CAMERA_NAME: &str = "camera";
556 const MUTED_MIC: Microphone = Microphone { muted: true };
557 let mut v2 = InputInfoSourcesV2::default();
558 v2.input_device_state.set_source_state(
559 InputDeviceType::CAMERA,
560 DEFAULT_CAMERA_NAME.to_string(),
561 DeviceStateSource::SOFTWARE,
562 DeviceState::AVAILABLE,
563 );
564 v2.input_device_state.set_source_state(
565 InputDeviceType::CAMERA,
566 DEFAULT_CAMERA_NAME.to_string(),
567 DeviceStateSource::HARDWARE,
568 DeviceState::MUTED,
569 );
570 v2.sw_microphone = MUTED_MIC;
571
572 let serialized_v2 = v2.serialize_to();
573 let current = InputInfoSources::try_deserialize_from(&serialized_v2)
574 .expect("deserialization should succeed");
575 let mut expected_input_state = InputState::new();
576
577 expected_input_state.set_source_state(
578 InputDeviceType::MICROPHONE,
579 DEFAULT_MIC_NAME.to_string(),
580 DeviceStateSource::SOFTWARE,
581 DeviceState::MUTED,
582 );
583 expected_input_state.set_source_state(
584 InputDeviceType::MICROPHONE,
585 DEFAULT_MIC_NAME.to_string(),
586 DeviceStateSource::HARDWARE,
587 DeviceState::AVAILABLE,
588 );
589 expected_input_state.set_source_state(
590 InputDeviceType::CAMERA,
591 DEFAULT_CAMERA_NAME.to_string(),
592 DeviceStateSource::SOFTWARE,
593 DeviceState::AVAILABLE,
594 );
595 expected_input_state.set_source_state(
596 InputDeviceType::CAMERA,
597 DEFAULT_CAMERA_NAME.to_string(),
598 DeviceStateSource::HARDWARE,
599 DeviceState::MUTED,
600 );
601
602 assert_eq!(current.input_device_state, expected_input_state);
603 }
604
605 #[fasync::run_until_stalled(test)]
606 async fn test_camera_error_on_restore() {
607 let message_hub = service::MessageHub::create_hub();
608 let (event_tx, _event_rx) = mpsc::unbounded();
609 let external_publisher = ExternalEventPublisher::new(event_tx);
610
611 let storage_factory = InMemoryStorageFactory::new();
612 storage_factory
613 .initialize::<InputController<InMemoryStorageFactory>>()
614 .await
615 .expect("controller should have impls");
616 let store = storage_factory.get_store().await;
617 let client_proxy = create_proxy(message_hub).await;
618 let controller = InputController::<InMemoryStorageFactory>::create_with_config(
619 client_proxy,
620 InputConfiguration {
621 devices: vec![InputDeviceConfiguration {
622 device_name: DEFAULT_CAMERA_NAME.to_string(),
623 device_type: InputDeviceType::CAMERA,
624 source_states: vec![SourceState {
625 source: DeviceStateSource::SOFTWARE,
626 state: 0,
627 }],
628 mutable_toggle_state: 0,
629 }],
630 },
631 store,
632 external_publisher,
633 )
634 .expect("Should have controller");
635
636 let result = controller.handle(Request::Restore).await;
638 assert_eq!(result, Some(Ok(None)));
639
640 let result = controller.handle(Request::Get).await;
642 let Some(Ok(Some(SettingInfo::Input(input_info)))) = result else {
643 panic!("Expected Input response. Got {result:?}");
644 };
645 let camera_state = input_info
646 .input_device_state
647 .get_state(InputDeviceType::CAMERA, DEFAULT_CAMERA_NAME.to_string())
648 .unwrap();
649 assert!(camera_state.has_state(DeviceState::ERROR));
650 }
651
652 #[fasync::run_until_stalled(test)]
653 async fn test_controller_creation_with_default_config() {
654 use crate::handler::setting_handler::persist::controller::CreateWithAsync;
655
656 let message_hub = service::MessageHub::create_hub();
657 let client_proxy = create_proxy(message_hub).await;
658 let config_logger = InspectConfigLogger::new(component::inspector().root());
659 let default_setting = DefaultSetting::new(
660 Some(InputConfiguration::default()),
661 "/config/data/input_device_config.json",
662 Rc::new(std::sync::Mutex::new(config_logger)),
663 );
664
665 let (event_tx, _) = mpsc::unbounded();
666 let external_publisher = ExternalEventPublisher::new(event_tx);
667
668 let storage_factory = InMemoryStorageFactory::new();
669 storage_factory
670 .initialize::<InputController<InMemoryStorageFactory>>()
671 .await
672 .expect("controller should have impls");
673 let _controller = InputController::create_with(
674 client_proxy,
675 (
676 Rc::new(storage_factory),
677 Rc::new(std::sync::Mutex::new(default_setting)),
678 external_publisher,
679 ),
680 )
681 .await
682 .expect("Should have controller");
683 }
684
685 async fn create_proxy(message_hub: service::message::Delegate) -> ClientProxy {
686 let (controller_messenger, _) = message_hub
688 .create(service::message::MessengerType::Unbound)
689 .await
690 .expect("Unable to create agent messenger");
691
692 let service_registry = ServiceRegistry::create();
695
696 let service_context =
697 ServiceContext::new(Some(ServiceRegistry::serve(service_registry)), None);
698
699 let signature = controller_messenger.get_signature();
702
703 ClientProxy::new(
704 Rc::new(ClientImpl::for_test(
705 Default::default(),
706 controller_messenger,
707 signature,
708 Rc::new(service_context),
709 SettingType::Input,
710 )),
711 SettingType::Input,
712 )
713 .await
714 }
715}