audio: fix VirtioSnd re-activation
Hitherto the activation could succeed only once since take() function on
Option "Takes the value out of the option, leaving a None in its place."
Above resulted with crosvm crash in guest suspend/resume scenario when
the activate was called more than once (for the second time snd_data
and stream_source_generators was None).
To overcome above issue use clone for snd_data. For
stream_source_generator the clone can't be
easily used due to missing Clone support for stream_source_generators
embed data types (e.g.
369 | struct AudioBuffer<'a> {
370 | buffer: &'a mut [u8],
| ^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for
`&mut [u8]`
and some other). Therefore for stream_source_generator move
create_stream_source_generators from new() to activate.
BUG=b:246728970
TEST=Perform multiple suspend/resume s2idle cycle for borealis VM and
make sure that 1) crosvm doesn't crash anymore 2) audio from borealis VM
is still working after VM suspend/resume cycles.
Change-Id: I8b27042e4cc0e5efb1d92756ac3b71a5a744f705
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3904649
Commit-Queue: Norman Bintang <normanbt@chromium.org>
Reviewed-by: Norman Bintang <normanbt@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-by: Chih-Yang Hsia <paulhsia@chromium.org>
diff --git a/devices/src/virtio/snd/common_backend/mod.rs b/devices/src/virtio/snd/common_backend/mod.rs
index b13b54c..f9b0e0f 100644
--- a/devices/src/virtio/snd/common_backend/mod.rs
+++ b/devices/src/virtio/snd/common_backend/mod.rs
@@ -133,6 +133,7 @@
}
// Stores constant data
+#[derive(Clone)]
pub struct SndData {
jack_info: Vec<virtio_snd_jack_info>,
pcm_info: Vec<virtio_snd_pcm_info>,
@@ -167,13 +168,13 @@
pub struct VirtioSnd {
cfg: virtio_snd_config,
- snd_data: Option<SndData>,
+ snd_data: SndData,
avail_features: u64,
acked_features: u64,
queue_sizes: Box<[u16]>,
worker_threads: Vec<thread::JoinHandle<()>>,
kill_evt: Option<Event>,
- stream_source_generators: Option<Vec<Box<dyn StreamSourceGenerator>>>,
+ params: Parameters,
}
impl VirtioSnd {
@@ -181,17 +182,16 @@
let cfg = hardcoded_virtio_snd_config(¶ms);
let snd_data = hardcoded_snd_data(¶ms);
let avail_features = base_features;
- let stream_source_generators = create_stream_source_generators(¶ms, &snd_data);
Ok(VirtioSnd {
cfg,
- snd_data: Some(snd_data),
+ snd_data,
avail_features,
acked_features: 0,
queue_sizes: vec![MAX_VRING_LEN; MAX_QUEUE_NUM].into_boxed_slice(),
worker_threads: Vec::new(),
kill_evt: None,
- stream_source_generators: Some(stream_source_generators),
+ params,
})
}
}
@@ -371,12 +371,8 @@
};
self.kill_evt = Some(self_kill_evt);
- let snd_data = self.snd_data.take().expect("snd_data is none");
- let stream_source_generators = self
- .stream_source_generators
- .take()
- .expect("stream_source_generators is none");
-
+ let snd_data = self.snd_data.clone();
+ let stream_source_generators = create_stream_source_generators(&self.params, &snd_data);
let worker_result = thread::Builder::new()
.name("virtio_snd w".to_string())
.spawn(move || {