1use crate::input::input_device_configuration::InputConfiguration;
6use settings_common::inspect::event::Nameable;
7use settings_storage::device_storage::DeviceStorageConvertible;
8
9use anyhow::Error;
10use bitflags::bitflags;
11use fidl_fuchsia_settings::{
12 DeviceState as FidlDeviceState, DeviceStateSource as FidlDeviceStateSource,
13 DeviceType as FidlDeviceType, InputDevice as FidlInputDevice,
14 InputSettings as FidlInputSettings, SourceState as FidlSourceState,
15 ToggleStateFlags as FidlToggleFlags,
16};
17use serde::{Deserialize, Serialize};
18use std::borrow::Cow;
19use std::collections::{HashMap, HashSet};
20use std::fmt;
21
22use super::input_controller::InputError;
23
24impl From<&InputInfo> for FidlInputSettings {
25 fn from(info: &InputInfo) -> Self {
26 FidlInputSettings {
27 devices: Some(
28 info.input_device_state
29 .input_categories
30 .iter()
31 .flat_map(|(_, category)| {
32 category.devices.iter().map(|(_, device)| device.clone().into())
33 })
34 .collect(),
35 ),
36 ..Default::default()
37 }
38 }
39}
40
41#[derive(PartialEq, Debug, Clone)]
42pub struct InputInfo {
43 pub input_device_state: InputState,
44}
45
46impl Nameable for InputInfo {
47 const NAME: &str = "Input";
48}
49
50impl DeviceStorageConvertible for InputInfo {
51 type Storable = InputInfoSources;
52
53 fn get_storable(&self) -> Cow<'_, Self::Storable> {
54 Cow::Owned(InputInfoSources { input_device_state: self.input_device_state.clone() })
55 }
56}
57
58#[derive(PartialEq, Default, Debug, Clone, Serialize, Deserialize)]
59#[serde(deny_unknown_fields)]
60pub struct InputInfoSources {
61 pub input_device_state: InputState,
62}
63
64#[derive(PartialEq, Default, Debug, Clone, Copy, Serialize, Deserialize)]
65pub struct Microphone {
68 pub muted: bool,
69}
70
71#[derive(PartialEq, Debug, Default, Clone, Serialize, Deserialize)]
72pub struct InputState {
75 pub input_categories: HashMap<InputDeviceType, InputCategory>,
77}
78
79impl InputState {
80 pub(crate) fn new() -> Self {
81 Self::default()
82 }
83
84 pub(crate) fn insert_device(&mut self, input_device: InputDevice, source: DeviceStateSource) {
87 self.set_source_state(
88 input_device.device_type,
89 input_device.name,
90 source,
91 input_device.state,
92 );
93 }
94
95 pub(crate) fn set_source_state(
99 &mut self,
100 device_type: InputDeviceType,
101 device_name: String,
102 source: DeviceStateSource,
103 state: DeviceState,
104 ) {
105 let category = self.input_categories.entry(device_type).or_default();
107
108 let input_device = category
110 .devices
111 .entry(device_name.clone())
112 .or_insert_with(|| InputDevice::new(device_name, device_type));
113
114 let _ = input_device.source_states.insert(source, state);
116 input_device.compute_input_state();
117 }
118
119 pub(crate) fn get_source_state(
124 &self,
125 device_type: InputDeviceType,
126 device_name: String,
127 source: DeviceStateSource,
128 ) -> Result<DeviceState, Error> {
129 Ok(*self
130 .input_categories
131 .get(&device_type)
132 .ok_or_else(|| {
133 InputError::UnexpectedError("Failed to get input category by input type".into())
134 })?
135 .devices
136 .get(&device_name)
137 .ok_or_else(|| {
138 InputError::UnexpectedError("Failed to get input device by device name".into())
139 })?
140 .source_states
141 .get(&source)
142 .ok_or_else(|| {
143 InputError::UnexpectedError("Failed to get state from source states".into())
144 })?)
145 }
146
147 #[cfg(test)]
152 pub(crate) fn get_state(
153 &self,
154 device_type: InputDeviceType,
155 device_name: String,
156 ) -> Result<DeviceState, Error> {
157 Ok(self
158 .input_categories
159 .get(&device_type)
160 .ok_or_else(|| {
161 InputError::UnexpectedError("Failed to get input category by input type".into())
162 })?
163 .devices
164 .get(&device_name)
165 .ok_or_else(|| {
166 InputError::UnexpectedError("Failed to get input device by device name".into())
167 })?
168 .state)
169 }
170
171 pub(crate) fn is_empty(&self) -> bool {
173 self.input_categories.is_empty()
174 }
175
176 pub(crate) fn device_types(&self) -> HashSet<InputDeviceType> {
179 self.input_categories.keys().cloned().collect()
180 }
181}
182
183impl From<InputConfiguration> for InputState {
184 fn from(config: InputConfiguration) -> Self {
185 let mut categories = HashMap::<InputDeviceType, InputCategory>::new();
186 let devices = config.devices;
187
188 devices.iter().for_each(|device_config| {
189 let input_device_type = device_config.device_type;
191 let category = categories.entry(input_device_type).or_default();
192
193 let device_name = device_config.device_name.clone();
195 let device = category
196 .devices
197 .entry(device_name.clone())
198 .or_insert_with(|| InputDevice::new(device_name, input_device_type));
199
200 device_config.source_states.iter().for_each(|source_state| {
202 let value = DeviceState::from_bits(source_state.state).unwrap_or_default();
203 let _ = device.source_states.insert(source_state.source, value);
205 });
206
207 device.compute_input_state();
209 });
210 InputState { input_categories: categories }
211 }
212}
213
214#[derive(PartialEq, Debug, Default, Clone, Serialize, Deserialize)]
215pub struct InputCategory {
216 pub devices: HashMap<String, InputDevice>,
221}
222
223#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
224pub struct InputDevice {
225 pub name: String,
227
228 pub device_type: InputDeviceType,
230
231 pub source_states: HashMap<DeviceStateSource, DeviceState>,
233
234 pub state: DeviceState,
236}
237
238impl InputDevice {
239 fn new(name: String, device_type: InputDeviceType) -> Self {
240 Self {
241 name,
242 device_type,
243 source_states: HashMap::<DeviceStateSource, DeviceState>::new(),
244 state: DeviceState::new(),
245 }
246 }
247
248 fn compute_input_state(&mut self) {
249 let mut computed_state = DeviceState::from_bits(0).unwrap();
250
251 for state in self.source_states.values() {
252 if state.has_error() {
253 computed_state |= DeviceState::ERROR;
254 }
255 if state.has_state(DeviceState::DISABLED) {
256 computed_state |= DeviceState::DISABLED | DeviceState::MUTED;
257 }
258 if state.has_state(DeviceState::MUTED) {
259 computed_state |= DeviceState::MUTED;
260 }
261 if state.has_state(DeviceState::ACTIVE) {
262 computed_state |= DeviceState::ACTIVE | DeviceState::AVAILABLE;
263 }
264 }
265
266 if computed_state.has_error() {
270 self.state = DeviceState::ERROR;
271 } else if computed_state.has_state(DeviceState::DISABLED) {
272 self.state = DeviceState::DISABLED | DeviceState::MUTED;
273 } else if computed_state.has_state(DeviceState::MUTED) {
274 self.state = DeviceState::MUTED;
275 } else if computed_state.has_state(DeviceState::ACTIVE) {
276 self.state = DeviceState::ACTIVE | DeviceState::AVAILABLE;
277 } else {
278 self.state = DeviceState::AVAILABLE;
279 }
280 }
281}
282
283impl From<InputDevice> for FidlInputDevice {
284 fn from(device: InputDevice) -> Self {
285 let mut result = FidlInputDevice::default();
286
287 let source_states = Some(
289 device
290 .source_states
291 .keys()
292 .map(|source| FidlSourceState {
293 source: Some((*source).into()),
294 state: Some(
295 (*device.source_states.get(source).expect("Source state map key missing"))
296 .into(),
297 ),
298 ..Default::default()
299 })
300 .collect(),
301 );
302
303 let mutable_toggle_state: FidlDeviceState =
304 DeviceState::default_mutable_toggle_state().into();
305 result.device_name = Some(device.name.clone());
306 result.device_type = Some(device.device_type.into());
307 result.source_states = source_states;
308 result.mutable_toggle_state = mutable_toggle_state.toggle_flags;
309 result.state = Some(device.state.into());
310 result
311 }
312}
313
314#[derive(PartialEq, Eq, Debug, Copy, Clone, Hash, Serialize, Deserialize)]
315#[allow(clippy::upper_case_acronyms)]
316pub enum InputDeviceType {
317 CAMERA,
318 MICROPHONE,
319}
320
321impl fmt::Display for InputDeviceType {
329 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
330 match self {
331 InputDeviceType::CAMERA => fmt.write_str("camera"),
332 InputDeviceType::MICROPHONE => fmt.write_str("microphone"),
333 }
334 }
335}
336
337impl From<FidlDeviceType> for InputDeviceType {
338 fn from(device_type: FidlDeviceType) -> Self {
339 match device_type {
340 FidlDeviceType::Camera => InputDeviceType::CAMERA,
341 FidlDeviceType::Microphone => InputDeviceType::MICROPHONE,
342 }
343 }
344}
345
346impl From<InputDeviceType> for FidlDeviceType {
347 fn from(device_type: InputDeviceType) -> Self {
348 match device_type {
349 InputDeviceType::CAMERA => FidlDeviceType::Camera,
350 InputDeviceType::MICROPHONE => FidlDeviceType::Microphone,
351 }
352 }
353}
354
355#[derive(PartialEq, Eq, Debug, Copy, Clone, Hash, Serialize, Deserialize)]
356#[allow(clippy::upper_case_acronyms)]
357pub enum DeviceStateSource {
358 HARDWARE,
359 SOFTWARE,
360}
361
362impl From<FidlDeviceStateSource> for DeviceStateSource {
363 fn from(device_state_source: FidlDeviceStateSource) -> Self {
364 match device_state_source {
365 FidlDeviceStateSource::Hardware => DeviceStateSource::HARDWARE,
366 FidlDeviceStateSource::Software => DeviceStateSource::SOFTWARE,
367 }
368 }
369}
370
371impl From<DeviceStateSource> for FidlDeviceStateSource {
372 fn from(device_state_source: DeviceStateSource) -> Self {
373 match device_state_source {
374 DeviceStateSource::HARDWARE => FidlDeviceStateSource::Hardware,
375 DeviceStateSource::SOFTWARE => FidlDeviceStateSource::Software,
376 }
377 }
378}
379
380bitflags! {
381 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
382 pub struct DeviceState : u64 {
383 const AVAILABLE = 0b00000001;
384 const ACTIVE = 0b00000010;
385 const MUTED = 0b00000100;
386 const DISABLED = 0b00001000;
387 const ERROR = 0b00010000;
388 }
389}
390
391impl Default for DeviceState {
392 fn default() -> Self {
393 Self::new()
394 }
395}
396
397impl DeviceState {
398 pub(crate) fn new() -> Self {
399 Self::AVAILABLE
401 }
402
403 fn default_mutable_toggle_state() -> Self {
405 DeviceState::MUTED | DeviceState::DISABLED
406 }
407
408 pub(crate) fn has_state(&self, state: DeviceState) -> bool {
412 *self & state == state
413 }
414
415 fn has_error(&self) -> bool {
417 let is_err = *self & DeviceState::ERROR == DeviceState::ERROR;
418 let incompatible_state = self.has_state(DeviceState::ACTIVE | DeviceState::DISABLED)
419 || self.has_state(DeviceState::ACTIVE | DeviceState::MUTED)
420 || self.has_state(DeviceState::AVAILABLE | DeviceState::DISABLED)
421 || self.has_state(DeviceState::AVAILABLE | DeviceState::MUTED);
422 is_err || incompatible_state
423 }
424}
425
426impl From<FidlDeviceState> for DeviceState {
427 fn from(device_state: FidlDeviceState) -> Self {
428 if let Some(toggle_flags) = device_state.toggle_flags {
429 if let Some(res) = Self::from_bits(toggle_flags.bits()) {
430 return res;
431 }
432 }
433 Self::default_mutable_toggle_state()
434 }
435}
436
437impl From<DeviceState> for FidlDeviceState {
438 fn from(device_state: DeviceState) -> Self {
439 FidlDeviceState {
440 toggle_flags: FidlToggleFlags::from_bits(device_state.bits()),
441 ..Default::default()
442 }
443 }
444}
445
446bitflags_serde_legacy::impl_traits!(DeviceState);
447
448#[cfg(test)]
449mod tests {
450 use super::*;
451 use crate::input::input_device_configuration::{InputDeviceConfiguration, SourceState};
452
453 const DEFAULT_MIC_NAME: &str = "microphone";
454 const DEFAULT_CAMERA_NAME: &str = "camera";
455 const AVAILABLE_BITS: u64 = 1;
456 const MUTED_BITS: u64 = 4;
457 const MUTED_DISABLED_BITS: u64 = 12;
458
459 fn create_fidl_input_device(
461 device_name: &str,
462 device_type: FidlDeviceType,
463 sw_bits: u64,
464 hw_bits: u64,
465 overall_bits: u64,
466 ) -> FidlInputDevice {
467 FidlInputDevice {
468 device_name: Some(device_name.to_string()),
469 device_type: Some(device_type),
470 source_states: Some(vec![
471 FidlSourceState {
472 source: Some(FidlDeviceStateSource::Hardware),
473 state: Some(FidlDeviceState {
474 toggle_flags: FidlToggleFlags::from_bits(hw_bits),
475 ..Default::default()
476 }),
477 ..Default::default()
478 },
479 FidlSourceState {
480 source: Some(FidlDeviceStateSource::Software),
481 state: Some(FidlDeviceState {
482 toggle_flags: FidlToggleFlags::from_bits(sw_bits),
483 ..Default::default()
484 }),
485 ..Default::default()
486 },
487 ]),
488 mutable_toggle_state: FidlToggleFlags::from_bits(MUTED_DISABLED_BITS),
489 state: Some(FidlDeviceState {
490 toggle_flags: FidlToggleFlags::from_bits(overall_bits),
491 ..Default::default()
492 }),
493 ..Default::default()
494 }
495 }
496
497 fn create_input_device(
499 device_name: &str,
500 device_type: InputDeviceType,
501 sw_bits: u64,
502 hw_bits: u64,
503 overall_bits: u64,
504 ) -> InputDevice {
505 let mut input_device = InputDevice::new(device_name.to_string(), device_type);
506 let _ = input_device
507 .source_states
508 .insert(DeviceStateSource::SOFTWARE, DeviceState::from_bits(sw_bits).unwrap());
509 let _ = input_device
510 .source_states
511 .insert(DeviceStateSource::HARDWARE, DeviceState::from_bits(hw_bits).unwrap());
512 input_device.state = DeviceState::from_bits(overall_bits).unwrap();
513 input_device
514 }
515
516 fn create_device_config(
518 device_name: &str,
519 device_type: InputDeviceType,
520 sw_state: u64,
521 hw_state: u64,
522 ) -> InputDeviceConfiguration {
523 InputDeviceConfiguration {
524 device_name: device_name.to_string(),
525 device_type,
526 source_states: vec![
527 SourceState { source: DeviceStateSource::SOFTWARE, state: sw_state },
528 SourceState { source: DeviceStateSource::HARDWARE, state: hw_state },
529 ],
530 mutable_toggle_state: MUTED_DISABLED_BITS,
531 }
532 }
533
534 fn verify_fidl_input_device_eq(res: FidlInputDevice, expected: FidlInputDevice) {
537 assert_eq!(res.device_name, expected.device_name);
538 assert_eq!(res.device_type, expected.device_type);
539 assert_eq!(res.mutable_toggle_state, expected.mutable_toggle_state);
540 assert_eq!(res.state, expected.state);
541 let res_source_states = res.source_states.unwrap();
542 for source_state in expected.source_states.unwrap() {
543 assert!(&res_source_states.contains(&source_state));
544 }
545 }
546
547 #[fuchsia::test]
548 fn test_input_state_manipulation() {
549 let mut input_state = InputState::new();
550
551 input_state.set_source_state(
553 InputDeviceType::MICROPHONE,
554 DEFAULT_MIC_NAME.to_string(),
555 DeviceStateSource::SOFTWARE,
556 DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
557 );
558 input_state.set_source_state(
559 InputDeviceType::MICROPHONE,
560 DEFAULT_MIC_NAME.to_string(),
561 DeviceStateSource::HARDWARE,
562 DeviceState::from_bits(MUTED_BITS).unwrap(),
563 );
564 input_state.set_source_state(
565 InputDeviceType::CAMERA,
566 DEFAULT_CAMERA_NAME.to_string(),
567 DeviceStateSource::SOFTWARE,
568 DeviceState::from_bits(MUTED_BITS).unwrap(),
569 );
570 input_state.set_source_state(
571 InputDeviceType::CAMERA,
572 DEFAULT_CAMERA_NAME.to_string(),
573 DeviceStateSource::HARDWARE,
574 DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
575 );
576
577 assert_eq!(
579 input_state
580 .get_source_state(
581 InputDeviceType::MICROPHONE,
582 DEFAULT_MIC_NAME.to_string(),
583 DeviceStateSource::SOFTWARE
584 )
585 .unwrap(),
586 DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
587 );
588 assert_eq!(
589 input_state
590 .get_source_state(
591 InputDeviceType::MICROPHONE,
592 DEFAULT_MIC_NAME.to_string(),
593 DeviceStateSource::HARDWARE
594 )
595 .unwrap(),
596 DeviceState::from_bits(MUTED_BITS).unwrap(),
597 );
598 assert_eq!(
599 input_state
600 .get_source_state(
601 InputDeviceType::CAMERA,
602 DEFAULT_CAMERA_NAME.to_string(),
603 DeviceStateSource::SOFTWARE
604 )
605 .unwrap(),
606 DeviceState::from_bits(MUTED_BITS).unwrap(),
607 );
608 assert_eq!(
609 input_state
610 .get_source_state(
611 InputDeviceType::CAMERA,
612 DEFAULT_CAMERA_NAME.to_string(),
613 DeviceStateSource::HARDWARE
614 )
615 .unwrap(),
616 DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
617 );
618
619 assert_eq!(
621 input_state
622 .get_state(InputDeviceType::MICROPHONE, DEFAULT_MIC_NAME.to_string())
623 .unwrap(),
624 DeviceState::from_bits(MUTED_BITS).unwrap(),
625 );
626 assert_eq!(
627 input_state
628 .get_state(InputDeviceType::CAMERA, DEFAULT_CAMERA_NAME.to_string())
629 .unwrap(),
630 DeviceState::from_bits(MUTED_BITS).unwrap(),
631 );
632
633 input_state.set_source_state(
635 InputDeviceType::MICROPHONE,
636 DEFAULT_MIC_NAME.to_string(),
637 DeviceStateSource::HARDWARE,
638 DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
639 );
640 assert_eq!(
641 input_state
642 .get_state(InputDeviceType::MICROPHONE, DEFAULT_MIC_NAME.to_string())
643 .unwrap(),
644 DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
645 );
646
647 input_state.set_source_state(
649 InputDeviceType::CAMERA,
650 DEFAULT_CAMERA_NAME.to_string(),
651 DeviceStateSource::SOFTWARE,
652 DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
653 );
654 assert_eq!(
655 input_state
656 .get_state(InputDeviceType::CAMERA, DEFAULT_CAMERA_NAME.to_string())
657 .unwrap(),
658 DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
659 );
660 }
661
662 #[fuchsia::test]
663 fn test_input_configuration_to_input_state() {
664 let config = InputConfiguration {
665 devices: vec![
666 create_device_config(
667 DEFAULT_MIC_NAME,
668 InputDeviceType::MICROPHONE,
669 MUTED_BITS,
670 AVAILABLE_BITS,
671 ),
672 create_device_config(
673 DEFAULT_CAMERA_NAME,
674 InputDeviceType::CAMERA,
675 AVAILABLE_BITS,
676 AVAILABLE_BITS,
677 ),
678 create_device_config(
679 "camera2",
680 InputDeviceType::CAMERA,
681 AVAILABLE_BITS,
682 MUTED_DISABLED_BITS,
683 ),
684 ],
685 };
686 let result: InputState = config.into();
687 assert_eq!(
688 result
689 .get_source_state(
690 InputDeviceType::MICROPHONE,
691 DEFAULT_MIC_NAME.to_string(),
692 DeviceStateSource::SOFTWARE,
693 )
694 .unwrap(),
695 DeviceState::from_bits(MUTED_BITS).unwrap(),
696 );
697 assert_eq!(
698 result
699 .get_source_state(
700 InputDeviceType::MICROPHONE,
701 DEFAULT_MIC_NAME.to_string(),
702 DeviceStateSource::HARDWARE,
703 )
704 .unwrap(),
705 DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
706 );
707 assert_eq!(
708 result
709 .get_source_state(
710 InputDeviceType::CAMERA,
711 DEFAULT_CAMERA_NAME.to_string(),
712 DeviceStateSource::SOFTWARE,
713 )
714 .unwrap(),
715 DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
716 );
717 assert_eq!(
718 result
719 .get_source_state(
720 InputDeviceType::CAMERA,
721 DEFAULT_CAMERA_NAME.to_string(),
722 DeviceStateSource::HARDWARE,
723 )
724 .unwrap(),
725 DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
726 );
727 assert_eq!(
728 result
729 .get_source_state(
730 InputDeviceType::CAMERA,
731 "camera2".to_string(),
732 DeviceStateSource::SOFTWARE,
733 )
734 .unwrap(),
735 DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
736 );
737 assert_eq!(
738 result
739 .get_source_state(
740 InputDeviceType::CAMERA,
741 "camera2".to_string(),
742 DeviceStateSource::HARDWARE,
743 )
744 .unwrap(),
745 DeviceState::from_bits(MUTED_DISABLED_BITS).unwrap(),
746 );
747 }
748
749 #[fuchsia::test]
750 fn test_overall_state() {
753 let mut mic_available = create_input_device(
756 DEFAULT_MIC_NAME,
757 InputDeviceType::MICROPHONE,
758 AVAILABLE_BITS,
759 AVAILABLE_BITS,
760 AVAILABLE_BITS,
761 );
762 let mut mic_disabled = create_input_device(
763 DEFAULT_MIC_NAME,
764 InputDeviceType::MICROPHONE,
765 MUTED_DISABLED_BITS,
766 AVAILABLE_BITS,
767 MUTED_DISABLED_BITS,
768 );
769 let mut mic_muted = create_input_device(
770 DEFAULT_MIC_NAME,
771 InputDeviceType::MICROPHONE,
772 AVAILABLE_BITS,
773 MUTED_BITS,
774 MUTED_BITS,
775 );
776 let mut mic_active = create_input_device(
777 DEFAULT_MIC_NAME,
778 InputDeviceType::MICROPHONE,
779 3,
780 AVAILABLE_BITS,
781 3,
782 );
783 let mut mic_error = create_input_device(
784 DEFAULT_MIC_NAME,
785 InputDeviceType::MICROPHONE,
786 10,
787 AVAILABLE_BITS,
788 16,
789 );
790
791 mic_available.compute_input_state();
792 mic_disabled.compute_input_state();
793 mic_muted.compute_input_state();
794 mic_active.compute_input_state();
795 mic_error.compute_input_state();
796
797 assert_eq!(mic_available.state, DeviceState::AVAILABLE);
798 assert_eq!(mic_disabled.state, DeviceState::DISABLED | DeviceState::MUTED);
799 assert_eq!(mic_muted.state, DeviceState::MUTED);
800 assert_eq!(mic_active.state, DeviceState::ACTIVE | DeviceState::AVAILABLE);
801 assert_eq!(mic_error.state, DeviceState::ERROR);
802 }
803
804 #[fuchsia::test]
805 fn test_input_device_to_fidl_input_device() {
806 let expected_mic: FidlInputDevice = create_fidl_input_device(
807 DEFAULT_MIC_NAME,
808 FidlDeviceType::Microphone,
809 AVAILABLE_BITS,
810 AVAILABLE_BITS,
811 AVAILABLE_BITS,
812 );
813 let expected_cam: FidlInputDevice = create_fidl_input_device(
814 DEFAULT_CAMERA_NAME,
815 FidlDeviceType::Camera,
816 AVAILABLE_BITS,
817 MUTED_BITS,
818 MUTED_BITS,
819 );
820
821 let mut mic = InputDevice::new(DEFAULT_MIC_NAME.to_string(), InputDeviceType::MICROPHONE);
822 let _ = mic
823 .source_states
824 .insert(DeviceStateSource::SOFTWARE, DeviceState::from_bits(AVAILABLE_BITS).unwrap());
825 let _ = mic
826 .source_states
827 .insert(DeviceStateSource::HARDWARE, DeviceState::from_bits(AVAILABLE_BITS).unwrap());
828 mic.state = DeviceState::from_bits(AVAILABLE_BITS).unwrap();
829
830 let mut cam = InputDevice::new(DEFAULT_CAMERA_NAME.to_string(), InputDeviceType::CAMERA);
831 let _ = cam
832 .source_states
833 .insert(DeviceStateSource::SOFTWARE, DeviceState::from_bits(AVAILABLE_BITS).unwrap());
834 let _ = cam
835 .source_states
836 .insert(DeviceStateSource::HARDWARE, DeviceState::from_bits(MUTED_BITS).unwrap());
837 cam.state = DeviceState::from_bits(MUTED_BITS).unwrap();
838
839 let mic_res: FidlInputDevice = mic.into();
840 let cam_res: FidlInputDevice = cam.into();
841
842 verify_fidl_input_device_eq(mic_res, expected_mic);
843 verify_fidl_input_device_eq(cam_res, expected_cam);
844 }
845
846 #[fuchsia::test]
847 fn test_input_device_type_to_string() {
848 assert_eq!(InputDeviceType::CAMERA.to_string(), DEFAULT_CAMERA_NAME);
849 assert_eq!(InputDeviceType::MICROPHONE.to_string(), DEFAULT_MIC_NAME);
850 }
851
852 #[fuchsia::test]
853 fn test_fidl_device_type_to_device_type() {
854 let cam_res: FidlDeviceType = InputDeviceType::CAMERA.into();
855 let mic_res: FidlDeviceType = InputDeviceType::MICROPHONE.into();
856 assert_eq!(cam_res, FidlDeviceType::Camera);
857 assert_eq!(mic_res, FidlDeviceType::Microphone);
858 }
859
860 #[fuchsia::test]
861 fn test_device_type_to_fidl_device_type() {
862 let cam_res: InputDeviceType = FidlDeviceType::Camera.into();
863 let mic_res: InputDeviceType = FidlDeviceType::Microphone.into();
864 assert_eq!(cam_res, InputDeviceType::CAMERA);
865 assert_eq!(mic_res, InputDeviceType::MICROPHONE);
866 }
867
868 #[fuchsia::test]
869 fn test_fidl_device_state_source_to_device_state_source() {
870 let hw_res: FidlDeviceStateSource = DeviceStateSource::HARDWARE.into();
871 let sw_res: FidlDeviceStateSource = DeviceStateSource::SOFTWARE.into();
872 assert_eq!(hw_res, FidlDeviceStateSource::Hardware);
873 assert_eq!(sw_res, FidlDeviceStateSource::Software);
874 }
875
876 #[fuchsia::test]
877 fn test_device_state_source_to_fidl_device_state_source() {
878 let hw_res: DeviceStateSource = FidlDeviceStateSource::Hardware.into();
879 let sw_res: DeviceStateSource = FidlDeviceStateSource::Software.into();
880 assert_eq!(hw_res, DeviceStateSource::HARDWARE);
881 assert_eq!(sw_res, DeviceStateSource::SOFTWARE);
882 }
883
884 #[fuchsia::test]
885 fn test_device_state_errors() {
886 let available_disabled = DeviceState::from_bits(9).unwrap();
887 let available_muted = DeviceState::from_bits(5).unwrap();
888 let active_muted = DeviceState::from_bits(6).unwrap();
889 let active_disabled = DeviceState::from_bits(10).unwrap();
890 assert!(available_disabled.has_error());
891 assert!(available_muted.has_error());
892 assert!(active_muted.has_error());
893 assert!(active_disabled.has_error());
894 }
895
896 #[fuchsia::test]
897 fn test_fidl_device_state_to_device_state() {
898 let device_state: DeviceState = FidlDeviceState {
899 toggle_flags: FidlToggleFlags::from_bits(MUTED_BITS),
900 ..Default::default()
901 }
902 .into();
903 assert_eq!(device_state, DeviceState::from_bits(MUTED_BITS).unwrap(),);
904 }
905
906 #[fuchsia::test]
907 fn test_device_state_to_fidl_device_state() {
908 let fidl_device_state: FidlDeviceState = DeviceState::from_bits(MUTED_BITS).unwrap().into();
909 assert_eq!(
910 fidl_device_state,
911 FidlDeviceState {
912 toggle_flags: FidlToggleFlags::from_bits(MUTED_BITS),
913 ..Default::default()
914 }
915 );
916 }
917}