fuchsia_audio_dai/
discover.rs1use anyhow::Error;
6use fidl_fuchsia_io as fio;
7use std::path::Path;
8
9use crate::DigitalAudioInterface;
10
11const DAI_CONNECTOR_MEMBER: &str = "dai_connector";
13const DAI_SERVICE_DIR: &str = "/svc/fuchsia.hardware.audio.DaiConnectorService";
14
15pub async fn find_devices() -> Result<Vec<DigitalAudioInterface>, Error> {
17 let directory_proxy =
19 fuchsia_fs::directory::open_in_namespace(DAI_SERVICE_DIR, fio::Flags::empty())?;
20 find_devices_internal(directory_proxy).await
21}
22
23async fn find_devices_internal(
24 directory_proxy: fio::DirectoryProxy,
25) -> Result<Vec<DigitalAudioInterface>, Error> {
26 let files = fuchsia_fs::directory::readdir(&directory_proxy).await?;
27
28 let devices = files
29 .iter()
30 .map(|file| {
31 let path = Path::new(DAI_SERVICE_DIR).join(&file.name).join(DAI_CONNECTOR_MEMBER);
32 DigitalAudioInterface::new(&path)
33 })
34 .collect();
35
36 Ok(devices)
37}
38
39#[cfg(test)]
40mod tests {
41 use fidl_fuchsia_hardware_audio as fhaudio;
42 use fuchsia_component_test::{
43 Capability, ChildOptions, LocalComponentHandles, RealmBuilder, Route,
44 };
45 use futures::channel::mpsc;
46 use futures::{SinkExt, StreamExt};
47 use realmbuilder_mock_helpers::mock_svc;
48
49 use super::*;
50 use crate::test::mock_dai_service_with_io_devices;
51
52 #[fuchsia::test]
53 async fn test_env_dir_is_not_found() {
54 let _ = find_devices().await.expect_err("find devices okay");
55 }
56
57 async fn mock_client(
58 handles: LocalComponentHandles,
59 mut sender: mpsc::Sender<()>,
60 ) -> Result<(), Error> {
61 let service_dir = handles.open_service::<fhaudio::DaiConnectorServiceMarker>()?;
62 let devices = find_devices_internal(service_dir).await.expect("should find devices");
63 assert_eq!(devices.len(), 2);
64 let _ = sender.send(()).await.unwrap();
65 Ok(())
66 }
67
68 #[fuchsia::test]
69 async fn devices_found_from_env() {
70 let (device_sender, mut device_receiver) = mpsc::channel(0);
71 let builder = RealmBuilder::new().await.expect("Failed to create test realm builder");
72
73 let mock_svc = builder
75 .add_local_child(
76 "mock-svc",
77 move |handles: LocalComponentHandles| {
78 Box::pin(mock_svc(
79 handles,
80 mock_dai_service_with_io_devices(
81 "input1".to_string(),
82 "output1".to_string(),
83 ),
84 ))
85 },
86 ChildOptions::new().eager(),
87 )
88 .await
89 .expect("Failed adding mock service provider to topology");
90
91 let mock_client = builder
93 .add_local_child(
94 "mock-client",
95 move |handles: LocalComponentHandles| {
96 let s = device_sender.clone();
97 Box::pin(mock_client(handles, s.clone()))
98 },
99 ChildOptions::new().eager(),
100 )
101 .await
102 .expect("Failed adding mock client to topology");
103
104 builder
106 .add_route(
107 Route::new()
108 .capability(Capability::service::<fhaudio::DaiConnectorServiceMarker>())
109 .from(&mock_svc)
110 .to(&mock_client),
111 )
112 .await
113 .expect("Failed adding route for dai device service");
114
115 let _instance = builder.build().await.unwrap();
116
117 let _ = device_receiver.next().await.expect("should receive devices");
118 }
119}