blob: 549a8a11c3958d202b8f65ac73c14ec457311801 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::base::SettingInfo;
use crate::handler::device_storage::DeviceStorageConvertible;
use crate::handler::setting_handler::ControllerError;
use crate::input::input_device_configuration::InputConfiguration;
use anyhow::Error;
use bitflags::bitflags;
use fidl_fuchsia_settings::{
DeviceState as FidlDeviceState, DeviceStateSource as FidlDeviceStateSource,
DeviceType as FidlDeviceType, InputDevice as FidlInputDevice,
InputSettings as FidlInputSettings, SourceState as FidlSourceState,
ToggleStateFlags as FidlToggleFlags,
};
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use std::collections::{HashMap, HashSet};
use std::fmt;
impl From<SettingInfo> for FidlInputSettings {
fn from(response: SettingInfo) -> Self {
if let SettingInfo::Input(info) = response {
let mut input_settings = FidlInputSettings::EMPTY;
let mut input_devices: Vec<FidlInputDevice> = Vec::new();
info.input_device_state.input_categories.iter().for_each(|(_, category)| {
category.devices.iter().for_each(|(_, device)| {
input_devices.push(device.clone().into());
})
});
input_settings.devices = Some(input_devices);
input_settings
} else {
panic!("Incorrect value sent to input");
}
}
}
#[derive(PartialEq, Debug, Clone)]
pub struct InputInfo {
pub input_device_state: InputState,
}
impl DeviceStorageConvertible for InputInfo {
type Storable = InputInfoSources;
fn get_storable(&self) -> Cow<'_, Self::Storable> {
Cow::Owned(InputInfoSources { input_device_state: self.input_device_state.clone() })
}
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct InputInfoSources {
pub input_device_state: InputState,
}
#[derive(PartialEq, Debug, Clone, Copy, Serialize, Deserialize)]
// DO NOT USE - this type is deprecated and will be replaced by
// the use of InputDevice.
pub struct Microphone {
pub muted: bool,
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
/// The top-level struct for the input state. It categorizes the input devices
/// by their device type.
pub struct InputState {
/// The input devices categorized by device type.
pub input_categories: HashMap<InputDeviceType, InputCategory>,
}
impl InputState {
pub fn new() -> Self {
Self { input_categories: HashMap::<InputDeviceType, InputCategory>::new() }
}
/// Insert an InputDevice's state into the internal InputState hierarchy, updating the
/// state if it already exists or adding the state if it does not.
pub fn insert_device(&mut self, input_device: InputDevice, source: DeviceStateSource) {
self.set_source_state(
input_device.device_type,
input_device.name,
source,
input_device.state,
);
}
/// Set the `state` for a given device and `source`.
/// The combination of `device_type` and `device_name`
/// uniquely identifies the device.
pub fn set_source_state(
&mut self,
device_type: InputDeviceType,
device_name: String,
source: DeviceStateSource,
state: DeviceState,
) {
// Ensure the category has an entry in the categories map.
let category = self.input_categories.entry(device_type).or_insert(InputCategory::new());
// Ensure the device has an entry in the devices map.
let input_device = category
.devices
.entry(device_name.clone())
.or_insert(InputDevice::new(device_name.clone(), device_type));
// Replace or add the source state in the map.
input_device.source_states.insert(source, state);
input_device.compute_input_state();
}
/// Retrieve the state of a given device for one of its `source`s.
/// The combination of `device_type` and `device_name`
/// uniquely identifies the device. Returns None if it fails to find
/// the corresponding state for the given arguments.
pub fn get_source_state(
&self,
device_type: InputDeviceType,
device_name: String,
source: DeviceStateSource,
) -> Result<DeviceState, Error> {
return Ok(self
.input_categories
.get(&device_type)
.ok_or(ControllerError::UnexpectedError(
"Failed to get input category by input type".into(),
))?
.devices
.get(&device_name)
.ok_or(ControllerError::UnexpectedError(
"Failed to get input device by device name".into(),
))?
.source_states
.get(&source)
.ok_or(ControllerError::UnexpectedError(
"Failed to get state from source states".into(),
))?
.clone());
}
/// Retrieve the overall state of a given device.
/// The combination of `device_type` and `device_name`
/// uniquely identifies the device. Returns None if it fails to find
/// the corresponding state for the given arguments.
pub fn get_state(
&self,
device_type: InputDeviceType,
device_name: String,
) -> Result<DeviceState, Error> {
return Ok(self
.input_categories
.get(&device_type)
.ok_or(ControllerError::UnexpectedError(
"Failed to get input category by input type".into(),
))?
.devices
.get(&device_name)
.ok_or(ControllerError::UnexpectedError(
"Failed to get input device by device name".into(),
))?
.state
.clone());
}
/// Returns true if the state map is empty.
pub fn is_empty(&self) -> bool {
self.input_categories.is_empty()
}
/// Returns a set of the `InputDeviceType`s contained in the
/// state map.
pub fn device_types(&self) -> HashSet<InputDeviceType> {
self.input_categories.keys().cloned().collect()
}
}
impl From<InputConfiguration> for InputState {
fn from(config: InputConfiguration) -> Self {
let mut categories = HashMap::<InputDeviceType, InputCategory>::new();
let devices = config.devices;
devices.iter().for_each(|device_config| {
// Ensure the category has an entry in the categories map.
let input_device_type = device_config.device_type;
let category = categories.entry(input_device_type).or_insert(InputCategory::new());
// Ensure the device has an entry in the devices map.
let device_name = device_config.device_name.clone();
let device = category
.devices
.entry(device_name.clone())
.or_insert(InputDevice::new(device_name.clone(), input_device_type));
// Set the entry on the source states map.
device_config.source_states.iter().for_each(|source_state| {
let value =
DeviceState::from_bits(source_state.state).unwrap_or(DeviceState::new());
device.source_states.insert(source_state.source, value);
});
// Recompute the overall state.
device.compute_input_state();
});
InputState { input_categories: categories }
}
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct InputCategory {
// Map of input devices in this category, identified by names.
// It is recommended that the name be the lower-case string
// representation of the device type if there is only one input
// device in this category.
pub devices: HashMap<String, InputDevice>,
}
impl InputCategory {
pub fn new() -> Self {
Self { devices: HashMap::<String, InputDevice>::new() }
}
}
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct InputDevice {
/// The unique name within the device type.
pub name: String,
/// The type of input device.
pub device_type: InputDeviceType,
/// The states for each source.
pub source_states: HashMap<DeviceStateSource, DeviceState>,
/// The overall state of the device considering the `source_state`s.
pub state: DeviceState,
}
impl InputDevice {
pub fn new(name: String, device_type: InputDeviceType) -> Self {
Self {
name,
device_type,
source_states: HashMap::<DeviceStateSource, DeviceState>::new(),
state: DeviceState::new(),
}
}
pub fn compute_input_state(&mut self) {
let mut computed_state = DeviceState::from_bits(0).unwrap();
for state in self.source_states.values() {
if state.has_error() {
computed_state |= DeviceState::ERROR;
}
if state.has_state(DeviceState::DISABLED) {
computed_state |= DeviceState::DISABLED | DeviceState::MUTED;
}
if state.has_state(DeviceState::MUTED) {
computed_state |= DeviceState::MUTED;
}
if state.has_state(DeviceState::ACTIVE) {
computed_state |= DeviceState::ACTIVE | DeviceState::AVAILABLE;
}
}
// If any source has ERROR, DISABLED, MUTED, or ACTIVE, the overall
// state is that state, in order of precedence. Otherwise, the overall state
// is AVAILABLE.
if computed_state.has_error() {
self.state = DeviceState::ERROR;
} else if computed_state.has_state(DeviceState::DISABLED) {
self.state = DeviceState::DISABLED | DeviceState::MUTED;
} else if computed_state.has_state(DeviceState::MUTED) {
self.state = DeviceState::MUTED;
} else if computed_state.has_state(DeviceState::ACTIVE) {
self.state = DeviceState::ACTIVE | DeviceState::AVAILABLE;
} else {
self.state = DeviceState::AVAILABLE;
}
}
}
impl From<InputDevice> for FidlInputDevice {
fn from(device: InputDevice) -> Self {
let mut result = FidlInputDevice::EMPTY;
// Convert source states.
let source_state_map = device.source_states.clone();
let source_states = Some(
source_state_map
.keys()
.into_iter()
.map(|source| {
let mut source_state = FidlSourceState::EMPTY;
source_state.source = Some(source.clone().into());
source_state.state = Some(
source_state_map
.get(&source)
.expect("Source state map key missing")
.clone()
.into(),
);
return source_state;
})
.collect(),
);
let mutable_toggle_state: FidlDeviceState =
DeviceState::default_mutable_toggle_state().into();
result.device_name = Some(device.name.clone());
result.device_type = Some(device.device_type.into());
result.source_states = source_states;
result.mutable_toggle_state = mutable_toggle_state.toggle_flags;
result.state = Some(device.state.into());
result
}
}
#[derive(PartialEq, Eq, Debug, Copy, Clone, Hash, Serialize, Deserialize)]
pub enum InputDeviceType {
CAMERA,
MICROPHONE,
}
/// Instead of defining our own fmt function, an easier way
/// is to derive the 'Display' trait for enums using `enum-display-derive` crate
///
/// https://docs.rs/enum-display-derive/0.1.0/enum_display_derive/
///
/// Since addition of this in third_party/rust_crates needs OSRB approval, we
/// define our own function here.
impl fmt::Display for InputDeviceType {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
InputDeviceType::CAMERA => fmt.write_str("camera"),
InputDeviceType::MICROPHONE => fmt.write_str("microphone"),
}
}
}
impl From<FidlDeviceType> for InputDeviceType {
fn from(device_type: FidlDeviceType) -> Self {
match device_type {
FidlDeviceType::Camera => InputDeviceType::CAMERA,
FidlDeviceType::Microphone => InputDeviceType::MICROPHONE,
}
}
}
impl From<InputDeviceType> for FidlDeviceType {
fn from(device_type: InputDeviceType) -> Self {
match device_type {
InputDeviceType::CAMERA => FidlDeviceType::Camera,
InputDeviceType::MICROPHONE => FidlDeviceType::Microphone,
}
}
}
#[derive(PartialEq, Eq, Debug, Copy, Clone, Hash, Serialize, Deserialize)]
pub enum DeviceStateSource {
HARDWARE,
SOFTWARE,
}
impl From<FidlDeviceStateSource> for DeviceStateSource {
fn from(device_state_source: FidlDeviceStateSource) -> Self {
match device_state_source {
FidlDeviceStateSource::Hardware => DeviceStateSource::HARDWARE,
FidlDeviceStateSource::Software => DeviceStateSource::SOFTWARE,
}
}
}
impl From<DeviceStateSource> for FidlDeviceStateSource {
fn from(device_state_source: DeviceStateSource) -> Self {
match device_state_source {
DeviceStateSource::HARDWARE => FidlDeviceStateSource::Hardware,
DeviceStateSource::SOFTWARE => FidlDeviceStateSource::Software,
}
}
}
// TODO(fxbug.dev/67156): Add a "BLOCKED" flag to represent policy-driven
// disabling. "DISABLED" also needs to track "MUTED", as it will eventually
// be its replacement. This should also be done for the FIDL.
bitflags! {
#[derive(Serialize, Deserialize)]
pub struct DeviceState : u64 {
const AVAILABLE = 0b00000001;
const ACTIVE = 0b00000010;
const MUTED = 0b00000100;
const DISABLED = 0b00001000;
const ERROR = 0b00010000;
}
}
impl DeviceState {
pub fn new() -> Self {
// Represents AVAILABLE as the default.
Self { bits: 1 }
}
/// The flags that clients can manipulate by default.
pub fn default_mutable_toggle_state() -> Self {
DeviceState::MUTED | DeviceState::DISABLED
}
/// Returns true if the current state contains the given state.
/// e.g. All the 1 bits in the given `state` are also 1s in the
/// current state.
pub fn has_state(&self, state: DeviceState) -> bool {
return *self & state == state;
}
/// Returns true if the device's state has an error.
pub fn has_error(&self) -> bool {
let is_err = *self & DeviceState::ERROR == DeviceState::ERROR;
let incompatible_state = self.has_state(DeviceState::ACTIVE | DeviceState::DISABLED)
|| self.has_state(DeviceState::ACTIVE | DeviceState::MUTED)
|| self.has_state(DeviceState::AVAILABLE | DeviceState::DISABLED)
|| self.has_state(DeviceState::AVAILABLE | DeviceState::MUTED);
is_err || incompatible_state
}
}
impl From<FidlDeviceState> for DeviceState {
fn from(device_state: FidlDeviceState) -> Self {
if let Some(toggle_flags) = device_state.toggle_flags {
if let Some(res) = Self::from_bits(toggle_flags.bits()) {
return res;
}
}
Self::default_mutable_toggle_state()
}
}
impl From<DeviceState> for FidlDeviceState {
fn from(device_state: DeviceState) -> Self {
let mut state = FidlDeviceState::EMPTY;
state.toggle_flags = FidlToggleFlags::from_bits(device_state.bits);
state
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::input::input_device_configuration::{
InputConfiguration, InputDeviceConfiguration, SourceState,
};
const DEFAULT_MIC_NAME: &str = "microphone";
const DEFAULT_CAMERA_NAME: &str = "camera";
const AVAILABLE_BITS: u64 = 1;
const MUTED_BITS: u64 = 4;
const MUTED_DISABLED_BITS: u64 = 12;
/// Helper to create a `FidlInputDevice`.
fn create_fidl_input_device(
device_name: &str,
device_type: FidlDeviceType,
sw_bits: u64,
hw_bits: u64,
overall_bits: u64,
) -> FidlInputDevice {
FidlInputDevice {
device_name: Some(device_name.to_string()),
device_type: Some(device_type),
source_states: Some(vec![
FidlSourceState {
source: Some(FidlDeviceStateSource::Hardware),
state: Some(FidlDeviceState {
toggle_flags: FidlToggleFlags::from_bits(hw_bits),
..FidlDeviceState::EMPTY
}),
..FidlSourceState::EMPTY
},
FidlSourceState {
source: Some(FidlDeviceStateSource::Software),
state: Some(FidlDeviceState {
toggle_flags: FidlToggleFlags::from_bits(sw_bits),
..FidlDeviceState::EMPTY
}),
..FidlSourceState::EMPTY
},
]),
mutable_toggle_state: FidlToggleFlags::from_bits(MUTED_DISABLED_BITS),
state: Some(FidlDeviceState {
toggle_flags: FidlToggleFlags::from_bits(overall_bits),
..FidlDeviceState::EMPTY
}),
..FidlInputDevice::EMPTY
}
}
/// Helper to create an [`InputDevice`].
fn create_input_device(
device_name: &str,
device_type: InputDeviceType,
sw_bits: u64,
hw_bits: u64,
overall_bits: u64,
) -> InputDevice {
let mut input_device = InputDevice::new(device_name.to_string(), device_type);
input_device
.source_states
.insert(DeviceStateSource::SOFTWARE, DeviceState::from_bits(sw_bits).unwrap());
input_device
.source_states
.insert(DeviceStateSource::HARDWARE, DeviceState::from_bits(hw_bits).unwrap());
input_device.state = DeviceState::from_bits(overall_bits).unwrap();
input_device
}
/// Helper for creating the config for an `InputDevice`.
fn create_device_config(
device_name: &str,
device_type: InputDeviceType,
sw_state: u64,
hw_state: u64,
) -> InputDeviceConfiguration {
InputDeviceConfiguration {
device_name: device_name.to_string(),
device_type: device_type,
source_states: vec![
SourceState { source: DeviceStateSource::SOFTWARE, state: sw_state },
SourceState { source: DeviceStateSource::HARDWARE, state: hw_state },
],
mutable_toggle_state: MUTED_DISABLED_BITS,
}
}
/// Helper for verifying the equality of a `FidlInputDevice`. Cannot directly
/// compare because the order of the source_states vector may vary.
fn verify_fidl_input_device_eq(res: FidlInputDevice, expected: FidlInputDevice) {
assert_eq!(res.device_name, expected.device_name);
assert_eq!(res.device_type, expected.device_type);
assert_eq!(res.mutable_toggle_state, expected.mutable_toggle_state);
assert_eq!(res.state, expected.state);
let res_source_states = res.source_states.unwrap();
for source_state in expected.source_states.unwrap() {
assert!(&res_source_states.contains(&source_state));
}
}
#[test]
fn test_input_state_manipulation() {
let mut input_state = InputState::new();
// Set the source state for each source and device type.
input_state.set_source_state(
InputDeviceType::MICROPHONE,
DEFAULT_MIC_NAME.to_string(),
DeviceStateSource::SOFTWARE,
DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
);
input_state.set_source_state(
InputDeviceType::MICROPHONE,
DEFAULT_MIC_NAME.to_string(),
DeviceStateSource::HARDWARE,
DeviceState::from_bits(MUTED_BITS).unwrap(),
);
input_state.set_source_state(
InputDeviceType::CAMERA,
DEFAULT_CAMERA_NAME.to_string(),
DeviceStateSource::SOFTWARE,
DeviceState::from_bits(MUTED_BITS).unwrap(),
);
input_state.set_source_state(
InputDeviceType::CAMERA,
DEFAULT_CAMERA_NAME.to_string(),
DeviceStateSource::HARDWARE,
DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
);
// Get the source state for each source and device type.
assert_eq!(
input_state
.get_source_state(
InputDeviceType::MICROPHONE,
DEFAULT_MIC_NAME.to_string(),
DeviceStateSource::SOFTWARE
)
.unwrap(),
DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
);
assert_eq!(
input_state
.get_source_state(
InputDeviceType::MICROPHONE,
DEFAULT_MIC_NAME.to_string(),
DeviceStateSource::HARDWARE
)
.unwrap(),
DeviceState::from_bits(MUTED_BITS).unwrap(),
);
assert_eq!(
input_state
.get_source_state(
InputDeviceType::CAMERA,
DEFAULT_CAMERA_NAME.to_string(),
DeviceStateSource::SOFTWARE
)
.unwrap(),
DeviceState::from_bits(MUTED_BITS).unwrap(),
);
assert_eq!(
input_state
.get_source_state(
InputDeviceType::CAMERA,
DEFAULT_CAMERA_NAME.to_string(),
DeviceStateSource::HARDWARE
)
.unwrap(),
DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
);
// Get the overall states for each device.
assert_eq!(
input_state
.get_state(InputDeviceType::MICROPHONE, DEFAULT_MIC_NAME.to_string())
.unwrap(),
DeviceState::from_bits(MUTED_BITS).unwrap(),
);
assert_eq!(
input_state
.get_state(InputDeviceType::CAMERA, DEFAULT_CAMERA_NAME.to_string())
.unwrap(),
DeviceState::from_bits(MUTED_BITS).unwrap(),
);
// Switch the mic hardware on.
input_state.set_source_state(
InputDeviceType::MICROPHONE,
DEFAULT_MIC_NAME.to_string(),
DeviceStateSource::HARDWARE,
DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
);
assert_eq!(
input_state
.get_state(InputDeviceType::MICROPHONE, DEFAULT_MIC_NAME.to_string())
.unwrap(),
DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
);
// Switch the camera software on.
input_state.set_source_state(
InputDeviceType::CAMERA,
DEFAULT_CAMERA_NAME.to_string(),
DeviceStateSource::SOFTWARE,
DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
);
assert_eq!(
input_state
.get_state(InputDeviceType::CAMERA, DEFAULT_CAMERA_NAME.to_string())
.unwrap(),
DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
);
}
#[test]
fn test_input_configuration_to_input_state() {
let config = InputConfiguration {
devices: vec![
create_device_config(
DEFAULT_MIC_NAME,
InputDeviceType::MICROPHONE,
MUTED_BITS,
AVAILABLE_BITS,
),
create_device_config(
DEFAULT_CAMERA_NAME,
InputDeviceType::CAMERA,
AVAILABLE_BITS,
AVAILABLE_BITS,
),
create_device_config(
"camera2",
InputDeviceType::CAMERA,
AVAILABLE_BITS,
MUTED_DISABLED_BITS,
),
],
};
let result: InputState = config.into();
assert_eq!(
result
.get_source_state(
InputDeviceType::MICROPHONE,
DEFAULT_MIC_NAME.to_string(),
DeviceStateSource::SOFTWARE,
)
.unwrap(),
DeviceState::from_bits(MUTED_BITS).unwrap(),
);
assert_eq!(
result
.get_source_state(
InputDeviceType::MICROPHONE,
DEFAULT_MIC_NAME.to_string(),
DeviceStateSource::HARDWARE,
)
.unwrap(),
DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
);
assert_eq!(
result
.get_source_state(
InputDeviceType::CAMERA,
DEFAULT_CAMERA_NAME.to_string(),
DeviceStateSource::SOFTWARE,
)
.unwrap(),
DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
);
assert_eq!(
result
.get_source_state(
InputDeviceType::CAMERA,
DEFAULT_CAMERA_NAME.to_string(),
DeviceStateSource::HARDWARE,
)
.unwrap(),
DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
);
assert_eq!(
result
.get_source_state(
InputDeviceType::CAMERA,
"camera2".to_string(),
DeviceStateSource::SOFTWARE,
)
.unwrap(),
DeviceState::from_bits(AVAILABLE_BITS).unwrap(),
);
assert_eq!(
result
.get_source_state(
InputDeviceType::CAMERA,
"camera2".to_string(),
DeviceStateSource::HARDWARE,
)
.unwrap(),
DeviceState::from_bits(MUTED_DISABLED_BITS).unwrap(),
);
}
#[test]
/// Test that the combination of the input device's source states results
/// in the correct overall device state.
fn test_overall_state() {
// The last number doesn't matter here, it will be overwritten by the
// compute_input_state calls.
let mut mic_available = create_input_device(
DEFAULT_MIC_NAME,
InputDeviceType::MICROPHONE,
AVAILABLE_BITS,
AVAILABLE_BITS,
AVAILABLE_BITS,
);
let mut mic_disabled = create_input_device(
DEFAULT_MIC_NAME,
InputDeviceType::MICROPHONE,
MUTED_DISABLED_BITS,
AVAILABLE_BITS,
MUTED_DISABLED_BITS,
);
let mut mic_muted = create_input_device(
DEFAULT_MIC_NAME,
InputDeviceType::MICROPHONE,
AVAILABLE_BITS,
MUTED_BITS,
MUTED_BITS,
);
let mut mic_active = create_input_device(
DEFAULT_MIC_NAME,
InputDeviceType::MICROPHONE,
3,
AVAILABLE_BITS,
3,
);
let mut mic_error = create_input_device(
DEFAULT_MIC_NAME,
InputDeviceType::MICROPHONE,
10,
AVAILABLE_BITS,
16,
);
mic_available.compute_input_state();
mic_disabled.compute_input_state();
mic_muted.compute_input_state();
mic_active.compute_input_state();
mic_error.compute_input_state();
assert_eq!(mic_available.state, DeviceState::AVAILABLE);
assert_eq!(mic_disabled.state, DeviceState::DISABLED | DeviceState::MUTED);
assert_eq!(mic_muted.state, DeviceState::MUTED);
assert_eq!(mic_active.state, DeviceState::ACTIVE | DeviceState::AVAILABLE);
assert_eq!(mic_error.state, DeviceState::ERROR);
}
#[test]
fn test_input_device_to_fidl_input_device() {
let expected_mic: FidlInputDevice = create_fidl_input_device(
DEFAULT_MIC_NAME,
FidlDeviceType::Microphone,
AVAILABLE_BITS,
AVAILABLE_BITS,
AVAILABLE_BITS,
);
let expected_cam: FidlInputDevice = create_fidl_input_device(
DEFAULT_CAMERA_NAME,
FidlDeviceType::Camera,
AVAILABLE_BITS,
MUTED_BITS,
MUTED_BITS,
);
let mut mic = InputDevice::new(DEFAULT_MIC_NAME.to_string(), InputDeviceType::MICROPHONE);
mic.source_states
.insert(DeviceStateSource::SOFTWARE, DeviceState::from_bits(AVAILABLE_BITS).unwrap());
mic.source_states
.insert(DeviceStateSource::HARDWARE, DeviceState::from_bits(AVAILABLE_BITS).unwrap());
mic.state = DeviceState::from_bits(AVAILABLE_BITS).unwrap();
let mut cam = InputDevice::new(DEFAULT_CAMERA_NAME.to_string(), InputDeviceType::CAMERA);
cam.source_states
.insert(DeviceStateSource::SOFTWARE, DeviceState::from_bits(AVAILABLE_BITS).unwrap());
cam.source_states
.insert(DeviceStateSource::HARDWARE, DeviceState::from_bits(MUTED_BITS).unwrap());
cam.state = DeviceState::from_bits(MUTED_BITS).unwrap();
let mic_res: FidlInputDevice = mic.into();
let cam_res: FidlInputDevice = cam.into();
verify_fidl_input_device_eq(mic_res, expected_mic);
verify_fidl_input_device_eq(cam_res, expected_cam);
}
#[test]
fn test_input_device_type_to_string() {
assert_eq!(InputDeviceType::CAMERA.to_string(), DEFAULT_CAMERA_NAME);
assert_eq!(InputDeviceType::MICROPHONE.to_string(), DEFAULT_MIC_NAME);
}
#[test]
fn test_fidl_device_type_to_device_type() {
let cam_res: FidlDeviceType = InputDeviceType::CAMERA.into();
let mic_res: FidlDeviceType = InputDeviceType::MICROPHONE.into();
assert_eq!(cam_res, FidlDeviceType::Camera);
assert_eq!(mic_res, FidlDeviceType::Microphone);
}
#[test]
fn test_device_type_to_fidl_device_type() {
let cam_res: InputDeviceType = FidlDeviceType::Camera.into();
let mic_res: InputDeviceType = FidlDeviceType::Microphone.into();
assert_eq!(cam_res, InputDeviceType::CAMERA);
assert_eq!(mic_res, InputDeviceType::MICROPHONE);
}
#[test]
fn test_fidl_device_state_source_to_device_state_source() {
let hw_res: FidlDeviceStateSource = DeviceStateSource::HARDWARE.into();
let sw_res: FidlDeviceStateSource = DeviceStateSource::SOFTWARE.into();
assert_eq!(hw_res, FidlDeviceStateSource::Hardware);
assert_eq!(sw_res, FidlDeviceStateSource::Software);
}
#[test]
fn test_device_state_source_to_fidl_device_state_source() {
let hw_res: DeviceStateSource = FidlDeviceStateSource::Hardware.into();
let sw_res: DeviceStateSource = FidlDeviceStateSource::Software.into();
assert_eq!(hw_res, DeviceStateSource::HARDWARE);
assert_eq!(sw_res, DeviceStateSource::SOFTWARE);
}
#[test]
fn test_device_state_errors() {
let available_disabled = DeviceState::from_bits(9).unwrap();
let available_muted = DeviceState::from_bits(5).unwrap();
let active_muted = DeviceState::from_bits(6).unwrap();
let active_disabled = DeviceState::from_bits(10).unwrap();
assert!(available_disabled.has_error());
assert!(available_muted.has_error());
assert!(active_muted.has_error());
assert!(active_disabled.has_error());
}
#[test]
fn test_fidl_device_state_to_device_state() {
let device_state: DeviceState = FidlDeviceState {
toggle_flags: FidlToggleFlags::from_bits(MUTED_BITS),
..FidlDeviceState::EMPTY
}
.into();
assert_eq!(device_state, DeviceState::from_bits(MUTED_BITS).unwrap(),);
}
#[test]
fn test_device_state_to_fidl_device_state() {
let fidl_device_state: FidlDeviceState = DeviceState::from_bits(MUTED_BITS).unwrap().into();
assert_eq!(
fidl_device_state,
FidlDeviceState {
toggle_flags: FidlToggleFlags::from_bits(MUTED_BITS),
..FidlDeviceState::EMPTY
}
);
}
}