1use crate::input_device_configuration::InputConfiguration;
6use crate::input_fidl_handler::Publisher;
7use crate::types::{
8 DeviceState, DeviceStateSource, InputDevice, InputDeviceType, InputInfo, InputInfoSources,
9 InputState, Microphone,
10};
11use anyhow::{Context, Error};
12use fuchsia_async as fasync;
13use futures::StreamExt;
14use futures::channel::mpsc::UnboundedReceiver;
15use futures::channel::oneshot::Sender;
16use serde::{Deserialize, Serialize};
17use settings_camera::connect_to_camera;
18use settings_common::config::default_settings::DefaultSetting;
19use settings_common::inspect::event::{
20 ExternalEventPublisher, ResponseType, SettingValuePublisher,
21};
22use settings_common::service_context::ServiceContext;
23use settings_media_buttons::{Event, MediaButtons};
24use settings_storage::UpdateState;
25use settings_storage::device_storage::{DeviceStorage, DeviceStorageCompatible};
26use settings_storage::storage_factory::{NoneT, StorageAccess, StorageFactory};
27use std::borrow::Cow;
28use std::rc::Rc;
29
30pub(crate) const DEFAULT_CAMERA_NAME: &str = "camera";
31pub(crate) const DEFAULT_MIC_NAME: &str = "microphone";
32
33pub(crate) const MAX_INPUT_DEVICES: usize = fidl_fuchsia_settings::MAX_INPUT_DEVICES as usize;
37
38type UpdateInputResult = Result<Option<InputInfo>, InputError>;
39fn check_publish(
40 result: UpdateInputResult,
41 publish: impl Fn(InputInfo),
42) -> Result<Option<()>, InputError> {
43 result.map(|info| info.map(publish))
44}
45
46#[derive(thiserror::Error, Debug)]
47pub(crate) enum InputError {
48 #[error("Failed to initialize controller: {0:?}")]
49 InitFailure(Error),
50 #[error("Unsupported device type: {0:?}")]
51 Unsupported(InputDeviceType),
52 #[error("External failure for Input dependency: {0:?} request:{1:?} error:{2}")]
53 ExternalFailure(Cow<'static, str>, Cow<'static, str>, Cow<'static, str>),
54 #[error("Write failed for Input: {0:?}")]
55 WriteFailure(Error),
56 #[error("The maximum number of input devices has been reached.")]
57 MaximumInputDeviceLimitReached(Cow<'static, str>),
58 #[error("Unexpected error: {0}")]
59 UnexpectedError(Cow<'static, str>),
60}
61
62impl From<&InputError> for ResponseType {
63 fn from(error: &InputError) -> Self {
64 match error {
65 InputError::InitFailure(..) => ResponseType::InitFailure,
66 InputError::Unsupported(..) => ResponseType::UnsupportedError,
67 InputError::ExternalFailure(..) => ResponseType::ExternalFailure,
68 InputError::WriteFailure(..) => ResponseType::StorageFailure,
69 InputError::MaximumInputDeviceLimitReached(..) => {
70 ResponseType::MaximumInputDevicesReached
71 }
72 InputError::UnexpectedError(..) => ResponseType::UnexpectedError,
73 }
74 }
75}
76
77impl DeviceStorageCompatible for InputInfoSources {
78 type Loader = NoneT;
79 const KEY: &'static str = "input_info";
80
81 fn try_deserialize_from(value: &str) -> Result<Self, Error> {
82 Self::extract(value).or_else(|e| {
83 log::info!("Failed to deserialize InputInfoSources. Falling back to V2: {e:?}");
84 InputInfoSourcesV2::try_deserialize_from(value).map(Self::from)
85 })
86 }
87}
88
89impl From<InputInfoSourcesV2> for InputInfoSources {
90 fn from(v2: InputInfoSourcesV2) -> Self {
91 let mut input_state = v2.input_device_state;
92
93 input_state.set_source_state(
95 InputDeviceType::MICROPHONE,
96 DEFAULT_MIC_NAME.to_string(),
97 DeviceStateSource::HARDWARE,
98 if v2.hw_microphone.muted { DeviceState::MUTED } else { DeviceState::AVAILABLE },
99 );
100 input_state.set_source_state(
101 InputDeviceType::MICROPHONE,
102 DEFAULT_MIC_NAME.to_string(),
103 DeviceStateSource::SOFTWARE,
104 if v2.sw_microphone.muted { DeviceState::MUTED } else { DeviceState::AVAILABLE },
105 );
106
107 InputInfoSources { input_device_state: input_state }
108 }
109}
110
111impl From<InputInfoSources> for InputInfo {
112 fn from(info: InputInfoSources) -> InputInfo {
113 InputInfo { input_device_state: info.input_device_state }
114 }
115}
116
117#[derive(PartialEq, Default, Debug, Clone, Serialize, Deserialize)]
118pub struct InputInfoSourcesV2 {
119 hw_microphone: Microphone,
120 sw_microphone: Microphone,
121 input_device_state: InputState,
122}
123
124impl DeviceStorageCompatible for InputInfoSourcesV2 {
125 type Loader = NoneT;
126 const KEY: &'static str = "input_info_sources_v2";
127
128 fn try_deserialize_from(value: &str) -> Result<Self, Error> {
129 Self::extract(value).or_else(|e| {
130 log::info!("Failed to deserialize InputInfoSourcesV2. Falling back to V1: {e:?}");
131 InputInfoSourcesV1::try_deserialize_from(value).map(Self::from)
132 })
133 }
134}
135
136impl From<InputInfoSourcesV1> for InputInfoSourcesV2 {
137 fn from(v1: InputInfoSourcesV1) -> Self {
138 InputInfoSourcesV2 {
139 hw_microphone: v1.hw_microphone,
140 sw_microphone: v1.sw_microphone,
141 input_device_state: InputState::new(),
142 }
143 }
144}
145
146#[derive(PartialEq, Default, Debug, Clone, Copy, Serialize, Deserialize)]
147pub struct InputInfoSourcesV1 {
148 pub hw_microphone: Microphone,
149 pub sw_microphone: Microphone,
150}
151
152impl DeviceStorageCompatible for InputInfoSourcesV1 {
153 type Loader = NoneT;
154 const KEY: &'static str = "input_info_sources_v1";
155}
156
157pub(crate) enum Request {
158 Set(Vec<InputDevice>, Sender<Result<(), InputError>>),
159}
160
161pub struct InputController {
162 service_context: Rc<ServiceContext>,
163 store: Rc<DeviceStorage>,
165
166 input_device_state: InputState,
168
169 input_device_config: InputConfiguration,
171 publisher: Option<Publisher>,
172 setting_value_publisher: SettingValuePublisher<InputInfo>,
173 external_publisher: ExternalEventPublisher,
174}
175
176impl StorageAccess for InputController {
177 type Storage = DeviceStorage;
178 type Data = InputInfoSources;
179 const STORAGE_KEY: &'static str = InputInfoSources::KEY;
180}
181
182impl InputController {
183 pub(super) async fn new<F>(
184 service_context: Rc<ServiceContext>,
185 default_setting: &mut DefaultSetting<InputConfiguration, &'static str>,
186 storage_factory: Rc<F>,
187 setting_value_publisher: SettingValuePublisher<InputInfo>,
188 external_publisher: ExternalEventPublisher,
189 ) -> Result<Self, InputError>
190 where
191 F: StorageFactory<Storage = DeviceStorage>,
192 {
193 let input_device_config = default_setting
194 .load_default_value()
195 .context("Unable to load input device config")
196 .map_err(InputError::InitFailure)?
197 .expect("Input requires a configuration");
198 Ok(InputController::create_with_config(
199 service_context,
200 input_device_config,
201 &*storage_factory,
202 setting_value_publisher,
203 external_publisher,
204 )
205 .await)
206 }
207
208 pub(crate) async fn create_with_config<F>(
210 service_context: Rc<ServiceContext>,
211 input_device_config: InputConfiguration,
212 storage_factory: &F,
213 setting_value_publisher: SettingValuePublisher<InputInfo>,
214 external_publisher: ExternalEventPublisher,
215 ) -> Self
216 where
217 F: StorageFactory<Storage = DeviceStorage>,
218 {
219 Self {
220 service_context,
221 store: storage_factory.get_store().await,
222 input_device_state: InputState::new(),
223 input_device_config,
224 publisher: None,
225 setting_value_publisher,
226 external_publisher,
227 }
228 }
229
230 async fn has_input_device(&self, device_type: InputDeviceType) -> bool {
232 let input_device_config_state: InputState = self.input_device_config.clone().into();
233 input_device_config_state.device_types().contains(&device_type)
234 }
235
236 pub(super) fn register_publisher(&mut self, publisher: Publisher) {
237 self.publisher = Some(publisher);
238 }
239
240 fn publish(&self, info: InputInfo) {
241 let _ = self.setting_value_publisher.publish(&info);
242 if let Some(publisher) = self.publisher.as_ref() {
243 publisher.set(info);
244 }
245 }
246
247 pub(super) async fn handle(
248 mut self,
249 mut camera_event_rx: UnboundedReceiver<(bool, super::ResultSender)>,
250 mut media_buttons_event_rx: UnboundedReceiver<(Event, super::ResultSender)>,
251 mut request_rx: UnboundedReceiver<Request>,
252 ) -> fasync::Task<()> {
253 fasync::Task::local(async move {
254 let mut next_camera_event = camera_event_rx.next();
255 let mut next_media_buttons_event = media_buttons_event_rx.next();
256 let mut next_request = request_rx.next();
257 loop {
258 futures::select! {
259 event = next_camera_event => {
260 let Some((is_muted, response_tx)) = event else {
261 continue;
262 };
263 next_camera_event = camera_event_rx.next();
264 let res = self.handle_camera_event(is_muted).await;
265 let _ = response_tx.send(res);
266 }
267 event = next_media_buttons_event => {
268 let Some((Event::OnButton(buttons), response_tx)) = event else {
269 continue;
270 };
271 next_media_buttons_event = media_buttons_event_rx.next();
272 let res = self.handle_media_buttons_event(buttons).await;
273 let _ = response_tx.send(res);
274 }
275 request = next_request => {
276 let Some(request) = request else {
277 continue;
278 };
279 next_request = request_rx.next();
280 let Request::Set(input_devices, tx) = request;
281 let res = check_publish(
282 self.set_input_states(input_devices, DeviceStateSource::SOFTWARE).await,
283 |info| self.publish(info)).map(|_|{});
284 let _ = tx.send(res);
285 }
286 }
287 }
288 })
289 }
290
291 async fn handle_camera_event(&mut self, is_muted: bool) -> Result<Option<()>, InputError> {
292 let stored_info = self.get_stored_info().await;
293 let old_state = Self::get_cam_sw_state_from(&stored_info.input_device_state)?;
294 if old_state.has_state(DeviceState::MUTED) != is_muted {
295 check_publish(
296 self.set_sw_camera_mute(is_muted, DEFAULT_CAMERA_NAME.to_string()).await,
297 |info| self.publish(info),
298 )
299 } else {
300 Ok(None)
301 }
302 }
303
304 async fn handle_media_buttons_event(
305 &mut self,
306 mut buttons: MediaButtons,
307 ) -> Result<Option<()>, InputError> {
308 if buttons.mic_mute.is_some() && !self.has_input_device(InputDeviceType::MICROPHONE).await {
309 buttons.set_mic_mute(None);
310 }
311 if buttons.camera_disable.is_some() && !self.has_input_device(InputDeviceType::CAMERA).await
312 {
313 buttons.set_camera_disable(None);
314 }
315 check_publish(self.set_hw_media_buttons_state(buttons).await, |info| self.publish(info))
316 }
317
318 async fn get_stored_info(&self) -> InputInfo {
323 let mut input_info = InputInfo::from(self.store.get::<InputInfo>().await);
324 if input_info.input_device_state.is_empty() {
325 input_info.input_device_state = self.input_device_config.clone().into();
326 }
327 input_info
328 }
329
330 pub(super) async fn restore(&mut self) -> Result<InputInfo, InputError> {
332 let input_info = self.get_stored_info().await;
333 self.input_device_state = input_info.input_device_state.clone();
334
335 if self.input_device_config.devices.iter().any(|d| d.device_type == InputDeviceType::CAMERA)
336 {
337 match self.get_cam_sw_state() {
338 Ok(state) => {
339 if let Err(e) = self.push_cam_sw_state(state).await {
342 log::error!("Unable to restore camera state: {e:?}");
343 self.set_cam_err_state(state);
344 }
345 }
346 Err(e) => {
347 log::error!("Unable to load cam sw state: {e:?}");
348 self.set_cam_err_state(DeviceState::ERROR);
349 }
350 }
351 }
352 Ok(input_info)
353 }
354
355 async fn set_sw_camera_mute(&mut self, disabled: bool, name: String) -> UpdateInputResult {
356 let mut input_info = self.get_stored_info().await;
357 input_info.input_device_state.set_source_state(
358 InputDeviceType::CAMERA,
359 name.clone(),
360 DeviceStateSource::SOFTWARE,
361 if disabled { DeviceState::MUTED } else { DeviceState::AVAILABLE },
362 );
363
364 self.input_device_state.set_source_state(
365 InputDeviceType::CAMERA,
366 name.clone(),
367 DeviceStateSource::SOFTWARE,
368 if disabled { DeviceState::MUTED } else { DeviceState::AVAILABLE },
369 );
370 self.store
371 .write(&input_info)
372 .await
373 .map(|state| (UpdateState::Updated == state).then_some(input_info))
374 .context("writing sw camera info")
375 .map_err(InputError::WriteFailure)
376 }
377
378 async fn set_hw_media_buttons_state(
380 &mut self,
381 media_buttons: MediaButtons,
382 ) -> UpdateInputResult {
383 let mut states_to_process = Vec::new();
384 if let Some(mic_mute) = media_buttons.mic_mute {
385 states_to_process.push((InputDeviceType::MICROPHONE, mic_mute));
386 }
387 if let Some(camera_disable) = media_buttons.camera_disable {
388 states_to_process.push((InputDeviceType::CAMERA, camera_disable));
389 }
390
391 let mut input_info = self.get_stored_info().await;
392
393 for (device_type, muted) in states_to_process.into_iter() {
394 let hw_state_res = input_info.input_device_state.get_source_state(
396 device_type,
397 device_type.to_string(),
398 DeviceStateSource::HARDWARE,
399 );
400
401 let mut hw_state = hw_state_res.map_err(|err| {
402 InputError::UnexpectedError(
403 format!("Could not fetch current hw mute state: {err:?}").into(),
404 )
405 })?;
406
407 if muted {
408 hw_state &= !DeviceState::AVAILABLE;
410 hw_state |= DeviceState::MUTED;
411 } else {
412 hw_state |= DeviceState::AVAILABLE;
414 hw_state &= !DeviceState::MUTED;
415 }
416
417 input_info.input_device_state.set_source_state(
419 device_type,
420 device_type.to_string(),
421 DeviceStateSource::HARDWARE,
422 hw_state,
423 );
424 self.input_device_state.set_source_state(
425 device_type,
426 device_type.to_string(),
427 DeviceStateSource::HARDWARE,
428 hw_state,
429 );
430 }
431
432 self.store
433 .write(&input_info)
434 .await
435 .map(|state| (UpdateState::Updated == state).then_some(input_info))
436 .context("writing hw media buttons")
437 .map_err(InputError::WriteFailure)
438 }
439
440 async fn set_input_states(
442 &mut self,
443 input_devices: Vec<InputDevice>,
444 source: DeviceStateSource,
445 ) -> UpdateInputResult {
446 let mut input_info = self.get_stored_info().await;
447 let device_types = input_info.input_device_state.device_types();
448 let cam_state = self.get_cam_sw_state().ok();
449
450 let mut new_devices = Vec::new();
453 for input_device in input_devices.iter() {
454 if !device_types.contains(&input_device.device_type) {
455 return Err(InputError::Unsupported(input_device.device_type));
456 }
457
458 let already_exists = input_info
459 .input_device_state
460 .contains_device(input_device.device_type, &input_device.name);
461
462 let already_counted = new_devices
463 .iter()
464 .any(|(dt, name)| *dt == input_device.device_type && *name == &input_device.name);
465
466 if !already_exists && !already_counted {
467 new_devices.push((input_device.device_type, &input_device.name));
468 }
469 }
470
471 if input_info.input_device_state.total_devices() + new_devices.len() > MAX_INPUT_DEVICES {
473 log::error!(
474 "Maximum number of supported input devices ({MAX_INPUT_DEVICES}) has been reached."
475 );
476 return Err(InputError::MaximumInputDeviceLimitReached(
477 format!("Maximum limit of {MAX_INPUT_DEVICES} input devices has been reached.")
478 .into(),
479 ));
480 }
481
482 for input_device in &input_devices {
485 input_info.input_device_state.insert_device(input_device.clone(), source);
486 }
487
488 let modified_cam_state = Self::get_cam_sw_state_from(&input_info.input_device_state).ok();
492 if cam_state != modified_cam_state
493 && let Some(state) = modified_cam_state
494 {
495 self.push_cam_sw_state(state).await?;
496 }
497
498 for input_device in input_devices {
501 self.input_device_state.insert_device(input_device, source);
502 }
503
504 self.store
505 .write(&input_info)
506 .await
507 .map(|state| (UpdateState::Updated == state).then_some(input_info))
508 .context("writing input states")
509 .map_err(InputError::WriteFailure)
510 }
511
512 fn get_cam_sw_state_from(input_state: &InputState) -> Result<DeviceState, InputError> {
514 input_state
515 .get_source_state(
516 InputDeviceType::CAMERA,
517 DEFAULT_CAMERA_NAME.to_string(),
518 DeviceStateSource::SOFTWARE,
519 )
520 .map_err(|e| {
521 InputError::UnexpectedError(
522 format!("Could not find camera software state: {e:?}").into(),
523 )
524 })
525 }
526
527 fn get_cam_sw_state(&self) -> Result<DeviceState, InputError> {
529 Self::get_cam_sw_state_from(&self.input_device_state)
530 }
531
532 fn set_cam_err_state(&mut self, mut state: DeviceState) {
534 state.set(DeviceState::ERROR, true);
535 self.input_device_state.set_source_state(
536 InputDeviceType::CAMERA,
537 DEFAULT_CAMERA_NAME.to_string(),
538 DeviceStateSource::SOFTWARE,
539 state,
540 )
541 }
542
543 async fn push_cam_sw_state(&mut self, cam_state: DeviceState) -> Result<(), InputError> {
549 let is_muted = cam_state.has_state(DeviceState::MUTED);
550
551 let camera_proxy =
555 connect_to_camera(&self.service_context, self.external_publisher.clone())
556 .await
557 .map_err(|e| {
558 InputError::UnexpectedError(
559 format!("Could not connect to camera device: {e:?}").into(),
560 )
561 })?;
562
563 camera_proxy.set_software_mute_state(is_muted).await.map_err(|e| {
564 InputError::ExternalFailure(
565 "fuchsia.camera3.Device".into(),
566 "SetSoftwareMuteState".into(),
567 format!("{e:?}").into(),
568 )
569 })
570 }
571}
572
573#[cfg(test)]
574mod tests {
575 use super::*;
576 use crate::input_device_configuration::{InputDeviceConfiguration, SourceState};
577 use fuchsia_async as fasync;
578 use fuchsia_inspect::component;
579 use futures::channel::mpsc;
580 use settings_common::inspect::config_logger::InspectConfigLogger;
581 use settings_common::service_context::ServiceContext;
582 use settings_test_common::storage::InMemoryStorageFactory;
583
584 #[fuchsia::test]
585 fn test_input_migration_v1_to_current() {
586 const MUTED_MIC: Microphone = Microphone { muted: true };
587 let v1 = InputInfoSourcesV1 { sw_microphone: MUTED_MIC, ..Default::default() };
588
589 let serialized_v1 = v1.serialize_to();
590 let current = InputInfoSources::try_deserialize_from(&serialized_v1)
591 .expect("deserialization should succeed");
592 let mut expected_input_state = InputState::new();
593 expected_input_state.set_source_state(
594 InputDeviceType::MICROPHONE,
595 DEFAULT_MIC_NAME.to_string(),
596 DeviceStateSource::SOFTWARE,
597 DeviceState::MUTED,
598 );
599 expected_input_state.set_source_state(
600 InputDeviceType::MICROPHONE,
601 DEFAULT_MIC_NAME.to_string(),
602 DeviceStateSource::HARDWARE,
603 DeviceState::AVAILABLE,
604 );
605 assert_eq!(current.input_device_state, expected_input_state);
606 }
607
608 #[fuchsia::test]
609 fn test_input_migration_v1_to_v2() {
610 const MUTED_MIC: Microphone = Microphone { muted: true };
611 let v1 = InputInfoSourcesV1 { sw_microphone: MUTED_MIC, ..Default::default() };
612
613 let serialized_v1 = v1.serialize_to();
614 let v2 = InputInfoSourcesV2::try_deserialize_from(&serialized_v1)
615 .expect("deserialization should succeed");
616
617 assert_eq!(v2.hw_microphone, Microphone { muted: false });
618 assert_eq!(v2.sw_microphone, MUTED_MIC);
619 assert_eq!(v2.input_device_state, InputState::new());
620 }
621
622 #[fuchsia::test]
623 fn test_input_migration_v2_to_current() {
624 const DEFAULT_CAMERA_NAME: &str = "camera";
625 const MUTED_MIC: Microphone = Microphone { muted: true };
626 let mut v2 = InputInfoSourcesV2::default();
627 v2.input_device_state.set_source_state(
628 InputDeviceType::CAMERA,
629 DEFAULT_CAMERA_NAME.to_string(),
630 DeviceStateSource::SOFTWARE,
631 DeviceState::AVAILABLE,
632 );
633 v2.input_device_state.set_source_state(
634 InputDeviceType::CAMERA,
635 DEFAULT_CAMERA_NAME.to_string(),
636 DeviceStateSource::HARDWARE,
637 DeviceState::MUTED,
638 );
639 v2.sw_microphone = MUTED_MIC;
640
641 let serialized_v2 = v2.serialize_to();
642 let current = InputInfoSources::try_deserialize_from(&serialized_v2)
643 .expect("deserialization should succeed");
644 let mut expected_input_state = InputState::new();
645
646 expected_input_state.set_source_state(
647 InputDeviceType::MICROPHONE,
648 DEFAULT_MIC_NAME.to_string(),
649 DeviceStateSource::SOFTWARE,
650 DeviceState::MUTED,
651 );
652 expected_input_state.set_source_state(
653 InputDeviceType::MICROPHONE,
654 DEFAULT_MIC_NAME.to_string(),
655 DeviceStateSource::HARDWARE,
656 DeviceState::AVAILABLE,
657 );
658 expected_input_state.set_source_state(
659 InputDeviceType::CAMERA,
660 DEFAULT_CAMERA_NAME.to_string(),
661 DeviceStateSource::SOFTWARE,
662 DeviceState::AVAILABLE,
663 );
664 expected_input_state.set_source_state(
665 InputDeviceType::CAMERA,
666 DEFAULT_CAMERA_NAME.to_string(),
667 DeviceStateSource::HARDWARE,
668 DeviceState::MUTED,
669 );
670
671 assert_eq!(current.input_device_state, expected_input_state);
672 }
673
674 #[fuchsia::test]
675 async fn test_camera_error_on_restore() {
676 let (event_tx, _event_rx) = mpsc::unbounded();
677 let external_publisher = ExternalEventPublisher::new(event_tx);
678 let storage_factory = InMemoryStorageFactory::new();
679 storage_factory
680 .initialize::<InputController>()
681 .await
682 .expect("controller should have impls");
683 let (value_tx, _value_rx) = mpsc::unbounded();
684 let setting_value_publisher = SettingValuePublisher::new(value_tx);
685 let mut controller: InputController =
686 InputController::create_with_config::<InMemoryStorageFactory>(
687 Rc::new(ServiceContext::new(None)),
688 InputConfiguration {
689 devices: vec![InputDeviceConfiguration {
690 device_name: DEFAULT_CAMERA_NAME.to_string(),
691 device_type: InputDeviceType::CAMERA,
692 source_states: vec![SourceState {
693 source: DeviceStateSource::SOFTWARE,
694 state: 0,
695 }],
696 mutable_toggle_state: 0,
697 }],
698 },
699 &storage_factory,
700 setting_value_publisher,
701 external_publisher,
702 )
703 .await;
704
705 let result = controller.restore().await;
707 assert!(result.is_ok());
708
709 let camera_state = controller
711 .input_device_state
712 .get_state(InputDeviceType::CAMERA, DEFAULT_CAMERA_NAME.to_string())
713 .unwrap();
714 assert!(camera_state.has_state(DeviceState::ERROR));
715 }
716
717 #[fasync::run_until_stalled(test)]
718 async fn test_controller_creation_with_default_config() {
719 let config_logger = InspectConfigLogger::new(component::inspector().root());
720 let mut default_setting = DefaultSetting::new(
721 Some(InputConfiguration::default()),
722 "/config/data/input_device_config.json",
723 Rc::new(std::sync::Mutex::new(config_logger)),
724 );
725
726 let (event_tx, _) = mpsc::unbounded();
727 let external_publisher = ExternalEventPublisher::new(event_tx);
728
729 let storage_factory = InMemoryStorageFactory::new();
730 storage_factory
731 .initialize::<InputController>()
732 .await
733 .expect("controller should have impls");
734 let (value_tx, _value_rx) = mpsc::unbounded();
735 let setting_value_publisher = SettingValuePublisher::new(value_tx);
736 let _controller = InputController::new(
737 Rc::new(ServiceContext::new(None)),
738 &mut default_setting,
739 Rc::new(storage_factory),
740 setting_value_publisher,
741 external_publisher,
742 )
743 .await
744 .expect("Should have controller");
745 }
746
747 #[fuchsia::test]
748 async fn test_set_input_states_limit() {
749 let (event_tx, _event_rx) = mpsc::unbounded();
750 let external_publisher = ExternalEventPublisher::new(event_tx);
751 let storage_factory = InMemoryStorageFactory::new();
752 storage_factory
753 .initialize::<InputController>()
754 .await
755 .expect("controller should have impls");
756 let (value_tx, _value_rx) = mpsc::unbounded();
757 let setting_value_publisher = SettingValuePublisher::new(value_tx);
758
759 let mut device_configs = Vec::new();
760 for i in 0..MAX_INPUT_DEVICES {
761 device_configs.push(InputDeviceConfiguration {
762 device_name: format!("mic{i}"),
763 device_type: InputDeviceType::MICROPHONE,
764 source_states: vec![SourceState { source: DeviceStateSource::SOFTWARE, state: 0 }],
765 mutable_toggle_state: 0,
766 });
767 }
768
769 let mut controller: InputController =
770 InputController::create_with_config::<InMemoryStorageFactory>(
771 Rc::new(ServiceContext::new(None)),
772 InputConfiguration { devices: device_configs },
773 &storage_factory,
774 setting_value_publisher,
775 external_publisher,
776 )
777 .await;
778
779 let _ = controller.restore().await;
780
781 let overflow_dev = InputDevice {
782 name: "mic_max_exceeded".to_string(),
783 device_type: InputDeviceType::MICROPHONE,
784 source_states: [(DeviceStateSource::SOFTWARE, DeviceState::AVAILABLE)].into(),
785 state: DeviceState::AVAILABLE,
786 };
787 let res =
788 controller.set_input_states(vec![overflow_dev], DeviceStateSource::SOFTWARE).await;
789 match res {
790 Err(InputError::MaximumInputDeviceLimitReached(msg)) => {
791 assert_eq!(
792 msg,
793 format!("Maximum limit of {MAX_INPUT_DEVICES} input devices has been reached.")
794 );
795 }
796 _ => panic!("Expected MaximumInputDeviceLimitReached, got {res:?}"),
797 }
798 }
799
800 async fn handle_camera3_device(
801 mut stream: fidl_fuchsia_camera3::DeviceRequestStream,
802 camera_muted: std::sync::Arc<std::sync::atomic::AtomicBool>,
803 ) {
804 use futures::StreamExt;
805 use std::sync::atomic::Ordering;
806 while let Some(Ok(req)) = stream.next().await {
807 if let fidl_fuchsia_camera3::DeviceRequest::SetSoftwareMuteState { muted, responder } =
808 req
809 {
810 camera_muted.store(muted, Ordering::Relaxed);
811 let _ = responder.send();
812 }
813 }
814 }
815
816 async fn handle_camera3_device_watcher(
817 mut stream: fidl_fuchsia_camera3::DeviceWatcherRequestStream,
818 camera_muted: std::sync::Arc<std::sync::atomic::AtomicBool>,
819 ) {
820 use futures::StreamExt;
821 while let Some(Ok(req)) = stream.next().await {
822 #[allow(unreachable_patterns)]
823 match req {
824 fidl_fuchsia_camera3::DeviceWatcherRequest::WatchDevices { responder } => {
825 let _ = responder.send(&[fidl_fuchsia_camera3::WatchDevicesEvent::Added(1)]);
826 }
827 fidl_fuchsia_camera3::DeviceWatcherRequest::ConnectToDevice {
828 id: _,
829 request,
830 control_handle: _,
831 } => {
832 let camera_muted = camera_muted.clone();
833 fasync::Task::local(handle_camera3_device(request.into_stream(), camera_muted))
834 .detach();
835 }
836 _ => {}
837 }
838 }
839 }
840
841 #[fuchsia::test]
842 async fn test_set_input_states_retry_on_failure() {
848 use fidl::endpoints::DiscoverableProtocolMarker;
849 use std::sync::Arc;
850 use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
851
852 let call_count = Arc::new(AtomicUsize::new(0));
853 let call_count_clone = call_count.clone();
854
855 let camera_muted = Arc::new(AtomicBool::new(false));
856 let camera_muted_clone = camera_muted.clone();
857
858 let service_context = Rc::new(ServiceContext::new(Some(Box::new(
860 move |service_name: &str, channel: zx::Channel| {
861 let count = call_count_clone.fetch_add(1, Ordering::Relaxed);
862 let camera_muted_clone = camera_muted_clone.clone();
863 let service_name = service_name.to_string();
864 Box::pin(async move {
865 if count == 1 {
866 return Err(anyhow::Error::msg("injected failure"));
867 }
868 if service_name != fidl_fuchsia_camera3::DeviceWatcherMarker::PROTOCOL_NAME {
869 return Err(anyhow::Error::msg("unsupported service"));
870 }
871 let stream = fidl::endpoints::ServerEnd::<
872 fidl_fuchsia_camera3::DeviceWatcherMarker,
873 >::new(channel)
874 .into_stream();
875 fasync::Task::local(handle_camera3_device_watcher(stream, camera_muted_clone))
876 .detach();
877 Ok(())
878 })
879 },
880 ))));
881
882 let storage_factory = InMemoryStorageFactory::new();
884 storage_factory
885 .initialize::<InputController>()
886 .await
887 .expect("controller should have impls");
888 let (value_tx, _value_rx) = mpsc::unbounded();
889 let setting_value_publisher = SettingValuePublisher::new(value_tx);
890 let (event_tx, _event_rx) = mpsc::unbounded();
891 let external_publisher = ExternalEventPublisher::new(event_tx);
892
893 let mut controller = InputController::create_with_config::<InMemoryStorageFactory>(
894 service_context,
895 InputConfiguration {
896 devices: vec![InputDeviceConfiguration {
897 device_name: DEFAULT_CAMERA_NAME.to_string(),
898 device_type: InputDeviceType::CAMERA,
899 source_states: vec![SourceState {
900 source: DeviceStateSource::SOFTWARE,
901 state: 0, }],
903 mutable_toggle_state: 0,
904 }],
905 },
906 &storage_factory,
907 setting_value_publisher,
908 external_publisher,
909 )
910 .await;
911
912 let _ = controller.restore().await;
913
914 let camera_state = controller
916 .input_device_state
917 .get_state(InputDeviceType::CAMERA, DEFAULT_CAMERA_NAME.to_string())
918 .unwrap();
919 assert!(!camera_state.has_state(DeviceState::MUTED));
920
921 let mute_device = InputDevice {
924 name: DEFAULT_CAMERA_NAME.to_string(),
925 device_type: InputDeviceType::CAMERA,
926 source_states: [(DeviceStateSource::SOFTWARE, DeviceState::MUTED)].into(),
927 state: DeviceState::MUTED,
928 };
929
930 let res = controller
931 .set_input_states(vec![mute_device.clone()], DeviceStateSource::SOFTWARE)
932 .await;
933 assert!(res.is_err());
934 assert_eq!(call_count.load(Ordering::Relaxed), 2);
935 assert!(!camera_muted.load(Ordering::Relaxed));
936
937 let res2 =
941 controller.set_input_states(vec![mute_device], DeviceStateSource::SOFTWARE).await;
942
943 assert_eq!(call_count.load(Ordering::Relaxed), 3);
946 assert!(res2.is_ok());
947 assert!(camera_muted.load(Ordering::Relaxed));
948 }
949}