• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // TODO(b/301630330): Address comments from CL once this is sync'd with downstream.
6 
7 pub mod async_stream;
8 mod completion_handler;
9 mod device_notification;
10 mod wave_format;
11 
12 use std::convert::From;
13 use std::fmt::Debug;
14 use std::os::raw::c_void;
15 use std::ptr::null_mut;
16 use std::sync::atomic::AtomicBool;
17 use std::sync::Arc;
18 use std::sync::Once;
19 use std::thread_local;
20 use std::time::Duration;
21 
22 use async_trait::async_trait;
23 use audio_streams::async_api::EventAsyncWrapper;
24 use audio_streams::capture::AsyncCaptureBuffer;
25 use audio_streams::capture::CaptureBufferError;
26 use audio_streams::capture::NoopCaptureStream;
27 use audio_streams::AsyncBufferCommit;
28 use audio_streams::AsyncPlaybackBuffer;
29 use audio_streams::AsyncPlaybackBufferStream;
30 use audio_streams::AudioStreamsExecutor;
31 use audio_streams::BoxError;
32 use audio_streams::BufferCommit;
33 use audio_streams::NoopStream;
34 use audio_streams::NoopStreamControl;
35 use audio_streams::PlaybackBuffer;
36 use audio_streams::PlaybackBufferError;
37 use audio_streams::PlaybackBufferStream;
38 use audio_streams::SampleFormat;
39 use audio_streams::StreamControl;
40 use audio_streams::StreamSource;
41 use base::error;
42 use base::info;
43 use base::warn;
44 use base::AsRawDescriptor;
45 use base::Error;
46 use base::Event;
47 use base::EventExt;
48 use base::EventWaitResult;
49 use completion_handler::WinAudioActivateAudioInterfaceCompletionHandler;
50 use sync::Mutex;
51 use thiserror::Error as ThisError;
52 use wave_format::*;
53 use winapi::shared::guiddef::GUID;
54 use winapi::shared::guiddef::REFCLSID;
55 use winapi::um::audioclient::*;
56 use winapi::um::audiosessiontypes::AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED;
57 use winapi::um::audiosessiontypes::AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED;
58 use winapi::um::audiosessiontypes::AUDCLNT_SHAREMODE_SHARED;
59 use winapi::um::audiosessiontypes::AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
60 use winapi::um::combaseapi::*;
61 use winapi::um::coml2api::STGM_READ;
62 use winapi::um::functiondiscoverykeys_devpkey::PKEY_Device_FriendlyName;
63 use winapi::um::mmdeviceapi::*;
64 use winapi::um::objbase::COINIT_APARTMENTTHREADED;
65 use winapi::um::propidl::PropVariantClear;
66 use winapi::um::propidl::PROPVARIANT;
67 use winapi::um::propsys::IPropertyStore;
68 use winapi::um::synchapi::WaitForSingleObject;
69 use winapi::um::unknwnbase::IUnknown;
70 use winapi::um::winbase::WAIT_OBJECT_0;
71 use winapi::Interface;
72 use wio::com::ComPtr;
73 
74 use crate::async_stream::log_init_error_with_limit;
75 use crate::async_stream::log_playback_error_with_limit;
76 use crate::intermediate_resampler_buffer::CaptureResamplerBuffer;
77 use crate::intermediate_resampler_buffer::PlaybackResamplerBuffer;
78 use crate::win_audio_impl::device_notification::WinIMMNotificationClient;
79 use crate::AudioSharedFormat;
80 use crate::ANDROID_CAPTURE_FRAME_SIZE_BYTES;
81 use crate::BYTES_PER_32FLOAT;
82 
83 const READY_TO_READ_TIMEOUT_MS: u32 = 2000;
84 pub const STEREO_CHANNEL_COUNT: u16 = 2;
85 pub const MONO_CHANNEL_COUNT: u16 = 1;
86 
87 // from msdn: https://docs.microsoft.com/en-us/windows/win32/coreaudio/audclnt-streamflags-xxx-constants
88 // these don't currently exist in winapi
89 const AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM: u32 = 0x80000000;
90 const AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY: u32 = 0x08000000;
91 
92 thread_local!(static THREAD_ONCE_INIT: Once = Once::new());
93 
94 // Used to differentiate between S_FALSE and S_OK. This means `CoInitializeEx` did not get called.
95 // Mainly used for testing.
96 const S_SKIPPED_COINIT: i32 = 2;
97 
98 const ACTIVATE_AUDIO_EVENT_TIMEOUT: Duration = Duration::from_secs(5);
99 
100 pub struct WinAudio {
101     pub cached_playback_buffer_stream:
102         Option<(Arc<Mutex<Box<dyn PlaybackBufferStream>>>, AudioSharedFormat)>,
103 }
104 impl WinAudio {
new() -> Result<Self, BoxError>105     pub fn new() -> Result<Self, BoxError> {
106         Ok(WinAudio {
107             cached_playback_buffer_stream: None,
108         })
109     }
110 
co_init_once_per_thread() -> i32111     pub(crate) fn co_init_once_per_thread() -> i32 {
112         let mut hr = S_SKIPPED_COINIT;
113         THREAD_ONCE_INIT.with(|once| {
114             once.call_once(|| {
115                 // SAFETY: All variables passed into `CoInitializeEx` are hardcoded
116                 unsafe {
117                     // Initializes the COM library for use by the calling thread. Needed so that
118                     // `CoCreateInstance` can be called to create a device
119                     // enumerator object.
120                     //
121                     // TODO(b/217413370): `CoUninitialize` is never called at any point in KiwiVm.
122                     // It might make sense for all VCPU threads to call `CoInitializeEx` when
123                     // starting and `CoUninitialize` when the thread ends. However when switching to
124                     // virtio-snd, we need to make sure cros_async threads get `Co(Un)Initialize`
125                     // support if needed.
126                     hr = CoInitializeEx(null_mut(), COINIT_APARTMENTTHREADED);
127                 };
128             })
129         });
130 
131         hr
132     }
133 }
134 
135 impl StreamSource for WinAudio {
136     /// Returns a stream control and a buffer generator object. The stream control object is not
137     /// used. The buffer generator object is a wrapper around WASAPI's objects that will create a
138     /// buffer for crosvm to copy audio bytes into.
new_playback_stream( &mut self, num_channels: usize, format: SampleFormat, frame_rate: u32, buffer_size: usize, ) -> Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), BoxError>139     fn new_playback_stream(
140         &mut self,
141         num_channels: usize,
142         format: SampleFormat,
143         frame_rate: u32,
144         buffer_size: usize, //number of frames;
145     ) -> Result<(Box<dyn StreamControl>, Box<dyn PlaybackBufferStream>), BoxError> {
146         let hr = WinAudio::co_init_once_per_thread();
147         let _ = check_hresult!(hr, WinAudioError::from(hr), "Co Initialized failed");
148 
149         let playback_buffer_stream: Box<dyn PlaybackBufferStream> =
150             match WinAudioRenderer::new(num_channels, format, frame_rate, buffer_size) {
151                 Ok(renderer) => Box::new(renderer),
152                 Err(e) => {
153                     warn!(
154                         "Failed to create WinAudioRenderer. Fallback to NoopStream with error: {}",
155                         e
156                     );
157                     Box::new(NoopStream::new(
158                         num_channels,
159                         SampleFormat::S16LE,
160                         frame_rate,
161                         buffer_size,
162                     ))
163                 }
164             };
165 
166         Ok((Box::new(NoopStreamControl::new()), playback_buffer_stream))
167     }
168 
169     /// Similar to `new_playback_stream, but will return an `AsyncPlaybackBufferStream` that can
170     /// run async operations.
new_async_playback_stream( &mut self, num_channels: usize, format: SampleFormat, frame_rate: u32, buffer_size: usize, ex: &dyn AudioStreamsExecutor, ) -> Result<(Box<dyn StreamControl>, Box<dyn AsyncPlaybackBufferStream>), BoxError>171     fn new_async_playback_stream(
172         &mut self,
173         num_channels: usize,
174         format: SampleFormat,
175         frame_rate: u32,
176         buffer_size: usize,
177         ex: &dyn AudioStreamsExecutor,
178     ) -> Result<(Box<dyn StreamControl>, Box<dyn AsyncPlaybackBufferStream>), BoxError> {
179         WinAudio::new_async_playback_stream_helper(
180             num_channels,
181             format,
182             frame_rate,
183             buffer_size,
184             ex,
185         )
186     }
187 }
188 
189 /// Proxy for a `DeviceRenderer` that handles device invalidated errors by switching to a new
190 /// `DeviceRenderer` on a new device.
191 pub(crate) struct WinAudioRenderer {
192     pub device: DeviceRendererWrapper,
193 }
194 
195 impl WinAudioRenderer {
196     /// Initializes WASAPI objects needed for audio. Only used for the Ac97 device.
new( num_channels: usize, format: SampleFormat, frame_rate: u32, incoming_buffer_size_in_frames: usize, ) -> Result<Self, RenderError>197     pub fn new(
198         num_channels: usize,
199         format: SampleFormat,
200         frame_rate: u32,
201         incoming_buffer_size_in_frames: usize,
202     ) -> Result<Self, RenderError> {
203         let device = DeviceRendererWrapper::new(
204             num_channels,
205             format,
206             frame_rate,
207             incoming_buffer_size_in_frames,
208             None,
209         )?;
210         Ok(Self { device })
211     }
212 
handle_playback_logging_on_error(e: &RenderError)213     fn handle_playback_logging_on_error(e: &RenderError) {
214         match &e {
215             RenderError::WinAudioError(win_audio_error) => {
216                 log_playback_error_with_limit(win_audio_error.into());
217                 match win_audio_error {
218                     WinAudioError::GetCurrentPaddingError(hr)
219                     | WinAudioError::GetBufferError(hr) => {
220                         if *hr == AUDCLNT_E_DEVICE_INVALIDATED {
221                             info!(
222                                 "Recieved AUDLNT_E_DEVICE_INVALIDATED error. No devices \
223                              attached, so will start listening for one."
224                             );
225                         } else {
226                             warn!(
227                                 "Unknown HResult: {} from GetCurrentPadding or GetBufferError. \
228                              Will still start listening for a new device",
229                                 hr
230                             );
231                         }
232                     }
233                     _ => warn!(
234                         "Unexpected errors. Will still listen for a new device: {}",
235                         win_audio_error
236                     ),
237                 }
238             }
239             _ => {
240                 log_playback_error_with_limit((&WinAudioError::Unknown).into());
241                 warn!(
242                     "Unexpected non WinAudioError. Will stil start listening for a new device: {}",
243                     e
244                 );
245             }
246         }
247     }
248 
249     /// Get the audio format used by the endpoint buffer, whether it be the `NoopStream` buffer
250     /// or the WASAPI endpoint buffer.
get_audio_shared_format(&self) -> AudioSharedFormat251     pub(crate) fn get_audio_shared_format(&self) -> AudioSharedFormat {
252         match &self.device.renderer_stream {
253             RendererStream::Device((device_renderer, _)) => device_renderer.audio_shared_format,
254             RendererStream::Noop(_) => AudioSharedFormat {
255                 bit_depth: 32,
256                 frame_rate: self.device.guest_frame_rate as usize,
257                 channels: self.device.num_channels,
258                 shared_audio_engine_period_in_frames: self.device.incoming_buffer_size_in_frames,
259                 channel_mask: None,
260             },
261         }
262     }
263 }
264 
265 /// This is only used by the Ac97 device, so this impl is deprecated.
266 impl PlaybackBufferStream for WinAudioRenderer {
267     /// Returns a wrapper around the WASAPI buffer.
next_playback_buffer<'b, 's: 'b>(&'s mut self) -> Result<PlaybackBuffer<'b>, BoxError>268     fn next_playback_buffer<'b, 's: 'b>(&'s mut self) -> Result<PlaybackBuffer<'b>, BoxError> {
269         match &mut self.device.renderer_stream {
270             RendererStream::Device((device_renderer, _)) => {
271                 match device_renderer.next_win_buffer() {
272                     Ok(_) => {
273                         return device_renderer
274                             .playback_buffer()
275                             .map_err(|e| Box::new(e) as _)
276                     }
277                     Err(e) => Err(Box::new(e)),
278                 }
279             }
280             RendererStream::Noop(_) => {
281                 error!("Unable to attach to a working audio device, giving up");
282                 Err(Box::new(WinAudioError::DeviceInvalidated))
283             }
284         }
285     }
286 }
287 
288 /// Used to help listen for device related events.
289 struct DeviceNotifier {
290     // Used to register the `IMMNotificationClient`.
291     device_enumerator: ComPtr<IMMDeviceEnumerator>,
292     // Used to help detect when a new audio device has been attached.
293     imm_notification_client: ComPtr<IMMNotificationClient>,
294 }
295 
296 impl DeviceNotifier {
297     /// Create the notification client that will listen to audio device events.
create_imm_device_notification( is_device_available: Arc<AtomicBool>, dataflow: EDataFlow, ) -> Result<Self, WinAudioError>298     pub(crate) fn create_imm_device_notification(
299         is_device_available: Arc<AtomicBool>,
300         dataflow: EDataFlow,
301     ) -> Result<Self, WinAudioError> {
302         let mut device_enumerator: *mut c_void = null_mut();
303 
304         // Creates a device enumerator in order to select our default audio device.
305         //
306         // SAFETY: Only `device_enumerator` is being modified and we own it.
307         let hr = unsafe {
308             CoCreateInstance(
309                 &CLSID_MMDeviceEnumerator as REFCLSID,
310                 null_mut(),
311                 CLSCTX_ALL,
312                 &IMMDeviceEnumerator::uuidof(),
313                 &mut device_enumerator,
314             )
315         };
316 
317         check_hresult!(
318             hr,
319             WinAudioError::GetDeviceEnumeratorError(hr),
320             "Win audio create client CoCreateInstance() failed when trying to set up the \
321              IMMNotificationClient."
322         )?;
323 
324         let device_enumerator =
325             // SAFETY: We know `device_enumerator` is a valid pointer, otherwise, we would've
326             // returned with an error earlier.
327             unsafe { ComPtr::from_raw(device_enumerator as *mut IMMDeviceEnumerator) };
328 
329         let imm_notification_client =
330             WinIMMNotificationClient::create_com_ptr(is_device_available, dataflow);
331 
332         // SAFETY: The creation of `imm_notification_client` is always valid.
333         let hr = unsafe {
334             device_enumerator.RegisterEndpointNotificationCallback(imm_notification_client.as_raw())
335         };
336         check_hresult!(
337             hr,
338             WinAudioError::RegisterEndpointNotifError(hr),
339             "Win audio errored on RegisterEndpointNotificationCallback."
340         )?;
341 
342         Ok(DeviceNotifier {
343             device_enumerator,
344             imm_notification_client,
345         })
346     }
347 }
348 
349 impl Drop for DeviceNotifier {
350     // `device_enumerator` and `imm_notification_client` will call `Release` when they are dropped
351     // since they are `ComPtr`s.
drop(&mut self)352     fn drop(&mut self) {
353         // SAFETY: The `notification_client` is a valid `IMMNotificationClient`.
354         unsafe {
355             self.device_enumerator
356                 .UnregisterEndpointNotificationCallback(self.imm_notification_client.as_raw());
357         }
358     }
359 }
360 
361 pub(crate) struct NoopRenderer {
362     // Playback stream that helps with sleeping in the playback loop when no devices are available.
363     // Audio bytes coming from the guest will be dropped.
364     noop_stream: NoopStream,
365     // Help listen for device related events, so that a new audio device can be detected.
366     _device_notifier: DeviceNotifier,
367     // True if a new device is available.
368     is_device_available: Arc<AtomicBool>,
369 }
370 
371 pub(crate) enum RendererStream {
372     Device(
373         (
374             DeviceRenderer,
375             // Buffer that contains a sample rate converter and also helps with managing differing
376             // periods between the guest and the host.
377             PlaybackResamplerBuffer,
378         ),
379     ),
380     Noop(NoopRenderer),
381 }
382 
383 /// Wraps the `DeviceRenderer` and `NoopStream` so that they can easily be interchanged in the
384 /// middle of audio playback. This also contains fields that helps with creating the aforementioned
385 /// objects and helps with detecting a new audio device being connected.
386 pub(crate) struct DeviceRendererWrapper {
387     // Helps manage a playback stream.
388     pub(crate) renderer_stream: RendererStream,
389     // Buffer sent to the CrosVm audio device (ie. Virtio Sound) for it to write to.
390     intermediate_buffer: Vec<u8>,
391     // guest channel count.
392     num_channels: usize,
393     // guest bit depth.
394     guest_bit_depth: SampleFormat,
395     // guest frame rate.
396     guest_frame_rate: u32,
397     // incoming buffer size from the guest per period.
398     incoming_buffer_size_in_frames: usize,
399 }
400 
401 impl DeviceRendererWrapper {
402     /// If no audio device are detected, then the creation of `DeviceRenderer` will fail. In this
403     /// case, a `NoopStream` will be created as well as the set up of the `IMMNotificationClient`.
new( num_channels: usize, guest_bit_depth: SampleFormat, guest_frame_rate: u32, incoming_buffer_size_in_frames: usize, ex: Option<&dyn AudioStreamsExecutor>, ) -> Result<Self, RenderError>404     fn new(
405         num_channels: usize,
406         guest_bit_depth: SampleFormat,
407         guest_frame_rate: u32,
408         incoming_buffer_size_in_frames: usize,
409         ex: Option<&dyn AudioStreamsExecutor>,
410     ) -> Result<Self, RenderError> {
411         let renderer_stream = match Self::create_device_renderer_and_log_time(
412             num_channels,
413             guest_frame_rate,
414             incoming_buffer_size_in_frames,
415             ex,
416         ) {
417             Ok(device) => {
418                 let audio_shared_format = device.audio_shared_format;
419                 let playback_resampler_buffer = PlaybackResamplerBuffer::new(
420                     guest_frame_rate as usize,
421                     audio_shared_format.frame_rate,
422                     incoming_buffer_size_in_frames,
423                     audio_shared_format.shared_audio_engine_period_in_frames,
424                     audio_shared_format.channels,
425                     audio_shared_format.channel_mask,
426                 )
427                 .expect("Failed to create PlaybackResamplerBuffer");
428 
429                 RendererStream::Device((device, playback_resampler_buffer))
430             }
431 
432             Err(e) => {
433                 Self::handle_init_logging_on_error(&e);
434                 Self::create_noop_stream_with_device_notification(
435                     num_channels,
436                     guest_frame_rate,
437                     incoming_buffer_size_in_frames,
438                 )?
439             }
440         };
441 
442         Ok(Self {
443             renderer_stream,
444             intermediate_buffer: vec![
445                 0;
446                 incoming_buffer_size_in_frames
447                     * num_channels
448                     * guest_bit_depth.sample_bytes()
449             ],
450             num_channels,
451             guest_bit_depth,
452             guest_frame_rate,
453             incoming_buffer_size_in_frames,
454         })
455     }
456 
handle_init_logging_on_error(e: &RenderError)457     fn handle_init_logging_on_error(e: &RenderError) {
458         match &e {
459             RenderError::WinAudioError(win_audio_error) => {
460                 match win_audio_error {
461                     WinAudioError::MissingDeviceError(_) => {
462                         info!(
463                             "No audio playback devices were found. Will start listening for new \
464                          devices"
465                         );
466                     }
467                     _ => {
468                         warn!(
469                             "Unexpected WinAudioError on initialization. Will still listen for \
470                         new devices: {}",
471                             e
472                         );
473                     }
474                 }
475                 log_init_error_with_limit(win_audio_error.into());
476             }
477             _ => {
478                 log_init_error_with_limit((&WinAudioError::Unknown).into());
479                 error!(
480                     "Unhandled NoopStream forced error. These errors should not have been \
481                  returned. WIll still listen for new devices: {}",
482                     e
483                 );
484             }
485         }
486     }
487 
create_noop_stream_with_device_notification( num_channels: usize, guest_frame_rate: u32, incoming_buffer_size_in_frames: usize, ) -> Result<RendererStream, RenderError>488     fn create_noop_stream_with_device_notification(
489         num_channels: usize,
490         guest_frame_rate: u32,
491         incoming_buffer_size_in_frames: usize,
492     ) -> Result<RendererStream, RenderError> {
493         let is_device_available = Arc::new(AtomicBool::new(false));
494         let noop_renderer = NoopRenderer {
495             noop_stream: NoopStream::new(
496                 num_channels,
497                 SampleFormat::S32LE,
498                 guest_frame_rate,
499                 incoming_buffer_size_in_frames,
500             ),
501             _device_notifier: DeviceNotifier::create_imm_device_notification(
502                 is_device_available.clone(),
503                 eRender,
504             )
505             .map_err(RenderError::WinAudioError)?,
506             is_device_available,
507         };
508 
509         Ok(RendererStream::Noop(noop_renderer))
510     }
511 
create_device_renderer_and_log_time( num_channels: usize, frame_rate: u32, incoming_buffer_size_in_frames: usize, ex: Option<&dyn AudioStreamsExecutor>, ) -> Result<DeviceRenderer, RenderError>512     fn create_device_renderer_and_log_time(
513         num_channels: usize,
514         frame_rate: u32,
515         incoming_buffer_size_in_frames: usize,
516         ex: Option<&dyn AudioStreamsExecutor>,
517     ) -> Result<DeviceRenderer, RenderError> {
518         let start = std::time::Instant::now();
519         let device =
520             DeviceRenderer::new(num_channels, frame_rate, incoming_buffer_size_in_frames, ex)?;
521         // This can give us insights to how other long other machines take to initialize audio.
522         // Eventually this should be a histogram metric.
523         info!(
524             "DeviceRenderer took {}ms to initialize audio.",
525             start.elapsed().as_millis()
526         );
527         Ok(device)
528     }
529 
get_intermediate_async_buffer(&mut self) -> Result<AsyncPlaybackBuffer, RenderError>530     fn get_intermediate_async_buffer(&mut self) -> Result<AsyncPlaybackBuffer, RenderError> {
531         let guest_frame_size = self.num_channels * self.guest_bit_depth.sample_bytes();
532         // SAFETY: `intermediate_buffer` doesn't get mutated by `Self` after this slice is
533         // created.
534         let slice = unsafe {
535             std::slice::from_raw_parts_mut(
536                 self.intermediate_buffer.as_mut_ptr(),
537                 self.intermediate_buffer.len(),
538             )
539         };
540         AsyncPlaybackBuffer::new(guest_frame_size, slice, self).map_err(RenderError::PlaybackBuffer)
541     }
542 }
543 
544 // SAFETY: DeviceRendererWrapper is safe to send between threads
545 unsafe impl Send for DeviceRendererWrapper {}
546 
547 // Implementation of buffer generator object. Used to get a buffer from WASAPI for crosvm to copy
548 // audio bytes from the guest memory into.
549 pub(crate) struct DeviceRenderer {
550     audio_render_client: ComPtr<IAudioRenderClient>,
551     audio_client: ComPtr<IAudioClient>,
552     win_buffer: *mut u8,
553     pub audio_shared_format: AudioSharedFormat,
554     audio_render_client_buffer_frame_count: u32,
555     ready_to_read_event: Event,
556     async_ready_to_read_event: Option<Box<dyn EventAsyncWrapper>>,
557     // Set to true if we should call WASAPI's `GetBuffer`. This should be false if there aren't
558     // enough bytes in `playback_resampler_buffer` to write a full Windows endpoint buffer period.
559     should_get_next_win_buffer: bool,
560 }
561 
562 impl DeviceRenderer {
563     // Initializes WASAPI objects needed for audio
new( num_channels: usize, guest_frame_rate: u32, incoming_buffer_size_in_frames: usize, ex: Option<&dyn AudioStreamsExecutor>, ) -> Result<Self, RenderError>564     fn new(
565         num_channels: usize,
566         guest_frame_rate: u32,
567         incoming_buffer_size_in_frames: usize,
568         ex: Option<&dyn AudioStreamsExecutor>,
569     ) -> Result<Self, RenderError> {
570         if num_channels > 2 {
571             return Err(RenderError::WinAudioError(
572                 WinAudioError::InvalidChannelCount(num_channels),
573             ));
574         }
575 
576         info!("Render guest frame rate: {}", guest_frame_rate);
577 
578         let audio_client = create_audio_client(eRender).map_err(RenderError::WinAudioError)?;
579 
580         let format = get_valid_mix_format(&audio_client).map_err(RenderError::WinAudioError)?;
581 
582         // SAFETY: `audio_client` is initialized
583         let hr = unsafe {
584             // Intializes the audio client by setting the buffer size in 100-nanoseconds and
585             // specifying the format the audio bytes will be passed in as.
586             // Setting `hnsBufferDuration` (in miilisecond units) to 0 will let the audio engine to
587             // pick the size that will minimize latency.
588             // `hnsPeriodicity` sets the device period and should always be 0 for shared mode.
589             audio_client.Initialize(
590                 AUDCLNT_SHAREMODE_SHARED,
591                 AUDCLNT_STREAMFLAGS_EVENTCALLBACK
592                     | AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM
593                     | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY
594                     | AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED
595                     | AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED,
596                 0, /* hnsBufferDuration */
597                 0, /* hnsPeriodicity */
598                 format.as_ptr(),
599                 null_mut(),
600             )
601         };
602         check_hresult!(
603             hr,
604             WinAudioError::AudioClientInitializationError(hr),
605             "Audio Client Initialize() failed."
606         )
607         .map_err(RenderError::WinAudioError)?;
608 
609         let (ready_to_read_event, async_ready_to_read_event) =
610             create_and_set_audio_client_event(&audio_client, &ex)
611                 .map_err(RenderError::WinAudioError)?;
612 
613         let audio_render_client = DeviceRenderer::create_audio_render_client(&audio_client)?;
614 
615         let shared_audio_engine_period_in_frames =
616             get_device_period_in_frames(&audio_client, &format);
617 
618         let audio_render_client_buffer_frame_count =
619             check_endpoint_buffer_size(&audio_client, shared_audio_engine_period_in_frames)
620                 .map_err(RenderError::WinAudioError)?;
621         if incoming_buffer_size_in_frames % shared_audio_engine_period_in_frames != 0 {
622             warn!(
623                 "Rendering: Guest period size: `{}` not divisible by shared audio engine period size: `{}`. \
624                  Audio glitches may occur if sample rate conversion isn't on.",
625                 incoming_buffer_size_in_frames, shared_audio_engine_period_in_frames
626             );
627         }
628 
629         // SAFETY: `audio_client` is initialized
630         let hr = unsafe {
631             // Starts the audio stream for playback
632             audio_client.Start()
633         };
634         check_hresult!(
635             hr,
636             WinAudioError::AudioClientStartError(hr),
637             "Audio Render Client Start() failed."
638         )
639         .map_err(RenderError::WinAudioError)?;
640 
641         let audio_shared_format =
642             format.create_audio_shared_format(shared_audio_engine_period_in_frames);
643         Ok(Self {
644             audio_render_client,
645             audio_client,
646             win_buffer: std::ptr::null_mut(),
647             audio_shared_format,
648             audio_render_client_buffer_frame_count,
649             ready_to_read_event,
650             async_ready_to_read_event,
651             should_get_next_win_buffer: true,
652         })
653     }
654 
create_audio_render_client( audio_client: &IAudioClient, ) -> Result<ComPtr<IAudioRenderClient>, RenderError>655     fn create_audio_render_client(
656         audio_client: &IAudioClient,
657     ) -> Result<ComPtr<IAudioRenderClient>, RenderError> {
658         let mut audio_render_client: *mut c_void = null_mut();
659 
660         // SAFETY: `audio_client` is initialized
661         let hr = unsafe {
662             audio_client.GetService(
663                 &IID_IAudioRenderClient as *const GUID,
664                 &mut audio_render_client,
665             )
666         };
667         check_hresult!(
668             hr,
669             WinAudioError::GetRenderClientError(hr),
670             "Audio Client GetService() failed."
671         )
672         .map_err(RenderError::WinAudioError)?;
673 
674         // SAFETY: `audio_render_client` is guaranteed to be initialized
675         unsafe {
676             Ok(ComPtr::from_raw(
677                 audio_render_client as *mut IAudioRenderClient,
678             ))
679         }
680     }
681 
682     // Returns a wraper around the WASAPI buffer
next_win_buffer(&mut self) -> Result<(), RenderError>683     fn next_win_buffer(&mut self) -> Result<(), RenderError> {
684         // We will wait for windows to tell us when it is ready to take in the next set of
685         // audio samples from the guest
686         loop {
687             // SAFETY: `ready_to_read_event` is guaranteed to be properly initialized
688             // and `num_frames_padding` is property initliazed as an empty pointer.
689             unsafe {
690                 let res = WaitForSingleObject(
691                     self.ready_to_read_event.as_raw_descriptor(),
692                     READY_TO_READ_TIMEOUT_MS,
693                 );
694                 if res != WAIT_OBJECT_0 {
695                     warn!(
696                         "Waiting for ready_to_read_event timed out after {} ms",
697                         READY_TO_READ_TIMEOUT_MS
698                     );
699                     break;
700                 }
701                 if self.enough_available_frames()? {
702                     break;
703                 }
704             }
705         }
706 
707         self.get_buffer()?;
708 
709         Ok(())
710     }
711 
712     /// Returns true if the number of frames avaialble in the Windows playback buffer is at least
713     /// the size of one full period worth of audio samples.
enough_available_frames(&mut self) -> Result<bool, RenderError>714     fn enough_available_frames(&mut self) -> Result<bool, RenderError> {
715         let mut num_frames_padding = 0u32;
716         // SAFETY: `num_frames_padding` is an u32 and `GetCurrentPadding` is a simple
717         // Windows function that shouldn't fail.
718         let hr = unsafe { self.audio_client.GetCurrentPadding(&mut num_frames_padding) };
719         check_hresult!(
720             hr,
721             WinAudioError::GetCurrentPaddingError(hr),
722             "Audio Client GetCurrentPadding() failed."
723         )
724         .map_err(RenderError::WinAudioError)?;
725 
726         // If the available free frames is less than the frames that are being sent over from the
727         // guest, then we want to only grab the number of frames available.
728         let num_frames_available =
729             (self.audio_render_client_buffer_frame_count - num_frames_padding) as usize;
730 
731         Ok(num_frames_available
732             >= self
733                 .audio_shared_format
734                 .shared_audio_engine_period_in_frames)
735     }
736 
get_buffer(&mut self) -> Result<(), RenderError>737     fn get_buffer(&mut self) -> Result<(), RenderError> {
738         self.win_buffer = std::ptr::null_mut();
739 
740         // This unsafe block will get the playback buffer and return the size of the buffer
741         //
742         // SAFETY:
743         // This is safe because the contents of `win_buffer` will be
744         // released when `ReleaseBuffer` is called in the `BufferCommit` implementation.
745         unsafe {
746             let hr = self.audio_render_client.GetBuffer(
747                 self.audio_shared_format
748                     .shared_audio_engine_period_in_frames as u32,
749                 &mut self.win_buffer,
750             );
751             check_hresult!(
752                 hr,
753                 WinAudioError::GetBufferError(hr),
754                 "Audio Render Client GetBuffer failed."
755             )
756             .map_err(RenderError::WinAudioError)?;
757         }
758 
759         Ok(())
760     }
761 
playback_buffer(&mut self) -> Result<PlaybackBuffer, RenderError>762     fn playback_buffer(&mut self) -> Result<PlaybackBuffer, RenderError> {
763         // SAFETY: `win_buffer` is allocated and retrieved from WASAPI. The size requested,
764         // which we specified in `next_win_buffer` is exactly
765         // `shared_audio_engine_period_in_frames`, so the size parameter should be valid.
766         let (frame_size_bytes, buffer_slice) = unsafe {
767             Self::get_frame_size_and_buffer_slice(
768                 self.audio_shared_format.bit_depth,
769                 self.audio_shared_format.channels,
770                 self.win_buffer,
771                 self.audio_shared_format
772                     .shared_audio_engine_period_in_frames,
773             )?
774         };
775 
776         PlaybackBuffer::new(frame_size_bytes, buffer_slice, self)
777             .map_err(RenderError::PlaybackBuffer)
778     }
779 
780     /// # Safety
781     ///
782     /// Safe only if:
783     ///   1. `win_buffer` is pointing to a valid buffer used for holding audio bytes.
784     ///   2. `bit_depth`, `channels`, and `shared_audio_engine_period_in_frames` are accurate with
785     ///      respect to `win_buffer`, so that a valid slice can be made.
786     ///   3. The variables mentioned in reason "2." must calculate a size no greater than the size
787     ///      of the buffer pointed to by `win_buffer`.
get_frame_size_and_buffer_slice<'a>( bit_depth: usize, channels: usize, win_buffer: *mut u8, shared_audio_engine_period_in_frames: usize, ) -> Result<(usize, &'a mut [u8]), RenderError>788     unsafe fn get_frame_size_and_buffer_slice<'a>(
789         bit_depth: usize,
790         channels: usize,
791         win_buffer: *mut u8,
792         shared_audio_engine_period_in_frames: usize,
793     ) -> Result<(usize, &'a mut [u8]), RenderError> {
794         if win_buffer.is_null() {
795             return Err(RenderError::InvalidBuffer);
796         }
797 
798         let frame_size_bytes = bit_depth * channels / 8;
799 
800         Ok((
801             frame_size_bytes,
802             std::slice::from_raw_parts_mut(
803                 win_buffer,
804                 shared_audio_engine_period_in_frames * frame_size_bytes,
805             ),
806         ))
807     }
808 }
809 
810 impl BufferCommit for DeviceRenderer {
811     // Called after buffer from WASAPI is filled. This will allow the audio bytes to be played as
812     // sound.
commit(&mut self, nframes: usize)813     fn commit(&mut self, nframes: usize) {
814         // SAFETY: `audio_render_client` is initialized and parameters passed
815         // into `ReleaseBuffer()` are valid
816         unsafe {
817             let hr = self.audio_render_client.ReleaseBuffer(nframes as u32, 0);
818             let _ = check_hresult!(
819                 hr,
820                 WinAudioError::from(hr),
821                 "Audio Render Client ReleaseBuffer() failed"
822             );
823         }
824     }
825 }
826 
827 impl Drop for DeviceRenderer {
drop(&mut self)828     fn drop(&mut self) {
829         // SAFETY:
830         // audio_client and audio_render_client will be released by ComPtr when dropped. Most likely
831         // safe to Release() if audio_client fails to stop. The MSDN doc does not mention that it
832         // will crash and this should be done anyways to prevent memory leaks
833         unsafe {
834             let hr = self.audio_client.Stop();
835             let _ = check_hresult!(
836                 hr,
837                 WinAudioError::from(hr),
838                 "Audio Render Client Stop() failed."
839             );
840         }
841     }
842 }
843 
844 // SAFETY: DeviceRenderer is safe to send between threads
845 unsafe impl Send for DeviceRenderer {}
846 
847 pub(crate) struct WinAudioCapturer {
848     pub device: DeviceCapturerWrapper,
849 }
850 
851 impl WinAudioCapturer {
get_audio_shared_format(&self) -> AudioSharedFormat852     pub(crate) fn get_audio_shared_format(&self) -> AudioSharedFormat {
853         match &self.device.capturer_stream {
854             CapturerStream::Device((device_capturer, _, _)) => device_capturer.audio_shared_format,
855             CapturerStream::Noop(_) => AudioSharedFormat {
856                 bit_depth: 16,
857                 frame_rate: self.device.guest_frame_rate as usize,
858                 channels: self.device.num_channels,
859                 shared_audio_engine_period_in_frames: self.device.guest_frame_rate as usize / 100,
860                 channel_mask: None,
861             },
862         }
863     }
864 }
865 
866 pub(crate) struct NoopBufferCommit;
867 
868 #[async_trait(?Send)]
869 impl AsyncBufferCommit for NoopBufferCommit {
870     // For capture, we don't need to `commit`, hence we no-op
commit(&mut self, _nframes: usize)871     async fn commit(&mut self, _nframes: usize) {
872         // No-op
873     }
874 }
875 
876 pub(crate) struct NoopCapturer {
877     // Capture stream that helps with sleeping in the capture loop when no devices are available.
878     // This will send 0's to the guest.
879     noop_capture_stream: NoopCaptureStream,
880     // Help listen for device related events, so that a new audio device can be detected.
881     _device_notifier: DeviceNotifier,
882     // True if a new device is available.
883     is_device_available: Arc<AtomicBool>,
884 }
885 
886 pub(crate) enum CapturerStream {
887     Device(
888         (
889             DeviceCapturer,
890             // Buffer that contains a sample rate converter and also helps with managing differing
891             // periods between the guest and the host.
892             CaptureResamplerBuffer,
893             // The `AsyncCaptureBuffer` requires an `AsyncBufferCommit` trait, but Windows doesn't
894             // need it.
895             NoopBufferCommit,
896         ),
897     ),
898     Noop(NoopCapturer),
899 }
900 
901 pub(crate) struct DeviceCapturerWrapper {
902     // Playback stream when an audio device is available.
903     pub(crate) capturer_stream: CapturerStream,
904     // guest channel count.
905     num_channels: usize,
906     // guest bit depth.
907     guest_bit_depth: SampleFormat,
908     // guest frame rate.
909     guest_frame_rate: u32,
910     // incoming buffer size from the guest per period.
911     outgoing_buffer_size_in_frames: usize,
912 }
913 
914 impl DeviceCapturerWrapper {
new( num_channels: usize, guest_bit_depth: SampleFormat, guest_frame_rate: u32, outgoing_buffer_size_in_frames: usize, ex: Option<&dyn audio_streams::AudioStreamsExecutor>, ) -> Result<Self, CaptureError>915     fn new(
916         num_channels: usize,
917         guest_bit_depth: SampleFormat,
918         guest_frame_rate: u32,
919         outgoing_buffer_size_in_frames: usize,
920         ex: Option<&dyn audio_streams::AudioStreamsExecutor>,
921     ) -> Result<Self, CaptureError> {
922         let capturer_stream = match Self::create_device_capturer_and_log_time(
923             num_channels,
924             guest_frame_rate,
925             outgoing_buffer_size_in_frames,
926             ex,
927         ) {
928             Ok(device) => {
929                 let audio_shared_format = device.audio_shared_format;
930                 let capture_resampler_buffer = CaptureResamplerBuffer::new_input_resampler(
931                     audio_shared_format.frame_rate,
932                     guest_frame_rate as usize,
933                     outgoing_buffer_size_in_frames,
934                     audio_shared_format.channels,
935                     audio_shared_format.channel_mask,
936                 )
937                 .expect("Failed to create CaptureResamplerBuffer");
938 
939                 CapturerStream::Device((device, capture_resampler_buffer, NoopBufferCommit))
940             }
941             Err(e) => {
942                 base::warn!("Creating DeviceCapturer failed: {}", e);
943                 Self::create_noop_capture_stream_with_device_notification(
944                     num_channels,
945                     guest_bit_depth,
946                     guest_frame_rate,
947                     outgoing_buffer_size_in_frames,
948                 )?
949             }
950         };
951         Ok(Self {
952             capturer_stream,
953             num_channels,
954             guest_bit_depth,
955             guest_frame_rate,
956             outgoing_buffer_size_in_frames,
957         })
958     }
959 
create_device_capturer_and_log_time( num_channels: usize, frame_rate: u32, outgoing_buffer_size_in_frames: usize, ex: Option<&dyn AudioStreamsExecutor>, ) -> Result<DeviceCapturer, CaptureError>960     fn create_device_capturer_and_log_time(
961         num_channels: usize,
962         frame_rate: u32,
963         outgoing_buffer_size_in_frames: usize,
964         ex: Option<&dyn AudioStreamsExecutor>,
965     ) -> Result<DeviceCapturer, CaptureError> {
966         let start = std::time::Instant::now();
967         let device =
968             DeviceCapturer::new(num_channels, frame_rate, outgoing_buffer_size_in_frames, ex)?;
969         // This can give us insights to how other long other machines take to initialize audio.
970         // Eventually this should be a histogram metric.
971         info!(
972             "DeviceRenderer took {}ms to initialize audio.",
973             start.elapsed().as_millis()
974         );
975         Ok(device)
976     }
977 
978     /// Read from the Windows capture buffer into the resampler until the resampler has bytes
979     /// available to be written to the guest.
drain_until_bytes_avaialable( device_capturer: &mut DeviceCapturer, capture_resampler_buffer: &mut CaptureResamplerBuffer, outgoing_buffer_size_in_frames: usize, ) -> Result<(), CaptureError>980     async fn drain_until_bytes_avaialable(
981         device_capturer: &mut DeviceCapturer,
982         capture_resampler_buffer: &mut CaptureResamplerBuffer,
983         outgoing_buffer_size_in_frames: usize,
984     ) -> Result<(), CaptureError> {
985         while !capture_resampler_buffer.is_next_period_available() {
986             device_capturer.async_next_win_buffer().await?;
987             Self::drain_to_resampler(
988                 device_capturer,
989                 capture_resampler_buffer,
990                 outgoing_buffer_size_in_frames,
991             )?;
992         }
993         Ok(())
994     }
995 
996     /// Gets a slice of sample rate converted audio frames and return an `AsyncCaptureBuffer`
997     /// with these audio frames to be used by the emulated audio device.
998     ///
999     /// This assumes the precondition that `capture_resmapler_buffer` has at least a period worth
1000     /// of audio frames available.
get_async_capture_buffer<'a>( capture_resampler_buffer: &mut CaptureResamplerBuffer, noop_buffer_commit: &'a mut NoopBufferCommit, ) -> Result<AsyncCaptureBuffer<'a>, CaptureError>1001     fn get_async_capture_buffer<'a>(
1002         capture_resampler_buffer: &mut CaptureResamplerBuffer,
1003         noop_buffer_commit: &'a mut NoopBufferCommit,
1004     ) -> Result<AsyncCaptureBuffer<'a>, CaptureError> {
1005         match capture_resampler_buffer.get_next_period() {
1006             Some(next_period) => {
1007                 // SAFETY: `next_period`'s buffer is owned by `capture_resampler_buffer`,
1008                 // and the buffer won't be cleared until
1009                 // `capture_resampler_buffer.get_next_period` is called again. That means the
1010                 // clearing won't happen until `next_slice` has been written into the rx queue.
1011                 let next_slice = unsafe {
1012                     std::slice::from_raw_parts_mut(next_period.as_mut_ptr(), next_period.len())
1013                 };
1014                 return AsyncCaptureBuffer::new(
1015                     ANDROID_CAPTURE_FRAME_SIZE_BYTES,
1016                     next_slice,
1017                     noop_buffer_commit,
1018                 )
1019                 .map_err(CaptureError::CaptureBuffer);
1020             }
1021             None => Err(CaptureError::ResamplerNoSamplesAvailable),
1022         }
1023     }
1024 
1025     /// Copy all the bytes from the Windows capture buffer into `CaptureResamplerBuffer`.
1026     ///
1027     /// This has a precondition that `win_buffer` is not null because `GetBuffer` has been called
1028     /// to get the next round of capture audio frames.
drain_to_resampler( device_capturer: &mut DeviceCapturer, capture_resampler_buffer: &mut CaptureResamplerBuffer, outgoing_buffer_size_in_frames: usize, ) -> Result<(), CaptureError>1029     fn drain_to_resampler(
1030         device_capturer: &mut DeviceCapturer,
1031         capture_resampler_buffer: &mut CaptureResamplerBuffer,
1032         outgoing_buffer_size_in_frames: usize,
1033     ) -> Result<(), CaptureError> {
1034         let mut slice = device_capturer.win_buffer.as_mut_slice();
1035         let audio_shared_format = device_capturer.audio_shared_format;
1036         // Guest period in buffer with the audio format provided by WASAPI.
1037         let guest_period_in_bytes =
1038             outgoing_buffer_size_in_frames * audio_shared_format.channels * BYTES_PER_32FLOAT;
1039 
1040         while !slice.is_empty() {
1041             if slice.len() >= guest_period_in_bytes {
1042                 capture_resampler_buffer.convert_and_add(&slice[..guest_period_in_bytes]);
1043                 slice = &mut slice[guest_period_in_bytes..];
1044             } else {
1045                 capture_resampler_buffer.convert_and_add(slice);
1046                 slice = &mut [];
1047             }
1048         }
1049         Ok(())
1050     }
1051 
1052     /// Set up a stream that write 0's and set up a listener for new audio capture devices.
1053     ///
1054     /// This call assumes that the last capture device has been disconnected and the
1055     /// `DeviceCapturer` no longer functions properly.
create_noop_capture_stream_with_device_notification( num_channels: usize, guest_bit_depth: SampleFormat, guest_frame_rate: u32, outgoing_buffer_size_in_frames: usize, ) -> Result<CapturerStream, CaptureError>1056     fn create_noop_capture_stream_with_device_notification(
1057         num_channels: usize,
1058         guest_bit_depth: SampleFormat,
1059         guest_frame_rate: u32,
1060         outgoing_buffer_size_in_frames: usize,
1061     ) -> Result<CapturerStream, CaptureError> {
1062         let is_device_available = Arc::new(AtomicBool::new(false));
1063         let noop_renderer = NoopCapturer {
1064             noop_capture_stream: NoopCaptureStream::new(
1065                 num_channels,
1066                 guest_bit_depth,
1067                 guest_frame_rate,
1068                 outgoing_buffer_size_in_frames,
1069             ),
1070             _device_notifier: DeviceNotifier::create_imm_device_notification(
1071                 is_device_available.clone(),
1072                 eCapture,
1073             )
1074             .map_err(CaptureError::WinAudioError)?,
1075             is_device_available,
1076         };
1077 
1078         Ok(CapturerStream::Noop(noop_renderer))
1079     }
1080 }
1081 
1082 // SAFETY: DeviceCapturerWrapper can be sent between threads safely
1083 unsafe impl Send for DeviceCapturerWrapper {}
1084 
1085 pub(crate) struct DeviceCapturer {
1086     audio_capture_client: ComPtr<IAudioCaptureClient>,
1087     _audio_client: ComPtr<IAudioClient>,
1088     win_buffer: Vec<u8>,
1089     pub audio_shared_format: AudioSharedFormat,
1090     _ready_to_write_event: Event,
1091     async_ready_to_write_event: Option<Box<dyn EventAsyncWrapper>>,
1092     last_buffer_flags: u32,
1093 }
1094 
1095 impl DeviceCapturer {
new( num_channels: usize, guest_frame_rate: u32, outgoing_buffer_size_in_frames: usize, ex: Option<&dyn audio_streams::AudioStreamsExecutor>, ) -> Result<Self, CaptureError>1096     fn new(
1097         num_channels: usize,
1098         guest_frame_rate: u32,
1099         outgoing_buffer_size_in_frames: usize,
1100         ex: Option<&dyn audio_streams::AudioStreamsExecutor>,
1101     ) -> Result<Self, CaptureError> {
1102         if num_channels > 2 {
1103             return Err(CaptureError::WinAudioError(
1104                 WinAudioError::InvalidChannelCount(num_channels),
1105             ));
1106         }
1107 
1108         info!("Capture guest frame rate: {}", guest_frame_rate);
1109 
1110         let audio_client = create_audio_client(eCapture).map_err(CaptureError::WinAudioError)?;
1111 
1112         let format = get_valid_mix_format(&audio_client).map_err(CaptureError::WinAudioError)?;
1113 
1114         // SAFETY: `audio_client` is initialized
1115         let hr = unsafe {
1116             // Intializes the audio client by setting the buffer size in 100-nanoseconds and
1117             // specifying the format the audio bytes will be passed in as.
1118             // Setting `hnsBufferDuration` (in miilisecond units) to 0 will let the audio engine to
1119             // pick the size that will minimize latency.
1120             // `hnsPeriodicity` sets the device period and should always be 0 for shared mode.
1121             audio_client.Initialize(
1122                 AUDCLNT_SHAREMODE_SHARED,
1123                 AUDCLNT_STREAMFLAGS_EVENTCALLBACK
1124                     | AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM
1125                     | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY
1126                     | AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED
1127                     | AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED,
1128                 0, /* hnsBufferDuration */
1129                 0, /* hnsPeriodicity */
1130                 format.as_ptr(),
1131                 null_mut(),
1132             )
1133         };
1134         check_hresult!(
1135             hr,
1136             WinAudioError::from(hr),
1137             "Audio Client Initialize() failed."
1138         )
1139         .map_err(CaptureError::WinAudioError)?;
1140 
1141         let (_ready_to_write_event, async_ready_to_write_event) =
1142             create_and_set_audio_client_event(&audio_client, &ex)
1143                 .map_err(CaptureError::WinAudioError)?;
1144 
1145         let audio_capture_client = Self::create_audio_capture_client(&audio_client)?;
1146 
1147         let shared_audio_engine_period_in_frames =
1148             get_device_period_in_frames(&audio_client, &format);
1149 
1150         if outgoing_buffer_size_in_frames % shared_audio_engine_period_in_frames != 0 {
1151             warn!(
1152                 "Capture: Guest period size: `{}` not divisible by shared audio engine period size: `{}`. \
1153                  Audio glitches may occur if sample rate conversion isn't on.",
1154                 outgoing_buffer_size_in_frames, shared_audio_engine_period_in_frames
1155             );
1156         }
1157 
1158         check_endpoint_buffer_size(&audio_client, shared_audio_engine_period_in_frames)
1159             .map_err(CaptureError::WinAudioError)?;
1160 
1161         // SAFETY: `audio_client` is initialized
1162         let hr = unsafe {
1163             // Starts the audio stream for capture
1164             audio_client.Start()
1165         };
1166         check_hresult!(
1167             hr,
1168             WinAudioError::from(hr),
1169             "Audio Render Client Start() failed."
1170         )
1171         .map_err(CaptureError::WinAudioError)?;
1172 
1173         Ok(Self {
1174             audio_capture_client,
1175             _audio_client: audio_client,
1176             win_buffer: Vec::new(),
1177             audio_shared_format: format
1178                 .create_audio_shared_format(shared_audio_engine_period_in_frames),
1179             _ready_to_write_event,
1180             async_ready_to_write_event,
1181             last_buffer_flags: 0,
1182         })
1183     }
1184 
create_audio_capture_client( audio_client: &IAudioClient, ) -> Result<ComPtr<IAudioCaptureClient>, CaptureError>1185     fn create_audio_capture_client(
1186         audio_client: &IAudioClient,
1187     ) -> Result<ComPtr<IAudioCaptureClient>, CaptureError> {
1188         let mut audio_capture_client: *mut c_void = null_mut();
1189 
1190         // SAFETY: `audio_client` is initialized
1191         let hr = unsafe {
1192             audio_client.GetService(
1193                 &IID_IAudioCaptureClient as *const GUID,
1194                 &mut audio_capture_client,
1195             )
1196         };
1197         check_hresult!(
1198             hr,
1199             WinAudioError::from(hr),
1200             "Audio Client GetService() failed."
1201         )
1202         .map_err(CaptureError::WinAudioError)?;
1203 
1204         // SAFETY: `audio_capture_client` is guaranteed to be initialized
1205         unsafe {
1206             Ok(ComPtr::from_raw(
1207                 audio_capture_client as *mut IAudioCaptureClient,
1208             ))
1209         }
1210     }
1211 
1212     // Returns a wrapper around the WASAPI buffer
async_next_win_buffer(&mut self) -> Result<(), CaptureError>1213     async fn async_next_win_buffer(&mut self) -> Result<(), CaptureError> {
1214         self.win_buffer.clear();
1215 
1216         // We will wait for windows to tell us when it is ready to take in the next set of
1217         // audio samples from the guest
1218         let async_ready_to_write_event =
1219             self.async_ready_to_write_event
1220                 .as_ref()
1221                 .ok_or(CaptureError::WinAudioError(
1222                     WinAudioError::MissingEventAsync,
1223                 ))?;
1224 
1225         // Unlike the sync version, there is no timeout anymore. So we could get stuck here,
1226         // although it is unlikely.
1227         async_ready_to_write_event.wait().await.map_err(|e| {
1228             CaptureError::WinAudioError(WinAudioError::AsyncError(
1229                 e,
1230                 "Failed to wait for async event to get next capture buffer.".to_string(),
1231             ))
1232         })?;
1233 
1234         // TODO(b/253506231): Might need to check for a full period of bytes before returning from
1235         // this function on AMD. For playback, there was a bug caused from us not doing this.
1236 
1237         self.get_buffer()?;
1238 
1239         Ok(())
1240     }
1241 
1242     // Drain the capture buffer and store the bytes in `win_buffer`.
get_buffer(&mut self) -> Result<(), CaptureError>1243     fn get_buffer(&mut self) -> Result<(), CaptureError> {
1244         // SAFETY:
1245         //   - `GetBuffer` only take output parameters that are all defined in this unsafe block.
1246         //   - `ReleaseBuffer` is called after the audio bytes are copied to `win_buffer`, so the
1247         //     audio bytes from `GetBuffer` will remain valid long enough.
1248         unsafe {
1249             let mut packet_length = self.next_packet_size()?;
1250 
1251             // The Windows documentation recommends calling `GetBuffer` until `GetNextPacketSize`
1252             // returns 0.
1253             while packet_length != 0 {
1254                 let mut buffer = std::ptr::null_mut();
1255                 let mut num_frames_available = 0;
1256                 let mut flags = 0;
1257 
1258                 // Position variables unused for now, but may be useful for debugging.
1259                 let mut device_position = 0;
1260                 let mut qpc_position = 0;
1261                 let hr = self.audio_capture_client.GetBuffer(
1262                     &mut buffer,
1263                     &mut num_frames_available,
1264                     &mut flags,
1265                     &mut device_position,
1266                     &mut qpc_position,
1267                 );
1268                 check_hresult!(
1269                     hr,
1270                     WinAudioError::from(hr),
1271                     "Audio Capture Client GetBuffer failed."
1272                 )
1273                 .map_err(CaptureError::WinAudioError)?;
1274 
1275                 let buffer_slice = std::slice::from_raw_parts_mut(
1276                     buffer,
1277                     num_frames_available as usize
1278                         * self.audio_shared_format.channels
1279                         * self.audio_shared_format.bit_depth
1280                         / 8,
1281                 );
1282 
1283                 if flags != 0 && self.last_buffer_flags != flags {
1284                     warn!(
1285                         "Audio Cature Client GetBuffer flags were not 0: {}",
1286                         Self::get_buffer_flags_to_string(flags)
1287                     );
1288 
1289                     self.last_buffer_flags = flags;
1290                 }
1291 
1292                 if flags & AUDCLNT_BUFFERFLAGS_SILENT == 0 {
1293                     self.win_buffer.extend_from_slice(buffer_slice);
1294                 } else {
1295                     self.win_buffer
1296                         .resize(self.win_buffer.len() + buffer_slice.len(), 0);
1297                 }
1298 
1299                 let hr = self
1300                     .audio_capture_client
1301                     .ReleaseBuffer(num_frames_available);
1302                 check_hresult!(
1303                     hr,
1304                     WinAudioError::from(hr),
1305                     "Audio Capture Client ReleaseBuffer() failed"
1306                 )
1307                 .map_err(CaptureError::WinAudioError)?;
1308 
1309                 packet_length = self.next_packet_size()?;
1310             }
1311         }
1312 
1313         Ok(())
1314     }
1315 
next_packet_size(&self) -> Result<u32, CaptureError>1316     fn next_packet_size(&self) -> Result<u32, CaptureError> {
1317         let mut len = 0;
1318         // SAFETY: `len` is a valid u32.
1319         let hr = unsafe { self.audio_capture_client.GetNextPacketSize(&mut len) };
1320         check_hresult!(
1321             hr,
1322             WinAudioError::from(hr),
1323             "Capture GetNextPacketSize() failed."
1324         )
1325         .map_err(CaptureError::WinAudioError)?;
1326         Ok(len)
1327     }
1328 
get_buffer_flags_to_string(flags: u32) -> String1329     fn get_buffer_flags_to_string(flags: u32) -> String {
1330         let mut result = Vec::new();
1331         if flags & AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY != 0 {
1332             result.push("AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY".to_string());
1333         }
1334         if flags & AUDCLNT_BUFFERFLAGS_SILENT != 0 {
1335             result.push("AUDCLNT_BUFFERFLAGS_SILENT".to_string());
1336         }
1337         if flags & AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR != 0 {
1338             result.push("AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR".to_string());
1339         }
1340         result.join(" | ")
1341     }
1342 }
1343 
1344 // SAFETY: DeviceCapturer can be sent between threads safely
1345 unsafe impl Send for DeviceCapturer {}
1346 
1347 // Create the `IAudioClient` which is used to create `IAudioRenderClient`, which is used for
1348 // audio playback, or used to create `IAudioCaptureClient`, which is used for audio capture.
create_audio_client(dataflow: EDataFlow) -> Result<ComPtr<IAudioClient>, WinAudioError>1349 fn create_audio_client(dataflow: EDataFlow) -> Result<ComPtr<IAudioClient>, WinAudioError> {
1350     let mut device_enumerator: *mut c_void = null_mut();
1351 
1352     // Creates a device enumerator in order to select our default audio device.
1353     //
1354     // SAFETY: Only `device_enumerator` is being modified and we own it.
1355     let hr = unsafe {
1356         CoCreateInstance(
1357             &CLSID_MMDeviceEnumerator as REFCLSID,
1358             null_mut(),
1359             CLSCTX_ALL,
1360             &IMMDeviceEnumerator::uuidof(),
1361             &mut device_enumerator,
1362         )
1363     };
1364     check_hresult!(
1365         hr,
1366         WinAudioError::GetDeviceEnumeratorError(hr),
1367         "Win audio create client CoCreateInstance() failed."
1368     )?;
1369 
1370     let device_enumerator =
1371         // SAFETY: `device_enumerator` is guaranteed to be initialized
1372         unsafe { ComPtr::from_raw(device_enumerator as *mut IMMDeviceEnumerator) };
1373 
1374     let mut device: *mut IMMDevice = null_mut();
1375     // SAFETY: `device_enumerator` is guaranteed to be initialized otherwise this method
1376     // would've exited
1377     let hr = unsafe { device_enumerator.GetDefaultAudioEndpoint(dataflow, eConsole, &mut device) };
1378     check_hresult!(
1379         hr,
1380         WinAudioError::MissingDeviceError(hr),
1381         "Device Enumerator GetDefaultAudioEndpoint() failed."
1382     )?;
1383 
1384     // SAFETY: `device` is guaranteed to be initialized
1385     let device = unsafe { ComPtr::from_raw(device) };
1386     print_device_info(&device)?;
1387 
1388     let is_render = if dataflow == eRender { true } else { false };
1389 
1390     // Call Windows API functions to get the `async_op` which will be used to retrieve the
1391     // AudioClient. More details above function definition.
1392     let async_op = enable_auto_stream_routing_and_wait(is_render)?;
1393 
1394     let mut factory: *mut IUnknown = null_mut();
1395 
1396     // SAFETY: `async_op` should be initialized at this point.
1397     let activate_result_hr = unsafe {
1398         let mut activate_result_hr = 0;
1399         let hr = (*async_op).GetActivateResult(&mut activate_result_hr, &mut factory);
1400 
1401         check_hresult!(
1402             hr,
1403             WinAudioError::GetActivateResultError(hr),
1404             "GetActivateResult failed. Cannot retrieve factory to create the Audio Client."
1405         )?;
1406 
1407         activate_result_hr
1408     };
1409     check_hresult!(
1410         activate_result_hr,
1411         WinAudioError::ActivateResultRunningError(activate_result_hr),
1412         "activateResult is an error. Cannot retrieve factory to create the Audio Client."
1413     )?;
1414 
1415     // SAFETY: `factory` is guaranteed to be initialized.
1416     let factory = unsafe { ComPtr::from_raw(factory) };
1417 
1418     factory.cast().map_err(WinAudioError::from)
1419 }
1420 
1421 // Enables automatic audio device routing (only will work for Windows 10, version 1607+).
1422 // This will return IActivateAudioInterfaceAsyncOperation that can be used to retrive the
1423 // AudioClient.
1424 //
1425 // This function will pretty much works as follows:
1426 // 1. Create the parameters to pass into `ActivateAudioInterfaceAsync`
1427 // 2. Call `ActivateAudioInterfaceAsync` which will run asynchrnously and will call a callback when
1428 //    completed.
1429 // 3. Wait on an event that will be notified when that callback is triggered.
1430 // 4. Return an IActivateAudioInterfaceAsyncOperation which can be used to retrived the AudioClient.
enable_auto_stream_routing_and_wait( is_render: bool, ) -> Result<ComPtr<IActivateAudioInterfaceAsyncOperation>, WinAudioError>1431 fn enable_auto_stream_routing_and_wait(
1432     is_render: bool,
1433 ) -> Result<ComPtr<IActivateAudioInterfaceAsyncOperation>, WinAudioError> {
1434     // Event that fires when callback is called.
1435     let activate_audio_interface_complete_event =
1436         Event::new_auto_reset().map_err(WinAudioError::CreateActivateAudioEventError)?;
1437 
1438     let cloned_activate_event = activate_audio_interface_complete_event
1439         .try_clone()
1440         .map_err(WinAudioError::CloneEvent)?;
1441 
1442     // Create the callback that is called when `ActivateAudioInterfaceAsync` is finished.
1443     // The field `parent` is irrelevant and is only there to fill in the struct so that
1444     // this code will run. `ActivateCompleted` is the callback.
1445     let completion_handler =
1446         WinAudioActivateAudioInterfaceCompletionHandler::create_com_ptr(cloned_activate_event);
1447 
1448     // Retrieve GUID that represents the default audio device.
1449     let mut audio_direction_guid_string: *mut u16 = std::ptr::null_mut();
1450 
1451     // This will get the GUID that represents the device we want `ActivateAudioInterfaceAsync`
1452     // to activate. `DEVINTERFACE_AUDIO_RENDER` represents the users default audio render device, so
1453     // as a result Windows will always route sound to the default device. Likewise,
1454     // `DEVINTERFACE_AUDIO_CAPTURE` represents the default audio capture device.
1455     //
1456     // SAFETY: We own `audio_direction_guid_string`.
1457     let hr = unsafe {
1458         if is_render {
1459             StringFromIID(
1460                 &DEVINTERFACE_AUDIO_RENDER as *const winapi::shared::guiddef::GUID,
1461                 &mut audio_direction_guid_string,
1462             )
1463         } else {
1464             StringFromIID(
1465                 &DEVINTERFACE_AUDIO_CAPTURE as *const winapi::shared::guiddef::GUID,
1466                 &mut audio_direction_guid_string,
1467             )
1468         }
1469     };
1470     check_hresult!(
1471         hr,
1472         WinAudioError::from(hr),
1473         format!(
1474             "Failed to retrive DEVINTERFACE_AUDIO GUID for {}",
1475             if is_render { "rendering" } else { "capturing" }
1476         )
1477     )?;
1478 
1479     let mut async_op: *mut IActivateAudioInterfaceAsyncOperation = std::ptr::null_mut();
1480 
1481     // This will asynchronously run and when completed, it will trigger the
1482     // `IActivateINterfaceCompletetionHandler` callback.
1483     // The callback is where the AudioClient can be retrived. This would be easier in C/C++,
1484     // but since in rust the callback is an extern function, it would be difficult to get the
1485     // `IAudioClient` from the callback to the scope here, so we use an
1486     // event to wait for the callback.
1487     //
1488     // SAFETY: We own async_op and the completion handler.
1489     let hr = unsafe {
1490         ActivateAudioInterfaceAsync(
1491             audio_direction_guid_string,
1492             &IAudioClient::uuidof(),
1493             /* activateParams= */ std::ptr::null_mut(),
1494             completion_handler.as_raw(),
1495             &mut async_op,
1496         )
1497     };
1498 
1499     // We want to free memory before error checking for `ActivateAudioInterfaceAsync` to prevent
1500     // a memory leak.
1501     //
1502     // SAFETY: `audio_direction_guid_string` should have valid memory
1503     // and we are freeing up memory here.
1504     unsafe {
1505         CoTaskMemFree(audio_direction_guid_string as *mut std::ffi::c_void);
1506     }
1507 
1508     check_hresult!(
1509         hr,
1510         WinAudioError::from(hr),
1511         "`Activate AudioInterfaceAsync failed."
1512     )?;
1513 
1514     // Wait for `ActivateAudioInterfaceAsync` to finish. `ActivateAudioInterfaceAsync` should
1515     // never hang, but added a long timeout just incase.
1516     match activate_audio_interface_complete_event.wait_timeout(ACTIVATE_AUDIO_EVENT_TIMEOUT) {
1517         Ok(event_result) => match event_result {
1518             EventWaitResult::Signaled => {}
1519             EventWaitResult::TimedOut => {
1520                 return Err(WinAudioError::ActivateAudioEventTimeoutError);
1521             }
1522         },
1523         Err(e) => {
1524             return Err(WinAudioError::ActivateAudioEventError(e));
1525         }
1526     }
1527 
1528     // SAFETY: We own `async_op` and it shouldn't be null if the activate audio event
1529     // fired.
1530     unsafe { Ok(ComPtr::from_raw(async_op)) }
1531 }
1532 
1533 /// Wrapper for dropping `PROPVARIANT` when out of scope.
1534 ///
1535 /// Safe when `prop_variant` is set to a valid `PROPVARIANT`
1536 struct SafePropVariant {
1537     prop_variant: PROPVARIANT,
1538 }
1539 
1540 impl Drop for SafePropVariant {
drop(&mut self)1541     fn drop(&mut self) {
1542         // SAFETY: `prop_variant` is set to a valid `PROPVARIANT` and won't be dropped elsewhere.
1543         unsafe {
1544             PropVariantClear(&mut self.prop_variant);
1545         }
1546     }
1547 }
1548 
1549 // Prints the friendly name for audio `device` to the log.
1550 // Safe when `device` is guaranteed to be successfully initialized.
print_device_info(device: &IMMDevice) -> Result<(), WinAudioError>1551 fn print_device_info(device: &IMMDevice) -> Result<(), WinAudioError> {
1552     let mut props: *mut IPropertyStore = null_mut();
1553     // SAFETY: `device` is guaranteed to be initialized
1554     let hr = unsafe { device.OpenPropertyStore(STGM_READ, &mut props) };
1555     check_hresult!(
1556         hr,
1557         WinAudioError::from(hr),
1558         "Win audio OpenPropertyStore failed."
1559     )?;
1560 
1561     // SAFETY: `props` is guaranteed to be initialized
1562     let props = unsafe { ComPtr::from_raw(props) };
1563 
1564     let mut prop_variant: PROPVARIANT = Default::default();
1565     // SAFETY: `props` is guaranteed to be initialized
1566     let hr = unsafe { props.GetValue(&PKEY_Device_FriendlyName, &mut prop_variant) };
1567     check_hresult!(
1568         hr,
1569         WinAudioError::from(hr),
1570         "Win audio property store GetValue failed."
1571     )?;
1572     let safe_prop_variant = SafePropVariant { prop_variant };
1573 
1574     // SAFETY: `val` was populated by a successful GetValue call that returns a pwszVal
1575     if unsafe { safe_prop_variant.prop_variant.data.pwszVal().is_null() } {
1576         warn!("Win audio property store GetValue returned a null string");
1577         return Err(WinAudioError::GenericError);
1578     }
1579     // SAFETY: `val` was populated by a successful GetValue call that returned a non-null
1580     // null-terminated pwszVal
1581     let device_name = unsafe {
1582         win_util::from_ptr_win32_wide_string(*(safe_prop_variant.prop_variant).data.pwszVal())
1583     };
1584     info!("Creating audio client: {}", device_name);
1585 
1586     Ok(())
1587 }
1588 
1589 // TODO(b/259476096): Once Ac97 is deprecated, we won't need to return a regular `Event`.
create_and_set_audio_client_event( audio_client: &IAudioClient, ex: &Option<&dyn audio_streams::AudioStreamsExecutor>, ) -> Result<(Event, Option<Box<dyn EventAsyncWrapper>>), WinAudioError>1590 fn create_and_set_audio_client_event(
1591     audio_client: &IAudioClient,
1592     ex: &Option<&dyn audio_streams::AudioStreamsExecutor>,
1593 ) -> Result<(Event, Option<Box<dyn EventAsyncWrapper>>), WinAudioError> {
1594     let ready_event = Event::new_auto_reset().unwrap();
1595     // SAFETY: `ready_event` will be initialized and also it will have the same
1596     // lifetime as `audio_client` because they are owned by DeviceRenderer or DeviceCapturer on
1597     // return.
1598     let hr = unsafe { audio_client.SetEventHandle(ready_event.as_raw_descriptor()) };
1599     check_hresult!(
1600         hr,
1601         WinAudioError::SetEventHandleError(hr),
1602         "SetEventHandle() failed."
1603     )?;
1604 
1605     let async_ready_event = if let Some(ex) = ex {
1606         // SAFETY:
1607         // Unsafe if `ready_event` and `async_ready_event` have different
1608         // lifetimes because both can close the underlying `RawDescriptor`. However, both
1609         // will be stored in the `DeviceRenderer` or `DeviceCapturer` fields, so this should be
1610         // safe.
1611         Some(unsafe {
1612             ex.async_event(ready_event.as_raw_descriptor())
1613                 .map_err(|e| {
1614                     WinAudioError::AsyncError(e, "Failed to create async event".to_string())
1615                 })?
1616         })
1617     } else {
1618         None
1619     };
1620     Ok((ready_event, async_ready_event))
1621 }
1622 
get_device_period_in_frames(audio_client: &IAudioClient, format: &WaveAudioFormat) -> usize1623 fn get_device_period_in_frames(audio_client: &IAudioClient, format: &WaveAudioFormat) -> usize {
1624     let mut shared_default_size_in_100nanoseconds: i64 = 0;
1625     let mut exclusive_min: i64 = 0;
1626     // SAFETY: `GetDevicePeriod` is taking in intialized valid i64's on the stack created above.
1627     unsafe {
1628         audio_client.GetDevicePeriod(
1629             &mut shared_default_size_in_100nanoseconds,
1630             &mut exclusive_min,
1631         );
1632     };
1633 
1634     format.get_shared_audio_engine_period_in_frames(shared_default_size_in_100nanoseconds as f64)
1635 }
1636 
check_endpoint_buffer_size( audio_client: &IAudioClient, shared_audio_engine_period_in_frames: usize, ) -> Result<u32, WinAudioError>1637 fn check_endpoint_buffer_size(
1638     audio_client: &IAudioClient,
1639     shared_audio_engine_period_in_frames: usize,
1640 ) -> Result<u32, WinAudioError> {
1641     let mut audio_client_buffer_frame_count: u32 = 0;
1642     // SAFETY: audio_client_buffer_frame_count is created above.
1643     let hr = unsafe { audio_client.GetBufferSize(&mut audio_client_buffer_frame_count) };
1644     check_hresult!(
1645         hr,
1646         WinAudioError::GetBufferSizeError(hr),
1647         "Audio Client GetBufferSize() failed."
1648     )?;
1649 
1650     if audio_client_buffer_frame_count < shared_audio_engine_period_in_frames as u32 {
1651         warn!(
1652             "The Windows audio engine period size in frames: {} /
1653             is bigger than the Audio Client's buffer size in frames: {}",
1654             shared_audio_engine_period_in_frames, audio_client_buffer_frame_count
1655         );
1656         return Err(WinAudioError::InvalidIncomingBufferSize);
1657     }
1658     Ok(audio_client_buffer_frame_count)
1659 }
1660 
1661 // TODO(b/253509368): Rename error so it is more generic for rendering and capturing.
1662 #[derive(Debug, ThisError)]
1663 pub enum WinAudioError {
1664     #[error("An unknown error has occurred.")]
1665     Unknown,
1666     /// The audio device was unplugged or became unavailable.
1667     #[error("win audio device invalidated")]
1668     DeviceInvalidated,
1669     /// A Windows API error occurred.
1670     /// "unknown win audio error HResult: {}, error code: {}"
1671     #[error("unknown win audio error HResult: {0}, error code: {1}")]
1672     WindowsError(i32, Error),
1673     #[error("buffer pointer is null")]
1674     InvalidBuffer,
1675     #[error("playback buffer error: {0}")]
1676     PlaybackBuffer(PlaybackBufferError),
1677     #[error("Incoming buffer size invalid")]
1678     InvalidIncomingBufferSize,
1679     #[error("Failed to wait for Activate Audio Event callback: {0}")]
1680     ActivateAudioEventError(Error),
1681     #[error("Failed to create Activate Audio Event: {0}")]
1682     CreateActivateAudioEventError(Error),
1683     #[error("Timed out waiting for Activate Audio Event callback.")]
1684     ActivateAudioEventTimeoutError,
1685     #[error("Something went wrong in windows audio.")]
1686     GenericError,
1687     #[error("Invalid guest channel count {0} is > than 2")]
1688     InvalidChannelCount(usize),
1689     #[error("Async related error: {0}: {1}")]
1690     AsyncError(std::io::Error, String),
1691     #[error("Ready to read async event was not set during win_audio initialization.")]
1692     MissingEventAsync,
1693     #[error("Failed to clone an event: {0}")]
1694     CloneEvent(Error),
1695     #[error("Failed to retrieve device enumerator. HResult: {0}")]
1696     GetDeviceEnumeratorError(i32),
1697     #[error("No audio device available. HResult: {0}")]
1698     MissingDeviceError(i32),
1699     #[error("Failed to run GetActivateResult. HResult: {0}")]
1700     GetActivateResultError(i32),
1701     #[error("Error while running GetActivateResult. HResult: {0}")]
1702     ActivateResultRunningError(i32),
1703     #[error("The AudioClient failed to initialize. HResult: {0}")]
1704     AudioClientInitializationError(i32),
1705     #[error("The AudioClient failed to set the event handle. HResult: {0}")]
1706     SetEventHandleError(i32),
1707     #[error("Failed to retrieve the rendering client. HResult: {0}")]
1708     GetRenderClientError(i32),
1709     #[error("The AudioClient failed to get the buffer size. HResult: {0}")]
1710     GetBufferSizeError(i32),
1711     #[error("The AudioClient failed to start. HResult: {0}")]
1712     AudioClientStartError(i32),
1713     #[error("GetCurrentPadding failed. This could mean the user disconnected their last audio device. HResult: {0}")]
1714     GetCurrentPaddingError(i32),
1715     #[error("GetBuffer failed during playback. HResult: {0}")]
1716     GetBufferError(i32),
1717     #[error("Failed to register IMMNotificationClient. HResult: {0}")]
1718     RegisterEndpointNotifError(i32),
1719     #[error("ReleaseBuffer failed. HResult: {0}")]
1720     ReleaseBufferError(i32),
1721 }
1722 
1723 impl From<&WinAudioError> for i64 {
from(error: &WinAudioError) -> i641724     fn from(error: &WinAudioError) -> i64 {
1725         let (err_type, hr) = match error {
1726             WinAudioError::Unknown => (0, 0),
1727             WinAudioError::GetDeviceEnumeratorError(hr) => (1, *hr),
1728             WinAudioError::MissingDeviceError(hr) => (2, *hr),
1729             WinAudioError::GetActivateResultError(hr) => (3, *hr),
1730             WinAudioError::ActivateResultRunningError(hr) => (4, *hr),
1731             WinAudioError::AudioClientInitializationError(hr) => (5, *hr),
1732             WinAudioError::SetEventHandleError(hr) => (6, *hr),
1733             WinAudioError::GetRenderClientError(hr) => (7, *hr),
1734             WinAudioError::GetBufferSizeError(hr) => (8, *hr),
1735             WinAudioError::AudioClientStartError(hr) => (9, *hr),
1736             WinAudioError::DeviceInvalidated => (10, 0),
1737             WinAudioError::WindowsError(hr, _) => (11, *hr),
1738             WinAudioError::InvalidBuffer => (12, 0),
1739             WinAudioError::PlaybackBuffer(_) => (13, 0),
1740             WinAudioError::InvalidIncomingBufferSize => (14, 0),
1741             WinAudioError::ActivateAudioEventError(_) => (15, 0),
1742             WinAudioError::CreateActivateAudioEventError(_) => (16, 0),
1743             WinAudioError::ActivateAudioEventTimeoutError => (17, 0),
1744             WinAudioError::GenericError => (18, 0),
1745             WinAudioError::InvalidChannelCount(_) => (19, 0),
1746             WinAudioError::AsyncError(_, _) => (20, 0),
1747             WinAudioError::MissingEventAsync => (21, 0),
1748             WinAudioError::CloneEvent(_) => (22, 0),
1749             WinAudioError::GetCurrentPaddingError(hr) => (23, *hr),
1750             WinAudioError::GetBufferError(hr) => (24, *hr),
1751             WinAudioError::RegisterEndpointNotifError(hr) => (25, *hr),
1752             WinAudioError::ReleaseBufferError(hr) => (26, *hr),
1753         };
1754         ((err_type as u64) << 32 | ((hr as u32) as u64)) as i64
1755     }
1756 }
1757 
1758 impl From<i32> for WinAudioError {
from(winapi_error_code: i32) -> Self1759     fn from(winapi_error_code: i32) -> Self {
1760         match winapi_error_code {
1761             AUDCLNT_E_DEVICE_INVALIDATED => Self::DeviceInvalidated,
1762             _ => Self::WindowsError(winapi_error_code, Error::last()),
1763         }
1764     }
1765 }
1766 
1767 #[derive(Debug, ThisError)]
1768 pub enum RenderError {
1769     #[error("RenderError: {0}")]
1770     WinAudioError(WinAudioError),
1771     #[error("AudioStream RenderBufferError error: {0}")]
1772     PlaybackBuffer(PlaybackBufferError),
1773     #[error("buffer pointer is null")]
1774     InvalidBuffer,
1775 }
1776 
1777 #[derive(Debug, ThisError)]
1778 pub enum CaptureError {
1779     #[error("CaptureError: {0}")]
1780     WinAudioError(WinAudioError),
1781     #[error("AudioStream CaptureBufferError error: {0}")]
1782     CaptureBuffer(CaptureBufferError),
1783     #[error("CaptureResamplerBuffer has no samples available.")]
1784     ResamplerNoSamplesAvailable,
1785     #[error("CaptureResamplerBuffer is missing.")]
1786     ResamplerMissing,
1787 }
1788 
1789 // Unfortunately, Kokoro's VM tests will fail on `GetDefaultAudioEndpoint` most likely because there
1790 // are no audio endpoints on the VMs running the test. These tests can be ran on a windows machine
1791 // with an audio device though.
1792 //
1793 // Thus these test are ignored, but are good for local testing. To run, just use the command:
1794 //
1795 //   $: cargo test -p win_audio win_audio_impl::tests:: -- --ignored
1796 //
1797 // Also, if a STATUS_DLL_NOT_FOUND exception happens, this is because the r8brain.dll can't be
1798 // be found. Just put it in the appropriate spot in the `target` directory.
1799 #[cfg(test)]
1800 mod tests {
1801     use std::thread;
1802 
1803     use cros_async::Executor;
1804     use metrics::sys::WaveFormatDetails;
1805     use winapi::shared::ksmedia::KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
1806     use winapi::shared::mmreg::WAVEFORMATEX;
1807     use winapi::shared::mmreg::WAVEFORMATEXTENSIBLE;
1808     use winapi::shared::mmreg::WAVE_FORMAT_EXTENSIBLE;
1809     use winapi::shared::winerror::S_OK;
1810 
1811     use super::*;
1812     // These tests needs to be ran serially because there is a chance that two different tests
1813     // running on different threads could open the same event named
1814     // ACTIVATE_AUDIO_INTERFACE_COMPLETION_EVENT.
1815     // So the first test thread could trigger it correctly, but the second test thread could open
1816     // the same triggered event even though the `ActivateAudioInterfaceAsync` operation hasn't
1817     // completed, thus causing an error.
1818     //
1819     // TODO(b/217768491): Randomizing events should resolve the need for serialized tests.
1820     static SERIALIZE_LOCK: Mutex<()> = Mutex::new(());
1821 
1822     struct SafeCoInit;
1823     impl SafeCoInit {
new_coinitialize() -> Self1824         fn new_coinitialize() -> Self {
1825             // SAFETY: We pass valid parameters to CoInitializeEx.
1826             unsafe {
1827                 CoInitializeEx(null_mut(), COINIT_APARTMENTTHREADED);
1828             }
1829             SafeCoInit {}
1830         }
1831     }
1832 
1833     impl Drop for SafeCoInit {
drop(&mut self)1834         fn drop(&mut self) {
1835             // SAFETY: We initialized COM, so it is safe to uninitialize it here.
1836             unsafe {
1837                 CoUninitialize();
1838             }
1839         }
1840     }
1841 
1842     #[test]
test_win_audio_error_to_descriptor_for_no_device()1843     fn test_win_audio_error_to_descriptor_for_no_device() {
1844         let err = WinAudioError::MissingDeviceError(-2147023728);
1845         let result: i64 = (&err).into();
1846 
1847         // 2 << 32 | (-2147023728)
1848         assert_eq!(result, 10737878160);
1849     }
1850 
1851     #[test]
test_win_audio_error_to_descriptor_for_failed_initialization()1852     fn test_win_audio_error_to_descriptor_for_failed_initialization() {
1853         let err = WinAudioError::AudioClientInitializationError(-2004287484);
1854         let result: i64 = (&err).into();
1855 
1856         // 5 << 32 | (-2004287484)
1857         assert_eq!(result, 23765516292);
1858     }
1859 
1860     #[test]
test_win_audio_error_to_descriptor_for_getcurrentpadding_error()1861     fn test_win_audio_error_to_descriptor_for_getcurrentpadding_error() {
1862         let err = WinAudioError::GetCurrentPaddingError(-2147023728);
1863         let result: i64 = (&err).into();
1864 
1865         // 23 << 32 | (-2004287484)
1866         assert_eq!(result, 100932191376);
1867     }
1868 
1869     #[ignore]
1870     #[test]
test_create_win_audio_renderer_no_co_initliazed()1871     fn test_create_win_audio_renderer_no_co_initliazed() {
1872         let _shared = SERIALIZE_LOCK.lock();
1873         let win_audio_renderer = DeviceRenderer::new(2, 48000, 720, None);
1874         assert!(win_audio_renderer.is_err());
1875     }
1876 
1877     #[ignore]
1878     #[test]
test_create_win_audio_capturer_no_co_initliazed()1879     fn test_create_win_audio_capturer_no_co_initliazed() {
1880         let _shared = SERIALIZE_LOCK.lock();
1881         let win_audio_renderer = DeviceCapturer::new(2, 48000, 720, None);
1882         assert!(win_audio_renderer.is_err());
1883     }
1884 
1885     #[ignore]
1886     #[test]
test_create_win_audio_renderer()1887     fn test_create_win_audio_renderer() {
1888         let _shared = SERIALIZE_LOCK.lock();
1889         let _co_init = SafeCoInit::new_coinitialize();
1890         let win_audio_renderer_result = DeviceRenderer::new(2, 48000, 480, None);
1891         assert!(win_audio_renderer_result.is_ok());
1892         let win_audio_renderer = win_audio_renderer_result.unwrap();
1893         // This test is dependent on device format settings and machine. Ie. this will probably
1894         // fail on AMD since its period is normally 513 for 48kHz.
1895         assert_eq!(
1896             win_audio_renderer
1897                 .audio_shared_format
1898                 .shared_audio_engine_period_in_frames,
1899             480
1900         );
1901     }
1902 
1903     #[ignore]
1904     #[test]
test_create_win_audio_capturer()1905     fn test_create_win_audio_capturer() {
1906         let _shared = SERIALIZE_LOCK.lock();
1907         let _co_init = SafeCoInit::new_coinitialize();
1908         let win_audio_capturer_result = DeviceCapturer::new(2, 48000, 480, None);
1909         assert!(win_audio_capturer_result.is_ok());
1910         let win_audio_capturer = win_audio_capturer_result.unwrap();
1911         // This test is dependent on device format settings and machine. Ie. this will probably
1912         // fail on AMD since its period is normally 513 for 48kHz.
1913         assert_eq!(
1914             win_audio_capturer
1915                 .audio_shared_format
1916                 .shared_audio_engine_period_in_frames,
1917             480
1918         );
1919     }
1920 
1921     #[ignore]
1922     #[test]
test_create_playback_stream()1923     fn test_create_playback_stream() {
1924         let _shared = SERIALIZE_LOCK.lock();
1925         let mut win_audio: WinAudio = WinAudio::new().unwrap();
1926         let (_, mut stream_source) = win_audio
1927             .new_playback_stream(2, SampleFormat::S16LE, 48000, 480)
1928             .unwrap();
1929         let playback_buffer = stream_source.next_playback_buffer().unwrap();
1930 
1931         assert_eq!(playback_buffer.frame_capacity(), 480);
1932     }
1933 
1934     #[ignore]
1935     #[test]
1936     // If the guest buffer is too big, then
1937     // there is no way to copy audio samples over succiently.
test_guest_buffer_size_bigger_than_audio_render_client_buffer_size()1938     fn test_guest_buffer_size_bigger_than_audio_render_client_buffer_size() {
1939         let _shared = SERIALIZE_LOCK.lock();
1940         let win_audio_renderer = DeviceRenderer::new(2, 48000, 100000, None);
1941 
1942         assert!(win_audio_renderer.is_err());
1943     }
1944 
1945     #[ignore]
1946     #[test]
test_co_init_called_once_per_thread()1947     fn test_co_init_called_once_per_thread() {
1948         let _shared = SERIALIZE_LOCK.lock();
1949         // Call co init in a background thread
1950         let join_handle = thread::spawn(move || {
1951             assert_eq!(WinAudio::co_init_once_per_thread(), S_OK);
1952         });
1953 
1954         // Wait for thread to finish
1955         join_handle
1956             .join()
1957             .expect("Thread calling co_init_once_per_thread panicked");
1958 
1959         // Call co init twice on the main thread.
1960         assert_eq!(WinAudio::co_init_once_per_thread(), S_OK);
1961         // Without thread local once_only this should fail
1962         assert_eq!(WinAudio::co_init_once_per_thread(), S_SKIPPED_COINIT);
1963         // SAFETY: We initialized COM, so it is safe to uninitialize it here.
1964         unsafe {
1965             CoUninitialize();
1966         }
1967     }
1968 
1969     #[ignore]
1970     #[test]
test_device_renderer_wrapper_noop_stream_proper_set()1971     fn test_device_renderer_wrapper_noop_stream_proper_set() {
1972         let _shared = SERIALIZE_LOCK.lock();
1973         let _co_init = SafeCoInit::new_coinitialize();
1974 
1975         let ex = Executor::new().expect("Failed to create executor.");
1976         let mut renderer_wrapper =
1977             DeviceRendererWrapper::new(2, SampleFormat::S16LE, 48000, 480, Some(&ex)).unwrap();
1978         assert!(matches!(
1979             renderer_wrapper.renderer_stream,
1980             RendererStream::Device(_)
1981         ));
1982 
1983         renderer_wrapper.renderer_stream =
1984             DeviceRendererWrapper::create_noop_stream_with_device_notification(2, 48000, 480)
1985                 .unwrap();
1986         assert!(matches!(
1987             renderer_wrapper.renderer_stream,
1988             RendererStream::Noop(_)
1989         ));
1990     }
1991 
1992     #[ignore]
1993     #[test]
test_device_capturer_wrapper_noop_stream_proper_set()1994     fn test_device_capturer_wrapper_noop_stream_proper_set() {
1995         let _shared = SERIALIZE_LOCK.lock();
1996         let _co_init = SafeCoInit::new_coinitialize();
1997 
1998         let ex = Executor::new().expect("Failed to create executor.");
1999         let mut capturer_wrapper =
2000             DeviceCapturerWrapper::new(2, SampleFormat::S16LE, 48000, 480, Some(&ex)).unwrap();
2001         assert!(matches!(
2002             capturer_wrapper.capturer_stream,
2003             CapturerStream::Device(_)
2004         ));
2005 
2006         capturer_wrapper.capturer_stream =
2007             DeviceCapturerWrapper::create_noop_capture_stream_with_device_notification(
2008                 2,
2009                 SampleFormat::S16LE,
2010                 48000,
2011                 480,
2012             )
2013             .unwrap();
2014         assert!(matches!(
2015             capturer_wrapper.capturer_stream,
2016             CapturerStream::Noop(_)
2017         ));
2018     }
2019 
2020     // Test may be flakey because other tests will be creating an AudioClient. Putting all tests
2021     // in one so we can run this individually to prevent the flakiness. This test may fail
2022     // depending on your selected default audio device.
2023     #[ignore]
2024     #[test]
test_check_format_get_mix_format_success()2025     fn test_check_format_get_mix_format_success() {
2026         let _shared = SERIALIZE_LOCK.lock();
2027 
2028         let _co_init = SafeCoInit::new_coinitialize();
2029         let audio_client = create_audio_client(eRender).unwrap();
2030         let mut format_ptr: *mut WAVEFORMATEX = std::ptr::null_mut();
2031         // SAFETY: `&mut format_ptr` is valid.
2032         let _hr = unsafe { audio_client.GetMixFormat(&mut format_ptr) };
2033 
2034         // SAFETY: `format_ptr` is not a null pointer, since it is set by `GetMixFormat`.
2035         let format = unsafe { WaveAudioFormat::new(format_ptr) };
2036 
2037         // Test format from `GetMixFormat`. This should ALWAYS be valid.
2038         assert!(check_format(
2039             &audio_client,
2040             &format,
2041             WaveFormatDetails::default(),
2042             AudioFormatEventType::RequestOk,
2043         )
2044         .is_ok());
2045 
2046         let format = WAVEFORMATEXTENSIBLE {
2047             Format: WAVEFORMATEX {
2048                 wFormatTag: WAVE_FORMAT_EXTENSIBLE,
2049                 nChannels: 2,
2050                 nSamplesPerSec: 48000,
2051                 nAvgBytesPerSec: 8 * 48000,
2052                 nBlockAlign: 8,
2053                 wBitsPerSample: 32,
2054                 cbSize: 22,
2055             },
2056             Samples: 32,
2057             dwChannelMask: 3,
2058             SubFormat: KSDATAFORMAT_SUBTYPE_IEEE_FLOAT,
2059         };
2060 
2061         // SAFETY: `GetMixFormat` casts `WAVEFORMATEXTENSIBLE` into a `WAVEFORMATEX` like so.
2062         // Also this is casting from a bigger to a smaller struct, so it shouldn't be possible for
2063         // this contructor to access memory it shouldn't.
2064         let format = unsafe { WaveAudioFormat::new((&format) as *const _ as *mut WAVEFORMATEX) };
2065 
2066         // Test valid custom format.
2067         assert!(check_format(
2068             &audio_client,
2069             &format,
2070             WaveFormatDetails::default(),
2071             AudioFormatEventType::RequestOk,
2072         )
2073         .is_ok());
2074 
2075         let format = WAVEFORMATEXTENSIBLE {
2076             Format: WAVEFORMATEX {
2077                 wFormatTag: WAVE_FORMAT_EXTENSIBLE,
2078                 nChannels: 2,
2079                 nSamplesPerSec: 48000,
2080                 nAvgBytesPerSec: 8 * 48000,
2081                 nBlockAlign: 8,
2082                 wBitsPerSample: 3, // This value will cause failure, since bitdepth of 3
2083                 // doesn't make sense
2084                 cbSize: 22,
2085             },
2086             Samples: 32,
2087             dwChannelMask: 3,
2088             SubFormat: KSDATAFORMAT_SUBTYPE_IEEE_FLOAT,
2089         };
2090 
2091         // SAFETY: `GetMixFormat` casts `WAVEFORMATEXTENSIBLE` into a `WAVEFORMATEX` like so.
2092         // Also this is casting from a bigger to a smaller struct, so it shouldn't be possible for
2093         // this contructor to access memory it shouldn't.
2094         let format = unsafe { WaveAudioFormat::new((&format) as *const _ as *mut WAVEFORMATEX) };
2095 
2096         // Test invalid format
2097         assert!(check_format(
2098             &audio_client,
2099             &format,
2100             WaveFormatDetails::default(),
2101             AudioFormatEventType::RequestOk,
2102         )
2103         .is_err());
2104     }
2105 }
2106