audio_streams/
async_api.rs

1// Copyright 2022 The ChromiumOS Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Traits required by `audio_streams` to perform async operations.
6//!
7//! Consumers must provide an implementation of `AudioStreamsExecutor` to allow the
8//! async `audio_streams` interface to do async io on the Executor provided by the consumer.
9//!
10//! These traits follow the interface of `cros_async`, since it is used by both crosvm and libcras
11//! to implement them.
12//!
13//! The implementation is provided in `cros_async::audio_streams_async`.
14
15use std::io::Result;
16#[cfg(any(target_os = "android", target_os = "linux"))]
17use std::os::unix::io::RawFd as RawDescriptor;
18#[cfg(any(target_os = "android", target_os = "linux"))]
19use std::os::unix::net::UnixStream;
20#[cfg(windows)]
21use std::os::windows::io::RawHandle;
22use std::time::Duration;
23
24use async_trait::async_trait;
25
26#[async_trait(?Send)]
27pub trait ReadAsync {
28    /// Read asynchronously into the provided Vec.
29    ///
30    /// The ownership of the Vec is returned after the operation completes, along with the number of
31    /// bytes read.
32    async fn read_to_vec<'a>(
33        &'a self,
34        file_offset: Option<u64>,
35        vec: Vec<u8>,
36    ) -> Result<(usize, Vec<u8>)>;
37}
38
39#[async_trait(?Send)]
40pub trait WriteAsync {
41    /// Write asynchronously from the provided Vec.
42    ///
43    /// The ownership of the Vec is returned after the operation completes, along with the number of
44    /// bytes written.
45    async fn write_from_vec<'a>(
46        &'a self,
47        file_offset: Option<u64>,
48        vec: Vec<u8>,
49    ) -> Result<(usize, Vec<u8>)>;
50}
51
52/// Trait to wrap around EventAsync, because audio_streams can't depend on anything in `base` or
53/// `cros_async`.
54#[async_trait(?Send)]
55pub trait EventAsyncWrapper {
56    async fn wait(&self) -> Result<u64>;
57}
58
59pub trait ReadWriteAsync: ReadAsync + WriteAsync {}
60
61pub type AsyncStream = Box<dyn ReadWriteAsync + Send>;
62
63/// Trait of Executor functionality used by `audio_streams`.
64#[async_trait(?Send)]
65pub trait AudioStreamsExecutor {
66    /// Create an object to allow async reads/writes from the specified UnixStream.
67    #[cfg(any(target_os = "android", target_os = "linux"))]
68    fn async_unix_stream(&self, f: UnixStream) -> Result<AsyncStream>;
69
70    /// Wraps an event that will be triggered when the audio backend is ready to read more audio
71    /// data.
72    ///
73    /// # Safety
74    /// Callers needs to make sure the `RawHandle` is an Event, or at least a valid Handle for
75    /// their use case.
76    #[cfg(windows)]
77    unsafe fn async_event(&self, event: RawHandle) -> Result<Box<dyn EventAsyncWrapper>>;
78
79    /// Returns a future that resolves after the specified time.
80    async fn delay(&self, dur: Duration) -> Result<()>;
81
82    // Returns a future that resolves after the provided descriptor is readable.
83    #[cfg(any(target_os = "android", target_os = "linux"))]
84    async fn wait_fd_readable(&self, _fd: RawDescriptor) -> Result<()> {
85        Ok(())
86    }
87}
88
89#[cfg(test)]
90pub mod test {
91    use super::*;
92
93    /// Stub implementation of the AudioStreamsExecutor to use in unit tests.
94    pub struct TestExecutor {}
95
96    #[async_trait(?Send)]
97    impl AudioStreamsExecutor for TestExecutor {
98        #[cfg(any(target_os = "android", target_os = "linux"))]
99        fn async_unix_stream(&self, _f: UnixStream) -> Result<AsyncStream> {
100            panic!("Not Implemented");
101        }
102
103        async fn delay(&self, dur: Duration) -> Result<()> {
104            // Simulates the delay by blocking to satisfy behavior expected in unit tests.
105            std::thread::sleep(dur);
106            return Ok(());
107        }
108
109        #[cfg(windows)]
110        unsafe fn async_event(&self, _event: RawHandle) -> Result<Box<dyn EventAsyncWrapper>> {
111            unimplemented!("async_event is not yet implemented on windows");
112        }
113    }
114}