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